-[submodule "contrib/gilbert/media/gilbert/extjs"]
- path = contrib/gilbert/media/gilbert/extjs
+[submodule "philo/contrib/gilbert/static/gilbert/extjs"]
+ path = philo/contrib/gilbert/static/gilbert/extjs
url = git://git.ithinksw.org/extjs.git
-[submodule "contrib/gilbert/media/gilbert/fugue-icons"]
- path = contrib/gilbert/media/gilbert/fugue-icons
+[submodule "philo/contrib/gilbert/static/gilbert/fugue-icons"]
+ path = philo/contrib/gilbert/static/gilbert/fugue-icons
url = git://git.ithinksw.org/fugue-icons.git
Prerequisites:
* Python 2.5.4+ <http://www.python.org/>
- * Django 1.2+ <http://www.djangoproject.com/>
+ * Django 1.3+ <http://www.djangoproject.com/>
* django-mptt e734079+ <https://github.com/django-mptt/django-mptt/>
- * django-staticmedia 0.2+ <http://pypi.python.org/pypi/django-staticmedia/>
* (Optional) django-grappelli 2.0+ <http://code.google.com/p/django-grappelli/>
* (Optional) south 0.7.2+ <http://south.aeracode.org/>
* (Optional) recaptcha-django r6 <http://code.google.com/p/recaptcha-django/>
If you are using philo.contrib.gilbert, you will additionally need to complete the following steps:
-1. add 'django.core.context_processors.request' to settings.TEMPLATE_CONTEXT_PROCESSORS
\ No newline at end of file
+1. add 'django.core.context_processors.request' to settings.TEMPLATE_CONTEXT_PROCESSORS
Prerequisites:
* [Python 2.5.4+ <http://www.python.org>](http://www.python.org/)
- * [Django 1.2+ <http://www.djangoproject.com/>](http://www.djangoproject.com/)
+ * [Django 1.3+ <http://www.djangoproject.com/>](http://www.djangoproject.com/)
* [django-mptt e734079+ <https://github.com/django-mptt/django-mptt/>](https://github.com/django-mptt/django-mptt/)
- * [django-staticmedia 0.2+ <http://pypi.python.org/pypi/django-staticmedia/>](http://pypi.python.org/pypi/django-staticmedia/)
* (Optional) [django-grappelli 2.0+ <http://code.google.com/p/django-grappelli/>](http://code.google.com/p/django-grappelli/)
* (Optional) [south 0.7.2+ <http://south.aeracode.org/)](http://south.aeracode.org/)
* (Optional) [recaptcha-django r6 <http://code.google.com/p/recaptcha-django/>](http://code.google.com/p/recaptcha-django/)
If you are using philo.contrib.gilbert, you will additionally need to complete the following steps:
-1. add 'django.core.context_processors.request' to settings.TEMPLATE_CONTEXT_PROCESSORS
\ No newline at end of file
+1. add 'django.core.context_processors.request' to settings.TEMPLATE_CONTEXT_PROCESSORS
+++ /dev/null
-from philo.loaders.database import Loader
-
-
-_loader = Loader()
-
-
-def load_template_source(template_name, template_dirs=None):
- # For backwards compatibility
- import warnings
- warnings.warn(
- "'philo.load_template_source' is deprecated; use 'philo.loaders.database.Loader' instead.",
- PendingDeprecationWarning
- )
- return _loader.load_template_source(template_name, template_dirs)
-load_template_source.is_usable = True
+++ /dev/null
-Subproject commit e9397f91ede62d446aed37d23256e8938fc4c335
+++ /dev/null
-body{
- background:#666;
- color: #CCC;
- font-family: Helvetica, Arial, sans-serif;
- font-size: 12px;
-}
-
-/* kill the borders */
-.x-panel-tl, .x-toolbar-layout-ct, .x-panel-tbar, .x-toolbar, .x-panel-header, .x-panel-body,
-.x-window-tl,
-.x-window-body,
-.x-window-mc,
-.x-progress-bar,
-.x-tab-scrolling-top,
-.x-tab-panel-body,
-.x-tab-scroller-left, .x-tab-scroller-right,
-.x-tab-strip-spacer,
-.x-tab-panel-footer,
-.x-tab-strip,
-.x-list-header-inner em,
-.x-grid3-cell,.x-grid3-header, .x-grid3-header-offset,
-.x-date-prevday,
-.x-date-nextday,
-.x-tab-panel-header{
- border: 0 !important;
-}
-
-/* kill stuff */
-.x-shadow{
- display:none !important;
-}
-.x-tool, .x-date-mp .x-date-mp-ybtn .x-date-mp-prev, .x-date-mp .x-date-mp-ybtn .x-date-mp-next{
- background-image:url(images/tools.png);
-}
-
-
-/* @group Basic Window */
-
-/* window header */
- .x-window-tr, .x-panel-tr{
- padding-right: 16px;
- background: transparent url(images/windowlight/tr.png) no-repeat right top;
- }
- .x-window-tc, .x-panel-tc{
- background: transparent url(images/windowlight/tc.png) repeat-x right top;
- overflow:visible;
- }
- .x-window-tl, .x-panel-tl{
- padding-left: 16px;
- background: transparent url(images/windowlight/tl.png) no-repeat left top;
- font-family: Optima;
- }
- .x-window-header-text, .x-panel-header-text{
- color: #FFF;
- text-shadow: 1px 1px 0 #000;
- font-size: 12px;
- }
- .x-window-header, .x-window-tc, .x-panel-tc{
- }
-
- .x-panel-tc > .x-panel-header, .x-window-tc > .x-window-header{
- margin: 0 -10px;
- }
- /* don't go off the edge when a window is maximized. */
- .x-window-maximized > .x-window-tl > .x-window-tr > .x-window-tc > .x-window-header{
- margin: 0;
- }
- /* hide the rounded corners when the window is maximized. */
- .x-window-maximized > .x-window-tl, .x-window-maximized > .x-window-tl > .x-window-tr{
- background: none;
- }
-
- .x-window-mc, .x-panel-mc{
- background: transparent url(images/windowlight/c.png) repeat right top;
- padding: 0;
- }
- .x-window-ml, .x-panel-ml{
- padding-left: 2px;
- background: transparent url(images/windowlight/l.png) repeat-y left bottom;
- }
- .x-window-mr, .x-panel-mr{
- padding-right: 2px;
- background: transparent url(images/windowlight/r.png) repeat-y right bottom;
- }
- .x-window-mc{
- border: 0;
- padding: 0;
- }
- .x-window-header, .x-panel-header{
- line-height: 16px;
- }
- .x-panel-header{
- margin: 0 0;
- }
- /* Window Footer Stuff */
- .x-window-bl, .x-panel-bl{
- padding-left: 16px;
- min-height: 16px;
- background: transparent url(images/windowdark/bl.png) no-repeat left bottom;
- }
- .x-window-br, .x-panel-br{
- padding-right: 16px;
- min-height: 16px;
- background: transparent url(images/windowdark/br.png) no-repeat right bottom;
- }
- .x-window-bc, .x-panel-bc{
- background: transparent url(images/windowdark/bc.png) repeat-x right bottom;
- min-height: 16px;
- }
- .x-window-bc .x-window-footer, .x-panel-bc .x-panel-footer{
- margin: 0 -16px;
- }
- /* If there is no footer, use the light version */
- .x-window-bl.x-window-no-footer, .x-panel-bl.x-panel-nofooter{
- border-top: 0;
- background-image: url(images/windowlight/bl.png);
- }
- .x-window-no-footer .x-window-br, .x-panel-nofooter .x-panel-br{
- background-image: url(images/windowlight/br.png);
- }
- .x-window-no-footer .x-window-bc, .x-panel-nofooter .x-panel-bc{
- background-image: url(images/windowlight/bc.png) ;
- }
-
-/* @end */
-
-/* @group Frame Panel inside a window */
-
-.x-window .x-panel-tl,
-.x-window .x-panel-tr,
-.x-window .x-panel-ml,
-.x-window .x-panel-mr,
-.x-window .x-panel-bl,
-.x-window .x-panel-br{
- padding: 0;
- background: transparent;
-}
-.x-window .x-panel-bl, .x-window .x-panel-bc, .x-window .x-panel-br{
- background-position: top left;
-}
-
-/* @end */
-
-
-
-/* @group Basic Panel */
-
-.x-panel-header{
- background: transparent url(images/windowlight/tc.png) repeat-x left top;
- font-family: Optima;
- }
- .x-panel-body{
- background: transparent url(images/windowlight/c.png) top left repeat;
- }
- .x-panel-mc .x-panel-body{
- background: none;
- }
-
-/* @end */
-
-/* @group Minimizers and Split-Panels */
-
-.x-splitbar-proxy{
- background: transparent url(images/fills/30w.png) left top repeat;
-}
-
-.x-layout-collapsed{
- background: transparent url(images/windowlight/c.png) top left repeat;
- border-color: #333;
- }
- .x-layout-collapsed-over{
- background: transparent url(images/windowdark/c.png) top left repeat;
- }
-
-.x-layout-mini-west, .x-layout-collapsed .x-layout-mini-east{
- background: transparent url(images/mini/mini-left.png) top left no-repeat;
-}
-.x-layout-mini-east, .x-layout-collapsed .x-layout-mini-west{
- background: transparent url(images/mini/mini-right.png) top left no-repeat;
-}
-.x-layout-mini-north, .x-layout-collapsed .x-layout-mini-south{
- background: transparent url(images/mini/mini-bottom.png) top left no-repeat;
-}
-.x-layout-mini-south, .x-layout-collapsed .x-layout-mini-north{
- background: transparent url(images/mini/mini-top.png) top left no-repeat;
-}
-
-/* @end */
-
-
-/* @group Toolbars */
-
-.x-toolbar{
- height: 24px;
- background: transparent url(images/tb.png) left top repeat-x;
-}
-.x-btn-text{
- color: #FFF;
-}
-.xtb-text{
- font-size: 11px;
-}
- /* text-edit */
- .x-edit-bold,
- .x-edit-italic,
- .x-edit-underline,
- .x-edit-increasefontsize,
- .x-edit-decreasefontsize,
- .x-edit-forecolor,
- .x-edit-backcolor,
- .x-edit-justifyleft,
- .x-edit-justifyright,
- .x-edit-justifycenter,
- .x-edit-createlink,
- .x-edit-insertorderedlist,
- .x-edit-insertunorderedlist,
- .x-edit-sourceedit{
- background-image: url(images/tb-sprite.png) !important;
- }
-
-/* @end */
-
-/* @group Buttons */
-
- .x-btn-ml, .x-btn-tl, .x-btn-bl, .x-btn-mr, .x-btn-tr, .x-btn-br{
- width: 3px;
- }
- .x-btn-tl, .x-btn-tr, .x-btn-bl, .x-btn-br{
- height: 3px;
- }
- .x-btn-mc em{
- margin: 0 2px;
- }
-
- /* @group Normal */
- .x-btn-tl,
- .x-btn-tr,
- .x-btn-bl,
- .x-btn-br,
- .x-btn-ml,
- .x-btn-mr{
- background: transparent url(images/btn/whole/Normal.png) top left no-repeat;
- }
- .x-btn-mc,
- .x-btn-bc,
- .x-btn-tc{
- background: transparent url(images/btn/c/Normal.png) top left repeat-x;
- }
- /* @end */
-
- /* @group Over */
- .x-btn-over .x-btn-tl,
- .x-btn-over .x-btn-tr,
- .x-btn-over .x-btn-bl,
- .x-btn-over .x-btn-br,
- .x-btn-over .x-btn-ml,
- .x-btn-over .x-btn-mr{
- background: transparent url(images/btn/whole/Over.png) top left no-repeat;
- }
- .x-btn-over .x-btn-mc,
- .x-btn-over .x-btn-bc,
- .x-btn-over .x-btn-tc{
- background: transparent url(images/btn/c/Over.png) top left repeat-x;
- }
- /* @end */
-
- /* @group Click */
- .x-btn-click .x-btn-tl,
- .x-btn-click .x-btn-tr,
- .x-btn-click .x-btn-bl,
- .x-btn-click .x-btn-br,
- .x-btn-click .x-btn-ml,
- .x-btn-click .x-btn-mr{
- background: transparent url(images/btn/whole/Pressed.png) top left no-repeat;
- }
- .x-btn-click .x-btn-mc,
- .x-btn-click .x-btn-bc,
- .x-btn-click .x-btn-tc{
- background: transparent url(images/btn/c/Pressed.png) top left repeat-x;
- }
- /* @end */
-
- /* @group Active */
- .x-btn-pressed .x-btn-tl, .x-btn-menu-active .x-btn-tl,
- .x-btn-pressed .x-btn-tr, .x-btn-menu-active .x-btn-tr,
- .x-btn-pressed .x-btn-bl, .x-btn-menu-active .x-btn-bl,
- .x-btn-pressed .x-btn-br, .x-btn-menu-active .x-btn-br,
- .x-btn-pressed .x-btn-ml, .x-btn-menu-active .x-btn-ml,
- .x-btn-pressed .x-btn-mr, .x-btn-menu-active .x-btn-mr{
- background: transparent url(images/btn/whole/Down.png) top left no-repeat;
- }
- .x-btn-pressed .x-btn-mc, .x-btn-menu-active .x-btn-mc,
- .x-btn-pressed .x-btn-bc, .x-btn-menu-active .x-btn-bc,
- .x-btn-pressed .x-btn-tc, .x-btn-menu-active .x-btn-tc{
- background: transparent url(images/btn/c/Down.png) top left repeat-x;
- }
- /* @end */
-.x-btn-mc{
- padding: 0 10px !important;
-}
-
-.x-btn-tl{ background-position: left top !important; }
-.x-btn-tc{ background-position: center top !important; }
-.x-btn-tr{ background-position: right top !important; }
-.x-btn-ml{ background-position: left center !important; }
-.x-btn-mc{ background-position: center center !important; }
-.x-btn-mr{ background-position: right center !important; }
-.x-btn-bl{ background-position: left bottom !important; }
-.x-btn-bc{ background-position: center bottom !important; }
-.x-btn-br{ background-position: right bottom !important; }
-
-.x-btn-arrow-bottom{
- background: transparent url(images/btn/arrv.png) center bottom no-repeat !important;
-}
-.x-btn-split-bottom{
- background: transparent url(images/btn/splitv.png) center bottom no-repeat !important;
- padding-bottom:18px !important;
-}
-.x-btn-icon-small-right .x-btn-text{ padding-right: 20px !important; }
-.x-btn-icon-medium-right .x-btn-text{ padding-right: 28px !important; }
-.x-btn-icon-large-right .x-btn-text{ padding-right: 36px !important; }
-
-/*.x-toolbar-cell table{
- height:22px;
- margin-top: 1px;
- }
- .x-btn-tr, .x-btn-tc, .x-btn-tl, .x-btn-br, .x-btn-bc, .x-btn-bl{
- display: none;
- }
- .x-btn-ml, .x-btn-mc, .x-btn-mr{
- height: 22px;
- }
- .x-btn-ml,
- .x-toolbar .x-btn-ml{
- width: 6px;
- background: transparent url(images/btn/l.png) left top no-repeat;
- }
- .x-btn-mc,
- .x-toolbar .x-btn-mc{
- background: transparent url(images/btn/c.png) left top repeat;
- }
- .x-btn-mr,
- .x-toolbar .x-btn-mr{
- width:6px;
- background: transparent url(images/btn/r.png) right top no-repeat;
- }
- .x-btn-text{
- text-shadow: -1px -1px 0 rgba(0,0,0,.6);
- color: #EEE;
- }
- /* over state */
- .x-btn-over .x-btn-ml, .x-btn-over .x-btn-mc,
- .x-toolbar .x-btn-over .x-btn-ml, .x-toolbar .x-btn-over .x-btn-mc{
- background-position: left -22px;
- }
- .x-btn-over .x-btn-mr,
- .x-toolbar .x-btn-over .x-btn-mr{
- background-position: right -22px;
- }
- .x-btn-over .x-btn-text{
- color: #FFF;
- }
- /* pressed state */
- .x-toolbar .x-btn-menu-active .x-btn-ml,
- .x-toolbar .x-btn-menu-active .x-btn-mc,
- .x-btn-pressed .x-btn-ml,
- .x-btn-pressed .x-btn-mc,
- .x-toolbar .x-btn-pressed .x-btn-ml,
- .x-toolbar .x-btn-pressed .x-btn-mc{
- background-position: left -66px;
- }
- .x-toolbar .x-btn-menu-active .x-btn-mr,
- .x-toolbar .x-btn-pressed .x-btn-mr,
- .x-btn-pressed .x-btn-mr{
- background-position: right -66px;
- }
-
- .x-btn-split{
- background: transparent url(images/btn/splith.png) right center no-repeat !important;
- }
- .x-btn-split button{
- padding-right: 5px !important;
- }
- .x-btn-arrow{
- background: transparent url(images/btn/menu.png) right center no-repeat !important;
- padding-right:12px !important;
- }
- /* pressed and over state */
- /* Commented out because the selectors are so specific they're overriding the click state. What to do? I don't want to use !important... Figure out later. */
- /*.x-toolbar .x-btn-menu-active.x-btn-over .x-btn-ml,
- .x-toolbar .x-btn-menu-active.x-btn-over .x-btn-mc,
- .x-btn-pressed.x-btn-over .x-btn-ml,
- .x-btn-pressed.x-btn-over .x-btn-mc,
- .x-toolbar .x-btn-pressed.x-btn-over .x-btn-ml,
- .x-toolbar .x-btn-pressed.x-btn-over .x-btn-mc{
- background-position: left -88px;
- }
- .x-toolbar .x-btn-menu-active.x-btn-over .x-btn-mr,
- .x-toolbar .x-btn-pressed.x-btn-over .x-btn-mr,
- .x-btn-pressed.x-btn-over .x-btn-mr{
- background-position: right -88px;
- }*/
- /* click state */
- /*.x-btn-click .x-btn-ml, .x-btn-click .x-btn-mc,
- .x-toolbar .x-btn-click .x-btn-ml, .x-toolbar .x-btn-click .x-btn-mc{
- background-position: left -44px;
- }
- .x-btn-click .x-btn-mr,
- .x-toolbar .x-btn-click .x-btn-mr{
- background-position: right -44px;
- }
- .x-btn-click .x-btn-text, .x-btn-pressed .x-btn-text{
- color: #FFF;
- }*/
-
-/* @end */
-
-
-/* @group Tabs */
-
-.x-tab-panel-header, .x-tab-panel-footer{
- padding: 0;
- background: transparent url(images/fills/80b.png)
-}
-.x-tab-scrolling-top{
- background: transparent url(images/windowdark/c.png)
- }
-
- /* default state */
-
- .x-tab-strip .x-tab-right{
- padding: 0 0 0 6px;
- background-image: url(images/tab/l/Top.png) !important;
- background-position:left top;
- }
- .x-tab-strip .x-tab-left{
- padding: 0 6px 0 0 !important;
- background-image: url(images/tab/r/Top.png) !important;
- background-position:right top;
- }
- .x-tab-strip .x-tab-strip-inner{
- background-image: url(images/tab/c/Top.png) !important;
- background-position:center top;
- }
- .x-tab-strip-bottom .x-tab-right{ background-image: url(images/tab/l/Bottom.png) !important; }
- .x-tab-strip-bottom .x-tab-left{ background-image: url(images/tab/r/Bottom.png) !important; }
- .x-tab-strip-bottom .x-tab-strip-inner{ background-image: url(images/tab/c/Bottom.png) !important; }
-
- /* hover state */
- .x-tab-strip-over .x-tab-right{ background-position: left -26px !important; }
- .x-tab-strip-over .x-tab-left{ background-position: right -26px !important;}
- .x-tab-strip-over .x-tab-strip-inner{ background-position: left -26px !important; }
- .x-tab-right .x-tab-left .x-tab-strip-inner .x-tab-strip-text{
- color: #CCC;
- text-shadow: -1px -1px 0 rgba(0,0,0,.2);
- }
-
- /* active state */
- .x-tab-strip-active .x-tab-right{ background-position: left -52px !important; }
- .x-tab-strip-active .x-tab-left{ background-position: right -52px !important; }
- .x-tab-strip-active .x-tab-strip-inner{ background-position: center -52px !important; }
- .x-tab-strip-active .x-tab-right .x-tab-left .x-tab-strip-inner .x-tab-strip-text{
- color: #222;
- text-shadow:1px 1px 0 rgba(255,255,255,.25);
- }
-
- /* spacer */
- .x-tab-strip-top{
- border: 0 !important;
- }
- .x-tab-strip-spacer{
- border: 0 !important;
- background: transparent url(images/fills/30w.png) top left repeat;
- height: 2px;
- }
-
- /* scroller */
- .x-tab-scroller-left, .x-tab-scroller-right{
- }
- .x-tab-scroller-left{
- background: transparent url(images/scroller/l.png) 0 0 no-repeat;
- }
- .x-tab-scroller-left-over, .x-tab-scroller-right-over{
- background-position: left -22px !important;
- }
- .x-tab-scroller-left-disabled, .x-tab-scroller-right-disabled{
- background-position: left 0 !important;
- }
- .x-tab-scroller-right{
- background: transparent url(images/scroller/r.png) right 0 no-repeat;
- }
-
- /* closable */
-
- .x-tab-strip-closable .x-tab-strip-inner{
- padding-right: 15px;
- }
- .x-tab-strip-close{
- background: transparent url(images/tab/close.png) 0 0 no-repeat;
- margin-right: 2px;
- top: 5px !important;
- right:4px !important;
- }
- .x-tab-strip-active .x-tab-strip-close{
- background-position: 0 -11px;
- }
-
-/* @end */
-
-/* @group Forms and Form Fields */
-
-.x-form .x-form-item{
- margin: 10px 0;
-}
-.x-form .x-form-item .x-form-item{
- margin: 0;
-}
-
-.x-form-field{
- font-size: 11px !important;
-}
-.x-toolbar-cell .x-form-field{
- height: 22px !important;
-}
-.x-form-text, .x-form-textarea{
- background: #444 url(images/gradients/dark-inner-shadow.png) top left repeat-x;
- color: #FFF;
- text-shadow: 1px 1px 0 #000;
- border-top-color: #666;
- border-bottom-color: #222;
- border-left-color: transparent;
- border-right-color: transparent;
-}
-.x-form-empty-field{
- color: #999;
-}
-.x-form-invalid{
- border-top-color: #700;
- border-bottom-color: #200;
- border-left-color: transparent;
- border-right-color: transparent;
- background-color: #C00;
- color: #FAA;
-}
-.x-form-invalid-icon{
- background: transparent url(images/icons/exclamation.png) top left no-repeat;
-}
-
-.x-form-textarea{
- background: #FFF !important;
- color: #000;
- text-shadow: none;
- border-color: #000 !important;
-}
-.x-form-field-wrap .x-form-trigger{
- background-image: url(images/trigger/blank.png);
- border-bottom-color: #111;
-}
-.x-form-field-wrap .x-form-arrow-trigger{
- background-image: url(images/trigger/drop.png);
-}
-.x-form-field-wrap .x-form-date-trigger{
- background-image: url(images/trigger/date.png);
-}
-.x-form-field-wrap .x-form-search-trigger{
- background-image: url(images/trigger/search.png);
-}
-.x-form-field-wrap .x-form-clear-trigger{
- background-image: url(images/trigger/clear.png);
-}
-.x-html-editor-wrap{
- background: #FFF;
- border:1px solid #000;
- color: #000 !important;
-}
-
-.x-fieldset{
- border:1px solid #888;
-}
-
-/* @end */
-
-/* icons */
-.ext-mb-question.ext-mb-icon{
- background: transparent url(images/icons/balloon.png) left center no-repeat;
-}
-.x-window-dlg .ext-mb-error{
- background: transparent url(images/icons/cross.png) left center no-repeat;
-}
-.x-window-dlg .ext-mb-warning{
- background: transparent url(images/icons/exclamation32.png) left center no-repeat;
-}
-.x-window-dlg .ext-mb-info{
- background: transparent url(images/icons/information.png) left center no-repeat;
-}
-
-
-/* @group Combo List */
-
-.x-combo-list{
- border: 1px solid transparent;
- color: #444;
- background: #FFF;
- border-color: #777;
-}
-.x-combo-list-item{
- border-color: transparent;
-}
-.x-combo-list .x-combo-selected{
- background: #06C;
- color: #FFF;
- border:1px solid transparent !important;
-}
-.x-combo-list-inner{
- background: #FFF;
- border-bottom-color: #777 !important;
-}
-
-/* @end */
-
-/* @group Lists and Grids */
-
-.x-grid3-header-offset, .x-grid3-header{
- padding: 0;
- margin-bottom: -1px;
-}
-.x-grid3-header-offset table{
- border-right: 2px groove #DDD;
-}
-.x-list-header, .x-grid3-header{
- background: #CCC url(images/gloss/light-gloss.png) left top repeat-x;
-}
-.x-pivotgrid .x-grid3-header-offset td, .x-list-header-inner div, .x-grid3-hd, .x-dd-drag-proxy .x-grid3-hd-inner, .sort-asc .x-grid3-hd-inner, .sort-desc .x-grid3-hd-inner{
- background: transparent url(images/listview/header.png) left top repeat-x;
- color: #222;
- text-shadow:1px 1px 0 rgba(255,255,255,.35);
-}
-.x-pivotgrid .x-grid3-header-offset td{
- border-bottom: 1px solid #888;
-}
-/* a hover state */
-.x-grid3 .x-grid3-hd-over .x-grid3-hd-inner{
- background: transparent url(images/listview/header.png) left -44px repeat-x;
-}
-.sort-asc, .sort-desc{
- border-top: 0 !important;
- border-bottom: 0 !important;
- border-right: 0 !important;
-}
-.x-list-header-inner .sort-asc, .x-list-header-inner .sort-desc{
- height: 15px;
-}
-.x-grid3 .sort-asc, .x-grid3 .sort-desc{
- background: transparent url(images/listview/header.png) 0 -22px repeat-x !important;
-}
-.x-grid3-hd-inner{
- color: #222;
-}
-.x-grid3 table{
- font-size: 12px;
-}
-.x-grid3-hd-btn{
- border-left:2px groove #DDD;
- border-right:2px groove #DDD;
- background: transparent url(images/listview/headerdrop.png) 0 0px;
-}
-.x-grid3-hd-btn:hover{
- background: transparent url(images/listview/headerdrop.png) 0 -44px !important;
-}
-
-.x-grid3-sort-icon{
- margin-top: -5px !important;
- height: 5px;
-}
-.sort-asc .x-grid3-sort-icon{
- background: transparent url(images/listview/sort-asc.png);
-}
-
-.sort-desc .x-grid3-sort-icon{
- background: transparent url(images/listview/sort-desc.png);
-}
-
-.x-list-header .sort-asc{
- background: transparent url(images/listview/listview-sort-asc.png) center top !important;
-}
-.x-list-header .sort-desc{
- background: transparent url(images/listview/listview-sort-desc.png) center top !important;
-}
-
-.x-cols-icon{
- background-image: url(images/listview/cols.png);
-}
-.xg-hmenu-sort-desc .x-menu-item-icon{
- background-image: url(images/listview/az.png);
-}
-.xg-hmenu-sort-asc .x-menu-item-icon{
- background-image: url(images/listview/za.png);
-}
-
-.x-grid3-row-over, .x-list-over{
- background: transparent url(images/fills/30w.png) top left repeat !important;
-}
-
-.x-grid3-row-alt{
- background: transparent url(images/fills/30b.png) top left repeat;
- border: 1px solid #222 !important;
- border-width: 1px 0 !important;
-}
-
-.x-grid3-scroller{
- margin-top: 1px;
-}
-
-/* @group Row Editor */
-
-.x-row-editor .x-row-editor-body{
- background: #838383 url(images/gloss/gloss.png) repeat center center;
-}
-.x-row-editor .x-row-editor-header, .x-row-editor .x-row-editor-footer{
- height: 0;
- border: 1px solid #FFF;
- border-width: 1px 0;
- background: transparent !important;
-}
-.x-row-editor .x-row-editor-header{
- border-top-color: rgba(0,0,0,.15);
- border-bottom-color: #71b3e1;
-}
-.x-row-editor .x-row-editor-footer{
- border-bottom-color: rgba(0,0,0,.15);
- border-top-color: #065790 !important;
-}
-
-.x-row-editor .x-row-editor-bwrap .x-plain,
-.x-row-editor .x-row-editor-bwrap .x-plain .x-plain-bwrap,
-.x-row-editor .x-row-editor-bwrap .x-plain .x-plain-bwrap .x-plain-body{
- background-image: url(images/grid/row-editor-btns.png);
-}
-
-
-/* @end */
-
-/* @group Manip States */
-
-.x-grid3-resize-proxy {
- background: #777;
-}
-
-.x-grid3-resize-marker {
- background: #777;
-}
-
-.col-move-top{
- background-image:url(images/grid/col-move-top.png);
-}
-
-.col-move-bottom{
- background-image:url(images/grid/col-move-bottom.png);
-}
-
-/* @end */
-
-/* @group Selection States */
-.x-grid3-row, .x-list-wrap dl{
- border: 1px solid transparent;
- border-width: 1px 0;
- }
- .x-grid3-row .x-grid3-row-table, .x-list-wrap dl dt{
- border: 1px solid transparent;
- border-width: 1px 0;
- }
-.x-grid3-row-selected, .x-list-selected{
- border-color: #000 !important;
- }
- .x-grid3-row-selected .x-grid3-row-table, .x-list-selected dt{
- background: transparent url(images/gloss/gloss.png) center center repeat;
- border-top-color: #71b3e1 !important;
- border-bottom-color: #065790 !important;
- }
- .x-grid3-row-selected .x-grid3-cell, .x-list-selected dt{
- color: #FFF;
- text-shadow: -1px -1px 0 rgba(0,0,0,.35);
- }
-
-/* @end */
-
-/* @group Groups */
-
-.x-grid3 .x-grid3-td-numberer{
- font-weight: bold;
- color: #AAA;
-}
-.x-grid3 .x-grid-group-hd{
- border-top: 1px solid #CCC !important;
- border-bottom: 1px solid #444 !important;
- background: #666 url(images/gradients/30white-to-trans.png) left top repeat-x;
- font-family: Helvetica, Arial, sans-serif;
- padding: 0;
- color: #FFF;
- text-shadow:-1px -1px rgba(0,0,0,.25)
-
-}
-.x-grid-group-collapsed .x-grid-group-hd{
- border-bottom: 1px solid #222 !important;
- background: #333 url(images/gradients/30white-to-trans.png) left top repeat-x;
-}
-
-/* @end */
-
-/* @group Pivot Grid */
- .x-pivotgrid .x-grid3-row-table{
- border-bottom: 1px solid transparent;
- }
- .x-grid3-header-title{
- background: #666 url(images/gloss/gloss.png) left 50% repeat;
- color: #FFF;
- text-shadow:-1px -1px 0 rgba(0,0,0,.75);
- border-top: 1px solid #999;
- border-bottom: 1px solid #111;
- font-size: 14px;
- font-family: Optima, sans-serif;
- line-height: 10px;
- }
- .x-grid3-row-headers table{
- border-collapse:separate !important;
- border-spacing:0;
- }
- .x-grid3-row-headers td{
- height: 19px !important;
- background: #FFF url(images/gloss/gloss.png) left 50% repeat;
- border-top: 1px solid #777;
- border-bottom: 1px solid #444;
- border-left: 1px solid #777;
- border-right: 1px solid #444;
- color: #FFF;
- text-shadow: -1px -1px 0 rgba(0,0,0,.35)
- }
-
-/* @end */
-
-
-
-/* @end */
-
-/* @group Menus */
-
-.x-menu{
- background: transparent url(images/fills/80b.png) top left repeat;
- border:1px solid #444;
- }
- .x-menu-item-text{
- color: #DDD;
- text-shadow: -1px -1x 0 #000;
- }
- .x-menu-item-active, .x-menu-item-active .x-menu-item{
- border-color: #3398e1;
- border-top-color: #71b3e1;
- border-bottom-color: #065790;
- }
- .x-menu-item-active{
- background: transparent url(images/gloss/gloss.png) left center repeat-x;
- }
- .x-menu-item-active .x-menu-item-text{
- color: #FFF;
- }
- .x-menu-sep{
- border-color: #444;
- }
- .x-menu-item-arrow{
- background-image: url(images/menu/arrow.png);
- }
- .x-menu-check-item .x-menu-item-icon{
- background: transparent url(images/form/unchecked.png) left center no-repeat;
- }
- .x-menu-item-checked .x-menu-check-item .x-menu-item-icon{
- background: transparent url(images/form/checked.png) left center no-repeat;
- }
- .x-menu-group-item .x-menu-item-icon{
- background: transparent url(images/form/unradioed.png) left center no-repeat;
- }
- .x-menu-item-checked .x-menu-group-item .x-menu-item-icon{
- background: transparent url(images/form/radioed.png) left center no-repeat;
- }
-
-/* @end */
-
-/* @group Progress Bar */
-
-.x-progress-wrap{
- color: #CCC;
- background: transparent url(images/progress.png) 0 -18px repeat-x;
- border: 1px solid #000;
-}
-.x-progress-inner{
- border: 1px solid #888;
-}
-.x-progress-bar{
- color: #FFF;
- background: #000 url(images/gloss/gloss.png) center center repeat-x;
- padding: 1px;
- height: 15px !important;
- border-bottom: 1px solid #000 !important;
-}
-
-/* @end */
-
-/* @group Date Picker */
-
-.x-date-picker{
- border: 1px solid #000;
- background: transparent url(images/windowdark/c.png) repeat right top;
-}
-.x-date-picker a{
- color: #06C;
-}
-.x-date-mp{
- background: #222;
-}
-.x-date-mp a{
- color: #6AF;
- text-shadow:-1px -1px 0 rgba(0,0,0,.35)
-}
-.x-date-picker table{
- font-size:11px;
-}
-.x-date-active{
- border-color: transparent !important;
-}
-.x-date-selected{
- border: 1px solid #000 !important;
-}
-.x-date-active a{
- color: #FFF;
-}
-.x-date-picker .x-date-today .x-date-date{
- background: transparent url(images/fills/30w.png) repeat;
- border-color: transparent;
-}
-.x-date-picker .x-date-selected .x-date-date{
- background: transparent url(images/windowlight/tc.png) repeat-x right center;
- border-color: #3398e1;
- border-top-color: #71b3e1;
- border-bottom-color: #065790;
-}
-.x-date-picker .x-date-selected.x-date-today .x-date-date{
- background-color: #FFF;
-}
-.x-date-prevday a, .x-date-nextday a{
- color: #888;
-}
-.x-date-bottom{
- padding: 3px;
- border-top-color: #000;
- background: transparent url(images/tb.png) left top repeat-x;
-}
-.x-date-picker th{
- background: transparent url(images/tb.png) left top repeat-x;
- border-bottom-color: #000;
-}
-.x-date-middle, .x-date-left, .x-date-right{
- background: #000 url(images/gradients/30white-to-trans.png) left top repeat-x;
- border-top: 1px solid #888;
-}
-.x-date-left a{
- background: transparent url(images/btn/left.png) left top no-repeat;
- height: 15px;
- left: 15px;
-}
-.x-date-right a{
- background: transparent url(images/btn/right.png) left top no-repeat;
- height: 15px;
- left: 15px;
-}
-.x-date-picker .x-date-mp-sel a{
- background: transparent url(images/windowlight/tc.png) repeat-x right center;
- border-color: #3398e1;
- border-top-color: #71b3e1;
- border-bottom-color: #065790;
-}
-.x-date-picker .x-date-mp-sep{
- border-color: #444;
-}
-.x-date-mp-btns td{
- border-color: #444;
-}
-.x-date-mp-btns{
- background: #000;
-}
-.x-date-mp-btns button{
- background: transparent url(images/windowlight/tc.png) repeat-x right center;
- border-color: #888;
- border-top-color: #CCC;
- border-bottom-color: #555;
- color: #FFF;
- text-shadow:-1px -1px 0 #000;
-}
-.x-date-mp-btns button:hover{
- border-color: #3398e1;
- border-top-color: #71b3e1;
- border-bottom-color: #065790;
-}
-
-/* @end */
-
-/* @group Resizable Handles */
-
-.x-resizable-handle{
-}
-.x-resizable-handle-north{ background-image: url(images/resizable/n.png); }
-.x-resizable-handle-south{ background-image: url(images/resizable/s.png); }
-
-.x-resizable-handle-east{ background-image: url(images/resizable/e.png); }
-.x-resizable-handle-west{ background-image: url(images/resizable/w.png); }
-.x-resizable-handle-northwest{ background-image: url(images/resizable/nw.png); }
-.x-resizable-handle-northeast{ background-image: url(images/resizable/ne.png); }
-.x-resizable-handle-southwest{ background-image: url(images/resizable/sw.png); }
-.x-resizable-handle-southeast{ background-image: url(images/resizable/se.png); }
-
-.x-resizable-pinned{
- background: #888;
-}
-
-.x-window-handle, .x-window.x-resizable-pinned{
- background: transparent !important;
-}
-
-/* @end */
-
-
-/* @group Node Tree */
-
-.x-tree .x-panel-body{
- background: #000;
-}
-.x-tree-node-expanded .x-tree-node-icon{
- background-image:url(images/tree/folder-open.png);
-}
-
-.x-tree-node-leaf .x-tree-node-icon{
- background-image:url(images/tree/leaf.png);
-}
-
-.x-tree-node-collapsed .x-tree-node-icon{
- background-image:url(images/tree/folder.png);
-}
-
-.x-tree-node-loading .x-tree-node-icon{
- background-image:url(images/tree/loading.gif) !important;
-}
-
-.x-tree-node .x-tree-node-inline-icon {
- background-image: none;
-}
-
-.x-tree-node-loading a span{
- font-style: italic;
- color:#FFF;
-}
-
-.x-tree-lines .x-tree-elbow{
- background-image:url(images/tree/elbow.gif);
-}
-
-.x-tree-lines .x-tree-elbow-plus{
- background-image:url(images/tree/elbow-plus.gif);
-}
-
-.x-tree-lines .x-tree-elbow-minus{
- background-image:url(images/tree/elbow-minus.gif);
-}
-
-.x-tree-lines .x-tree-elbow-end{
- background-image:url(images/tree/elbow-end.gif);
-}
-
-.x-tree-lines .x-tree-elbow-end-plus{
- background-image:url(images/tree/elbow-end-plus.gif);
-}
-
-.x-tree-lines .x-tree-elbow-end-minus{
- background-image:url(images/tree/elbow-end-minus.gif);
-}
-
-.x-tree-lines .x-tree-elbow-line{
- background-image:url(images/tree/elbow-line.gif);
-}
-
-.x-tree-no-lines .x-tree-elbow-plus{
- background-image:url(images/tree/elbow-plus-nl.gif);
-}
-.x-tree-no-lines .x-tree-elbow-minus{
- background-image:url(images/tree/elbow-minus-nl.gif);
-}
-
-.x-tree-no-lines .x-tree-elbow-end-plus{
- background-image:url(images/tree/elbow-end-plus-nl.gif);
-}
-
-.x-tree-no-lines .x-tree-elbow-end-minus{
- background-image:url(images/tree/elbow-end-minus-nl.gif);
-}
-
-.x-tree-arrows .x-tree-elbow-plus{
- background-image:url(images/tree/arrows.gif);
-}
-
-.x-tree-arrows .x-tree-elbow-minus{
- background-image:url(images/tree/arrows.gif);
-}
-
-.x-tree-arrows .x-tree-elbow-end-plus{
- background-image:url(images/tree/arrows.gif);
-}
-
-.x-tree-arrows .x-tree-elbow-end-minus{
- background-image:url(images/tree/arrows.gif);
-}
-
-.x-tree-node{
- color:#FFF;
- font: normal 11px arial, tahoma, helvetica, sans-serif;
-}
-
-.x-tree-node a, .x-dd-drag-ghost a{
- color:#FFF;
-}
-
-.x-tree-node a span, .x-dd-drag-ghost a span{
- color:#FFF;
-}
-
-.x-tree-node .x-tree-node-disabled a span{
- color:gray !important;
-}
-
-.x-tree-node div.x-tree-drag-insert-below{
- border-bottom-color: #3fb5ff;
-}
-
-.x-tree-node div.x-tree-drag-insert-above{
- border-top-color:#3fb5ff;
-}
-
-.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-below a{
- border-bottom-color:#3fb5ff;
-}
-
-.x-tree-dd-underline .x-tree-node div.x-tree-drag-insert-above a{
- border-top-color:#3fb5ff;
-}
-
-.x-tree-node .x-tree-drag-append a span{
- background-color:#444;
- border-color:#666;
-}
-
-.x-tree-node .x-tree-node-over {
- background-color: #444;
-}
-
-.x-tree-node .x-tree-selected {
- background-color: #456;
-}
-
-.x-tree-drop-ok-append .x-dd-drop-icon{
- background-image: url(images/tree/drop-add.png);
-}
-
-.x-tree-drop-ok-above .x-dd-drop-icon{
- background-image: url(images/tree/drop-over.gif);
-}
-
-.x-tree-drop-ok-below .x-dd-drop-icon{
- background-image: url(images/tree/drop-under.gif);
-}
-
-.x-tree-drop-ok-between .x-dd-drop-icon{
- background-image: url(images/tree/drop-between.gif);
-}
-
-/* @end */
-
-/* @group Toolbar Icons */
-
-.x-toolbar .x-btn-mc em.x-btn-split {
- background-image:url(../images/default/btn/s-arrow-noline.gif);
-}
-
-.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split,
-.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split
-{
- background-image:url(../images/default/btn/s-arrow-o.gif);
-}
-
-.x-toolbar .x-btn-mc em.x-btn-split-bottom {
- background-image:url(../images/default/btn/s-arrow-b-noline.gif);
-}
-
-.x-toolbar .x-btn-over .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-click .x-btn-mc em.x-btn-split-bottom,
-.x-toolbar .x-btn-menu-active .x-btn-mc em.x-btn-split-bottom, .x-toolbar .x-btn-pressed .x-btn-mc em.x-btn-split-bottom
-{
- background-image:url(../images/default/btn/s-arrow-bo.gif);
-}
-
-.x-toolbar .xtb-sep {
- width: 0;
- border-left: 1px solid #222;
- border-right: 1px solid #777;
-}
-.x-tbar-page-first{
- background-image: url(images/icons/first.png) !important;
-}
-
-.x-tbar-loading{
- background-image: url(images/icons/refresh.png) !important;
-}
-
-.x-tbar-page-last{
- background-image: url(images/icons/last.png) !important;
-}
-.x-tbar-page-next{
- background-image: url(images/icons/next.png) !important;
-}
-
-.x-tbar-page-prev{
- background-image: url(images/icons/prev.png) !important;
-}
-
-.x-item-disabled .x-tbar-loading{
- background-image: url(images/icons/d-refresh.png) !important;
-}
-
-.x-item-disabled .x-tbar-page-first{
- background-image: url(images/icons/d-first.png) !important;
-}
-
-.x-item-disabled .x-tbar-page-last{
- background-image: url(images/icons/d-last.png) !important;
-}
-
-.x-item-disabled .x-tbar-page-next{
- background-image: url(images/icons/d-next.png) !important;
-}
-
-.x-item-disabled .x-tbar-page-prev{
- background-image: url(images/icons/d-prev.png) !important;
-}
-
-.x-paging-info {
- color:#444;
-}
-
-.x-toolbar-more-icon {
- background-image: url(../images/default/toolbar/more.gif) !important;
-}
-
-/* @end */
-
-/* @group Tool Tips */
-
-.x-tip{
- color: #FFE;
- text-shadow: -1px -1px 0 rgba(0,0,0,.35);
-}
-.x-tip .x-tip-tl{
- padding-left: 5px;
- background:transparent url(images/tt/tl.png) top left no-repeat;
-}
-.x-tip .x-tip-tr{
- padding-right: 5px;
- background:transparent url(images/tt/tr.png) top right no-repeat;
-}
-.x-tip .x-tip-tc{
- font-family: Optima, sans-serif;
- text-transform: uppercase;
- letter-spacing: .1em;
- font-size: 10px;
- padding-bottom: 3px;
- padding-top: 5px;
- background:transparent url(images/tt/tc.png) top left repeat-x;
-}
-.x-tip .x-tip-ml{
- padding-left: 5px;
- background:transparent url(images/tt/ml.png) top left repeat-y;
-}
-.x-tip .x-tip-mr{
- padding-right: 5px;
- background:transparent url(images/tt/mr.png) top right repeat-y;
-}
-.x-tip .x-tip-mc{
- background:transparent url(images/tt/c.png) top right repeat;
-}
-.x-tip .x-tip-bl{
- padding-left: 5px;
- background:transparent url(images/tt/bl.png) bottom left no-repeat;
-}
-.x-tip .x-tip-br{
- padding-right: 5px;
- background:transparent url(images/tt/br.png) bottom right no-repeat;
-}
-.x-tip .x-tip-bc{
- height: 5px;
- background:transparent url(images/tt/bc.png) bottom left repeat-x;
-}
-
- /* @group Invalid Tips */
-
-.x-form-invalid-tip{
- color: #FCC;
- }
- .x-form-invalid-tip .x-tip-body{
- background:transparent url(images/icons/exclamation.png) top left no-repeat;
- }
- .x-form-invalid-tip .x-tip-tl{
- padding-left: 5px;
- background:transparent url(images/tt/i-tl.png) top left no-repeat;
- }
- .x-form-invalid-tip .x-tip-tr{
- padding-right: 5px;
- background:transparent url(images/tt/i-tr.png) top right no-repeat;
- }
- .x-form-invalid-tip .x-tip-tc{
- font-family: Optima, sans-serif;
- text-transform: uppercase;
- letter-spacing: .1em;
- font-size: 10px;
- padding-bottom: 3px;
- padding-top: 5px;
- background:transparent url(images/tt/i-tc.png) top left repeat-x;
- }
- .x-form-invalid-tip .x-tip-ml{
- padding-left: 5px;
- background:transparent url(images/tt/i-ml.png) top left repeat-y;
- }
- .x-form-invalid-tip .x-tip-mr{
- padding-right: 5px;
- background:transparent url(images/tt/i-mr.png) top right repeat-y;
- }
- .x-form-invalid-tip .x-tip-mc{
- background:transparent url(images/tt/i-c.png) top right repeat;
- }
- .x-form-invalid-tip .x-tip-bl{
- padding-left: 5px;
- background:transparent url(images/tt/i-bl.png) bottom left no-repeat;
- }
- .x-form-invalid-tip .x-tip-br{
- padding-right: 5px;
- background:transparent url(images/tt/i-br.png) bottom right no-repeat;
- }
- .x-form-invalid-tip .x-tip-bc{
- height: 5px;
- background:transparent url(images/tt/i-bc.png) bottom left repeat-x;
- }
-
- /* @end */
-
-/* @end */
-
-/* @group Slider */
-
-.x-slider-horz .x-slider-thumb{
- background-image: url(images/slider/thumbh.png) !important;
-}
-
-.x-slider-vert .x-slider-thumb{
- background-image: url(images/slider/thumbv.png) !important;
-}
-.x-slider-horz, .x-slider-horz .x-slider-end, .x-slider-horz .x-slider-inner{
- background-image: url(images/slider/h.png) !important;
-}
-.x-slider-vert, .x-slider-vert .x-slider-end, .x-slider-vert .x-slider-inner{
- background-image: url(images/slider/v.png) !important;
-}
-
-/* @end */
-
-/* @group Masked Panel */
-
-.ext-el-mask{
- background: #999;
-}
-.ext-el-mask-msg{
- background: transparent url(images/gloss/gloss.png) center center repeat;
- border-bottom-color: #222;
- border-top-color: #999;
- border-left-color: #444;
- border-right-color: #444;
- border-radius:4px;
-}
-.ext-el-mask-msg div{
- background: #000;
- border: 1px solid #222;
- border-top-color: #222;
- border-bottom-color: #999;
- border-left-color: #444;
- border-right-color: #444;
- border-radius:3px;
-}
-.x-mask-loading div{
- background:#000 url(images/load.gif) 4px 4px no-repeat;
-}
-
-/* @end */
-
-/* @group Color Palette */
-
-.x-color-palette{
- background: #666 url(images/gradients/30white-to-trans.png) 0 0 repeat-x;
- margin: -3px !important;
-}
-.x-color-palette a{
- color: #000;
- border-color: transparent;
-}
-.x-color-palette .x-color-palette-sel em, .x-color-palette a:hover em{
- border-top-color: #222;
- border-left-color: #444;
- border-right-color: #444;
- border-bottom-color: #666;
-}
-.x-color-palette .x-color-palette-sel, .x-color-palette a:hover{
- border-top-color: #666 !important;
- border-left-color: #444 !important;
- border-right-color: #444 !important;
- border-bottom-color: #222 !important;
- background: #000 url(images/gloss/gloss.png) center center repeat-x;
-}
- .x-color-palette a:hover{
- border-top-color: #71b3e1 !important;
- border-left-color: #3398e1 !important;
- border-right-color: #3398e1 !important;
- border-bottom-color: #065790 !important;
- background-color: #065790;
-}
-
-/* @end */
-
-/* @group Drag Proxy */
-
-.x-dd-drag-proxy{
- border: 1px solid #000;
- background: #000;
- border-radius:3px;
-}
-.x-dd-drag-ghost{
- border-radius:2px;
- background: #000 url(images/gloss/gloss.png) center center repeat-x;
- border-top: 1px solid #AAA;
- border-bottom: 1px solid #222;
- border-left: 1px solid #444;
- border-right: 1px solid #444;
-}
-.x-dd-drop-ok .x-dd-drop-icon{
- background-image: url(images/icons/yes.png);
-}
-.x-dd-drop-nodrop .x-dd-drop-icon{
- background-image: url(images/icons/no.png);
-}
-
-/* @end */
-
-/* @group Accordion */
-
-.x-accordion-hd{
- border-top: 1px solid #CCC !important;
- border-bottom: 1px solid #444 !important;
- background: #666 url(images/gradients/30white-to-trans.png) left top repeat-x;
- font-family: Helvetica, Arial, sans-serif;
- font-size: .9em;
-}
-.x-panel-collapsed .x-accordion-hd{
- border-bottom: 1px solid #222 !important;
- background: #333 url(images/gradients/30white-to-trans.png) left top repeat-x;
-}
-.x-accordion-hd .x-panel-header-text{
- text-shadow: -1px -1px 0 rgba(0,0,0,.35);
-}
-
-/* @end */
-
-/* @group Group Summary */
-
-.x-grid3-summary-row{
- background: transparent url(images/fills/80b.png) left top repeat;
-}
-
-/* @end */
-
+++ /dev/null
-{% load staticmedia %}<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>{% block head %}
- <title>{% block title %}{{ gilbert.title }}{% endblock %}</title>
-
- {% block css %}
- <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/resources/css/ext-all-notheme.css' %}" />
- <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.murano" title="murano" href="{% mediaurl 'gilbert/murano/murano.css' %}"{% if request.GET.theme and request.GET.theme != 'murano' %} disabled="disabled"{% endif %} />
- <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.access" title="access" href="{% mediaurl 'gilbert/extjs/resources/css' %}/xtheme-access.css"{% if request.GET.theme != 'access' %} disabled="disabled"{% endif %} />
- <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.blue" title="blue" href="{% mediaurl 'gilbert/extjs/resources/css' %}/xtheme-blue.css"{% if request.GET.theme != 'blue' %} disabled="disabled"{% endif %} />
- <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.gray" title="gray" href="{% mediaurl 'gilbert/extjs/resources/css' %}/xtheme-gray.css"{% if request.GET.theme != 'gray' %} disabled="disabled"{% endif %} />
- {% endblock %}
-
- {% block js %}
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/adapter/ext/ext-base.js' %}"></script>
- {% if request.GET.debug %}
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/ext-all-debug.js' %}"></script>
- {% else %}
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/ext-all.js' %}"></script>
- {% endif %}
- <script type="text/javascript">
- Ext.BLANK_IMAGE_URL = '{% mediaurl "gilbert/extjs/resources/images/default/s.gif" %}';
- </script>
- {% endblock %}
-
- {% block extrahead %}
- {% endblock %}
-
-{% endblock %}</head>
-<body style="background-image: url({% mediaurl 'gilbert/wallpaper.jpg' %});">{% block body %}{% endblock %}</body>
-</html>
+++ /dev/null
-{% load staticmedia %}
-{% for icon_name in icon_names %}
-.icon-{{ icon_name }} {
- background: url({% mediaurl 'gilbert/fugue-icons/icons-shadowless' %}/{{ icon_name }}.png) 0 no-repeat !important;
-}
-{% endfor %}
\ No newline at end of file
+++ /dev/null
-{% extends 'gilbert/base.html' %}
-{% load staticmedia %}
-
-{% block css %}{{ block.super }}
- <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/examples/ux/fileuploadfield/css/fileuploadfield.css' %}" />
- <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/superboxselect/superboxselect.css' %}" />
- <link rel="stylesheet" type="text/css" href="{% url gilbert:icons %}" />
-
- {% for router in gilbert.model_routers.values %}{% for admin in router.models.values %}{% for css_url in admin.index_css_urls %}
- <link rel="stylesheet" type="text/css" href="{{ css_url }}" />
- {% endfor %}{% endfor %}{% endfor %}
-
- {% for plugin in plugins %}{% for css_url in plugin.index_css_urls %}
- <link rel="stylesheet" type="text/css" href="{{ css_url }}" />
- {% endfor %}{% endfor %}
-{% endblock %}
-
-{% block js %}{{ block.super }}
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/examples/ux/FieldLabeler.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/examples/ux/fileuploadfield/FileUploadField.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/superboxselect/SuperBoxSelect.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/examples/ux/Reorderer.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/examples/ux/ToolbarReorderer.js' %}"></script>
-
- <script type="text/javascript" src="{% mediaurl 'gilbert/lib/app.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/lib/models.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/lib/plugins.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/lib/ui/forms.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/lib/ui/windows.js' %}"></script>
- <script type="text/javascript" src="{% mediaurl 'gilbert/gilbert.js' %}"></script>
-
- <script type="text/javascript" src="{% url gilbert:api %}"></script>
-
- {% for router in gilbert.model_routers.values %}{% for admin in router.models.values %}{% for js_url in admin.index_js_urls %}
- <script type="text/javascript" src="{{ js_url }}"></script>
- {% endfor %}{% endfor %}{% endfor %}
-
- {% for plugin in plugins %}{% for js_url in plugin.index_js_urls %}
- <script type="text/javascript" src="{{ js_url }}"></script>
- {% endfor %}{% endfor %}
-{% endblock %}
-
-{% block extrahead %}
- {% for router in gilbert.model_routers.values %}{% for admin in router.models.values %}{{ admin.index_extrahead }}{% endfor %}{% endfor %}
- {% for plugin in plugins %}{{ plugin.index_extrahead }}{% endfor %}
-{% endblock %}
\ No newline at end of file
+++ /dev/null
-from .models import Blog, BlogEntry, BlogView, NewsletterArticle, NewsletterIssue, Newsletter, NewsletterView
-from philo.contrib.gilbert import site
-
-
-site.register_model(Blog, icon_name='blog')
-site.register_model(BlogEntry, search_fields=('title', 'content',), icon_name='document-snippet')
-site.register_model(BlogView, icon_name='application-blog')
-site.register_model(NewsletterArticle, icon_name='document-snippet')
-site.register_model(NewsletterIssue, icon_name='newspaper')
-site.register_model(Newsletter, icon_name='newspapers')
-site.register_model(NewsletterView, icon_name='application')
\ No newline at end of file
--- /dev/null
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Philo.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Philo.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/Philo"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Philo"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
--- /dev/null
+"""
+Sphinx plugins for Django documentation.
+"""
+import os
+import re
+
+from docutils import nodes, transforms
+try:
+ import json
+except ImportError:
+ try:
+ import simplejson as json
+ except ImportError:
+ try:
+ from django.utils import simplejson as json
+ except ImportError:
+ json = None
+
+from sphinx import addnodes, roles
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.writers.html import SmartyPantsHTMLTranslator
+from sphinx.util.console import bold
+from sphinx.util.compat import Directive
+
+# RE for option descriptions without a '--' prefix
+simple_option_desc_re = re.compile(
+ r'([-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)')
+
+def setup(app):
+ app.add_crossref_type(
+ directivename = "setting",
+ rolename = "setting",
+ indextemplate = "pair: %s; setting",
+ )
+ app.add_crossref_type(
+ directivename = "templatetag",
+ rolename = "ttag",
+ indextemplate = "pair: %s; template tag"
+ )
+ app.add_crossref_type(
+ directivename = "templatefilter",
+ rolename = "tfilter",
+ indextemplate = "pair: %s; template filter"
+ )
+ app.add_crossref_type(
+ directivename = "fieldlookup",
+ rolename = "lookup",
+ indextemplate = "pair: %s; field lookup type",
+ )
+ app.add_description_unit(
+ directivename = "django-admin",
+ rolename = "djadmin",
+ indextemplate = "pair: %s; django-admin command",
+ parse_node = parse_django_admin_node,
+ )
+ app.add_description_unit(
+ directivename = "django-admin-option",
+ rolename = "djadminopt",
+ indextemplate = "pair: %s; django-admin command-line option",
+ parse_node = parse_django_adminopt_node,
+ )
+ app.add_config_value('django_next_version', '0.0', True)
+ app.add_directive('versionadded', VersionDirective)
+ app.add_directive('versionchanged', VersionDirective)
+ app.add_transform(SuppressBlockquotes)
+ app.add_builder(DjangoStandaloneHTMLBuilder)
+
+
+class VersionDirective(Directive):
+ has_content = True
+ required_arguments = 1
+ optional_arguments = 1
+ final_argument_whitespace = True
+ option_spec = {}
+
+ def run(self):
+ env = self.state.document.settings.env
+ arg0 = self.arguments[0]
+ is_nextversion = env.config.django_next_version == arg0
+ ret = []
+ node = addnodes.versionmodified()
+ ret.append(node)
+ if not is_nextversion:
+ if len(self.arguments) == 1:
+ linktext = 'Please, see the release notes </releases/%s>' % (arg0)
+ xrefs = roles.XRefRole()('doc', linktext, linktext, self.lineno, self.state)
+ node.extend(xrefs[0])
+ node['version'] = arg0
+ else:
+ node['version'] = "Development version"
+ node['type'] = self.name
+ if len(self.arguments) == 2:
+ inodes, messages = self.state.inline_text(self.arguments[1], self.lineno+1)
+ node.extend(inodes)
+ if self.content:
+ self.state.nested_parse(self.content, self.content_offset, node)
+ ret = ret + messages
+ env.note_versionchange(node['type'], node['version'], node, self.lineno)
+ return ret
+
+
+class SuppressBlockquotes(transforms.Transform):
+ """
+ Remove the default blockquotes that encase indented list, tables, etc.
+ """
+ default_priority = 300
+
+ suppress_blockquote_child_nodes = (
+ nodes.bullet_list,
+ nodes.enumerated_list,
+ nodes.definition_list,
+ nodes.literal_block,
+ nodes.doctest_block,
+ nodes.line_block,
+ nodes.table
+ )
+
+ def apply(self):
+ for node in self.document.traverse(nodes.block_quote):
+ if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes):
+ node.replace_self(node.children[0])
+
+class DjangoHTMLTranslator(SmartyPantsHTMLTranslator):
+ """
+ Django-specific reST to HTML tweaks.
+ """
+
+ # Don't use border=1, which docutils does by default.
+ def visit_table(self, node):
+ self.body.append(self.starttag(node, 'table', CLASS='docutils'))
+
+ # <big>? Really?
+ def visit_desc_parameterlist(self, node):
+ self.body.append('(')
+ self.first_param = 1
+
+ def depart_desc_parameterlist(self, node):
+ self.body.append(')')
+
+ #
+ # Don't apply smartypants to literal blocks
+ #
+ def visit_literal_block(self, node):
+ self.no_smarty += 1
+ SmartyPantsHTMLTranslator.visit_literal_block(self, node)
+
+ def depart_literal_block(self, node):
+ SmartyPantsHTMLTranslator.depart_literal_block(self, node)
+ self.no_smarty -= 1
+
+ #
+ # Turn the "new in version" stuff (versionadded/versionchanged) into a
+ # better callout -- the Sphinx default is just a little span,
+ # which is a bit less obvious that I'd like.
+ #
+ # FIXME: these messages are all hardcoded in English. We need to change
+ # that to accomodate other language docs, but I can't work out how to make
+ # that work.
+ #
+ version_text = {
+ 'deprecated': 'Deprecated in Django %s',
+ 'versionchanged': 'Changed in Django %s',
+ 'versionadded': 'New in Django %s',
+ }
+
+ def visit_versionmodified(self, node):
+ self.body.append(
+ self.starttag(node, 'div', CLASS=node['type'])
+ )
+ title = "%s%s" % (
+ self.version_text[node['type']] % node['version'],
+ len(node) and ":" or "."
+ )
+ self.body.append('<span class="title">%s</span> ' % title)
+
+ def depart_versionmodified(self, node):
+ self.body.append("</div>\n")
+
+ # Give each section a unique ID -- nice for custom CSS hooks
+ def visit_section(self, node):
+ old_ids = node.get('ids', [])
+ node['ids'] = ['s-' + i for i in old_ids]
+ node['ids'].extend(old_ids)
+ SmartyPantsHTMLTranslator.visit_section(self, node)
+ node['ids'] = old_ids
+
+def parse_django_admin_node(env, sig, signode):
+ command = sig.split(' ')[0]
+ env._django_curr_admin_command = command
+ title = "django-admin.py %s" % sig
+ signode += addnodes.desc_name(title, title)
+ return sig
+
+def parse_django_adminopt_node(env, sig, signode):
+ """A copy of sphinx.directives.CmdoptionDesc.parse_signature()"""
+ from sphinx.domains.std import option_desc_re
+ count = 0
+ firstname = ''
+ for m in option_desc_re.finditer(sig):
+ optname, args = m.groups()
+ if count:
+ signode += addnodes.desc_addname(', ', ', ')
+ signode += addnodes.desc_name(optname, optname)
+ signode += addnodes.desc_addname(args, args)
+ if not count:
+ firstname = optname
+ count += 1
+ if not count:
+ for m in simple_option_desc_re.finditer(sig):
+ optname, args = m.groups()
+ if count:
+ signode += addnodes.desc_addname(', ', ', ')
+ signode += addnodes.desc_name(optname, optname)
+ signode += addnodes.desc_addname(args, args)
+ if not count:
+ firstname = optname
+ count += 1
+ if not firstname:
+ raise ValueError
+ return firstname
+
+
+class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder):
+ """
+ Subclass to add some extra things we need.
+ """
+
+ name = 'djangohtml'
+
+ def finish(self):
+ super(DjangoStandaloneHTMLBuilder, self).finish()
+ if json is None:
+ self.warn("cannot create templatebuiltins.js due to missing simplejson dependency")
+ return
+ self.info(bold("writing templatebuiltins.js..."))
+ xrefs = self.env.domaindata["std"]["objects"]
+ templatebuiltins = {
+ "ttags": [n for ((t, n), (l, a)) in xrefs.items()
+ if t == "templatetag" and l == "ref/templates/builtins"],
+ "tfilters": [n for ((t, n), (l, a)) in xrefs.items()
+ if t == "templatefilter" and l == "ref/templates/builtins"],
+ }
+ outfilename = os.path.join(self.outdir, "templatebuiltins.js")
+ f = open(outfilename, 'wb')
+ f.write('var django_template_builtins = ')
+ json.dump(templatebuiltins, f)
+ f.write(';\n')
+ f.close();
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# Philo documentation build configuration file, created by
+# sphinx-quickstart on Fri Jan 28 14:04:16 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "_ext")))
+sys.path.append(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
+
+os.environ['DJANGO_SETTINGS_MODULE'] = 'dummy-settings'
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['djangodocs', 'sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Philo'
+copyright = u'2011, Joseph Spiros'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+from philo import VERSION
+version = '%s.%s' % (VERSION[0], VERSION[1])
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Philodoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'Philo.tex', u'Philo Documentation',
+ u'Stephen Burrows', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'philo', u'Philo Documentation',
+ [u'Stephen Burrows'], 1)
+]
--- /dev/null
+.. Philo documentation master file, created by
+ sphinx-quickstart on Fri Jan 28 14:04:16 2011.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to Philo's documentation!
+=================================
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ intro
+ models/intro
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+What is Philo?
+==============
+
+Philo is a foundation for developing web content management systems.
+
+Prerequisites:
+
+* `Python 2.5.4+ <http://www.python.org>`_
+* `Django 1.2+ <http://www.djangoproject.com/>`_
+* `django-mptt e734079+ <https://github.com/django-mptt/django-mptt/>`_
+* (Optional) `django-grappelli 2.0+ <http://code.google.com/p/django-grappelli/>`_
+* (Optional) `south 0.7.2+ <http://south.aeracode.org/>`_
+* (Optional) `recaptcha-django r6 <http://code.google.com/p/recaptcha-django/>`_
+
+To contribute, please visit the `project website <http://philo.ithinksw.org/>`_ or make a fork of the `git repository <http://github.com/ithinksw/philo/>`_. Feel free to join us on IRC at `irc://irc.oftc.net/#philo <irc://irc.oftc.net/#philo>`_.
--- /dev/null
+How to get started with philo
+=============================
+
+After installing `philo`_ and `mptt`_ on your python path, make sure to complete the following steps:
+
+1. add :mod:`philo` and :mod:`mptt` to :setting:`settings.INSTALLED_APPS`::
+
+ INSTALLED_APPS = (
+ ...
+ 'philo',
+ 'mptt',
+ ...
+ )
+
+2. add :class:`philo.middleware.RequestNodeMiddleware` to :setting:`settings.MIDDLEWARE_CLASSES`::
+
+ MIDDLEWARE_CLASSES = (
+ ...
+ 'philo.middleware.RequestNodeMiddleware',
+ ...
+ )
+
+3. include :mod:`philo.urls` somewhere in your urls.py file. For example::
+
+ from django.conf.urls.defaults import patterns, include, url
+ urlpatterns = patterns('',
+ url(r'^', include('philo.urls')),
+ )
+
+4. Optionally add a root :class:`node <philo.models.Node>` to your current :class:`Site` in the admin interface.
+
+Philo should be ready to go!
+
+.. _philo: http://github.com/ithinksw/philo
+.. _mptt: http://github.com/django-mptt/django-mptt
\ No newline at end of file
--- /dev/null
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ echo. dirhtml to make HTML files named index.html in directories
+ echo. singlehtml to make a single large HTML file
+ echo. pickle to make pickle files
+ echo. json to make JSON files
+ echo. htmlhelp to make HTML files and a HTML help project
+ echo. qthelp to make HTML files and a qthelp project
+ echo. devhelp to make HTML files and a Devhelp project
+ echo. epub to make an epub
+ echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+ echo. text to make text files
+ echo. man to make manual pages
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Philo.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Philo.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+:end
--- /dev/null
+Entities and Attributes
+=======================
+
+.. module:: philo.models.base
+
+One of the core concepts in Philo is the relationship between the :class:`Entity` and :class:`Attribute` classes. :class:`Attribute`\ s represent an arbitrary key/value pair by having one :class:`GenericForeignKey` to an :class:`Entity` and another to an :class:`AttributeValue`.
+
+
+Attributes
+----------
+
+.. autoclass:: Attribute
+ :members:
+
+.. autoclass:: AttributeValue
+ :members:
+
+.. automodule:: philo.models.base
+ :members: attribute_value_limiter
+
+.. autoclass:: JSONValue
+ :show-inheritance:
+
+.. autoclass:: ForeignKeyValue
+ :show-inheritance:
+
+.. autoclass:: ManyToManyValue
+ :show-inheritance:
+
+.. automodule:: philo.models.base
+ :members: value_content_type_limiter
+
+.. autofunction:: register_value_model(model)
+.. autofunction:: unregister_value_model(model)
+
+Entities
+--------
+
+.. autoclass:: Entity
+ :members:
+ :exclude-members: attribute_set
+
+.. autoclass:: TreeManager
+ :members:
+
+.. autoclass:: TreeEntity
+ :members:
+ :exclude-members: attribute_set
+
+ .. attribute:: objects
+
+ An instance of :class:`TreeManager`.
+
+ .. automethod:: get_path
\ No newline at end of file
--- /dev/null
+Philo's models
+==============
+
+Contents:
+
+.. toctree::
+ :maxdepth: 2
+
+ entities
+ nodes-and-views
+
+
+.. :module: philo.models
--- /dev/null
+Nodes and Views: Building Website structure
+===========================================
+.. currentmodule:: philo.models
+
+Nodes
+-----
+
+:class:`Node`\ s are the basic building blocks of a website using Philo. They define the URL hierarchy and connect each URL to a :class:`View` subclass instance which is used to generate an HttpResponse.
+
+.. class:: Node
+
+ :class:`!Node` subclasses :class:`TreeEntity`. It defines the following additional methods and attributes:
+
+ .. attribute:: view
+
+ :class:`GenericForeignKey` to a non-abstract subclass of :class:`View`
+
+ .. attribute:: accepts_subpath
+
+ A property shortcut for :attr:`self.view.accepts_subpath <View.accepts_subpath>`
+
+ .. method:: render_to_response(request[, extra_context=None])
+
+ This is a shortcut method for :meth:`View.render_to_response`
+
+ .. method:: get_absolute_url([request=None, with_domain=False, secure=False])
+
+ This is essentially a shortcut for calling :meth:`construct_url` without a subpath - which will return the URL of the Node.
+
+ .. method:: construct_url([subpath="/", request=None, with_domain=False, secure=False])
+
+ This method will do its best to construct a URL based on the Node's location. If with_domain is True, that URL will include a domain and a protocol; if secure is True as well, the protocol will be https. The request will be used to construct a domain in cases where a call to :meth:`Site.objects.get_current` fails.
+
+ Node urls will not contain a trailing slash unless a subpath is provided which ends with a trailing slash. Subpaths are expected to begin with a slash, as if returned by :func:`django.core.urlresolvers.reverse`.
+
+ :meth:`construct_url` may raise the following exceptions:
+
+ - :class:`NoReverseMatch` if "philo-root" is not reversable -- for example, if :mod:`philo.urls` is not included anywhere in your urlpatterns.
+ - :class:`Site.DoesNotExist <ObjectDoesNotExist>` if with_domain is True but no :class:`Site` or :class:`RequestSite` can be built.
+ - :class:`AncestorDoesNotExist` if the root node of the site isn't an ancestor of the node constructing the URL.
+
+Views
+-----
+
+Abstract View Models
+++++++++++++++++++++
+.. class:: View
+
+ :class:`!View` is an abstract model that represents an item which can be "rendered", either in response to an :class:`HttpRequest` or as a standalone. It subclasses :class:`Entity`, and defines the following additional methods and attributes:
+
+ .. attribute:: accepts_subpath
+
+ Defines whether this :class:`View` can handle subpaths. Default: ``False``
+
+ .. method:: handles_subpath(subpath)
+
+ Returns True if the the :class:`View` handles the given subpath, and False otherwise.
+
+ .. attribute:: nodes
+
+ A generic relation back to nodes.
+
+ .. method:: reverse([view_name=None, args=None, kwargs=None, node=None, obj=None])
+
+ If :attr:`accepts_subpath` is True, try to reverse a URL using the given parameters using ``self`` as the urlconf.
+
+ If ``obj`` is provided, :meth:`get_reverse_params` will be called and the results will be combined with any ``view_name``, ``args``, and ``kwargs`` that may have been passed in.
+
+ This method will raise the following exceptions:
+
+ - :class:`ViewDoesNotProvideSubpaths` if :attr:`accepts_subpath` is False.
+ - :class:`ViewCanNotProvideSubpath` if a reversal is not possible.
+
+ .. method:: get_reverse_params(obj)
+
+ This method is not implemented on the base class. It should return a ``view_name``, ``args``, ``kwargs`` tuple suitable for reversing a url for the given ``obj`` using ``self`` as the urlconf. If a reversal will not be possible, this method should raise :class:`ViewCanNotProvideSubpath`.
+
+ .. method:: attributes_with_node(node)
+
+ Returns a :class:`QuerySetMapper` using the :class:`node <Node>`'s attributes as a passthrough.
+
+ .. method:: render_to_response(request[, extra_context=None])
+
+ Renders the :class:`View` as an :class:`HttpResponse`. This will raise :const:`philo.exceptions.MIDDLEWARE_NOT_CONFIGURED` if the `request` doesn't have an attached :class:`Node`. This can happen if :class:`philo.middleware.RequestNodeMiddleware` is not in :setting:`settings.MIDDLEWARE_CLASSES` or if it is not functioning correctly.
+
+ :meth:`!render_to_response` will send the :obj:`view_about_to_render <philo.signals.view_about_to_render>` signal, then call :meth:`actually_render_to_response`, and finally send the :obj:`view_finished_rendering <philo.signals.view_finished_rendering>` signal before returning the ``response``.
+
+ .. method:: actually_render_to_response(request[, extra_context=None])
+
+ Concrete subclasses must override this method to provide the business logic for turning a ``request`` and ``extra_context`` into an :class:`HttpResponse`.
+
+.. class:: MultiView
+
+ :class:`!MultiView` is an abstract model which represents a section of related pages - for example, a :class:`~philo.contrib.penfield.BlogView` might have a foreign key to :class:`Page`\ s for an index, an entry detail, an entry archive by day, and so on. :class:`!MultiView` subclasses :class:`View`, and defines the following additional methods and attributes:
+
+ .. attribute:: accepts_subpath
+
+ Same as :attr:`View.accepts_subpath`. Default: ``True``
+
+ .. attribute:: urlpatterns
+
+ Returns urlpatterns that point to views (generally methods on the class). :class:`!MultiView`\ s can be thought of as "managing" these subpaths.
+
+ .. method:: actually_render_to_response(request[, extra_context=None])
+
+ Resolves the remaining subpath left after finding this :class:`View`'s node using :attr:`self.urlpatterns <urlpatterns>` and renders the view function (or method) found with the appropriate args and kwargs.
+
+ .. method:: get_context()
+
+ Hook for providing instance-specific context - such as the value of a Field - to all views.
+
+ .. method:: basic_view(field_name)
+
+ Given the name of a field on ``self``, accesses the value of that field and treats it as a :class:`View` instance. Creates a basic context based on :meth:`get_context` and any extra_context that was passed in, then calls the :class:`View` instance's :meth:`~View.render_to_response` method. This method is meant to be called to return a view function appropriate for :attr:`urlpatterns`.
+
+Concrete View Subclasses
+++++++++++++++++++++++++
+
+.. class:: Redirect
+
+ A :class:`View` subclass. Defines a 301 or 302 redirect to a different url on an absolute or relative path.
+
+ .. attribute:: STATUS_CODES
+
+ A choices tuple of redirect status codes (temporary or permanent).
+
+ .. attribute:: status_code
+
+ An :class:`IntegerField` which uses :attr:`STATUS_CODES` as its choices. Determines whether the redirect is considered temporary or permanent.
+
+ .. attribute:: target_node
+
+ An optional :class:`ForeignKey` to a :class:`Node`. If provided, that node will be used as the basis for the redirect.
+
+ .. attribute:: url_or_subpath
+
+ A :class:`CharField` which may contain an absolute or relative URL. This will be validated with :class:`philo.validators.RedirectValidator`.
+
+ .. attribute:: reversing_parameters
+
+ A :class:`~philo.models.fields.JSONField` instance. If the value of :attr:`reversing_parameters` is not None, the :attr:`url_or_subpath` will be treated as the name of a view to be reversed. The value of :attr:`reversing_parameters` will be passed into the reversal as args if it is a list or as kwargs if it is a dictionary.
+
+ .. attribute:: target_url
+
+ Calculates and returns the target url based on the :attr:`target_node`, :attr:`url_or_subpath`, and :attr:`reversing_parameters`.
+
+ .. method:: actually_render_to_response(request[, extra_context=None])
+
+ Returns an :class:`HttpResponseRedirect` to :attr:`self.target`.
+
+.. class:: File
+
+ A :class:`View` subclass. Stores an arbitrary file.
+
+ .. attribute:: mimetype
+
+ Defines the mimetype of the uploaded file. This will not be validated.
+
+ .. attribute:: file
+
+ Contains the uploaded file. Files are uploaded to ``philo/files/%Y/%m/%d``.
+
+ .. method:: __unicode__()
+
+ Returns the name of :attr:`self.file <file>`.
+
+Pages
+*****
+
+:class:`Page`\ s are the most frequently used :class:`View` subclass. They define a basic HTML page and its associated content. Each :class:`Page` renders itself according to a :class:`Template`. The :class:`Template` may contain :ttag:`container` tags, which define related :class:`Contentlet`\ s and :class:`ContentReference`\ s for any page using that :class:`Template`.
+
+.. class:: Page
+
+ A :class:`View` subclass. Represents a page - something which is rendered according to a template. The page will have a number of related Contentlets depending on the template selected - but these will appear only after the page has been saved with that template.
+
+ .. attribute:: template
+
+ A :class:`ForeignKey` to the :class:`Template` used to render this :class:`Page`.
+
+ .. attribute:: title
+
+ The name of this page. Chances are this will be used for organization - i.e. finding the page in a list of pages - rather than for display.
+
+ .. attribute:: containers
+
+ Returns :attr:`self.template.containers <Template.containers>` - a tuple containing the specs of all :ttag:`container`\ s defined in the :class:`Template`. The value will be cached on the instance so that multiple accesses will be less expensive.
+
+ .. method:: render_to_string([request=None, extra_context=None])
+
+ In addition to rendering as an :class:`HttpResponse`, a :class:`Page` can also render as a string. This means, for example, that :class:`Page`\ s can be used to render emails or other non-HTML-related content with the same :ttag:`container`-based functionality as is used for HTML.
+
+ .. method:: actually_render_to_response(request[, extra_context=None])
+
+ Returns an :class:`HttpResponse` with the content of the :meth:`render_to_string` method and the mimetype set to :attr:`self.template.mimetype <Template.mimetype>`.
+
+ .. clean_fields(self[, exclude=None)
+
+ This is an override of the default model clean_fields method. Essentially, in addition to validating the fields, this method validates the :class:`Template` instance that is used to render this :class:`Page`. This is useful for catching template errors before they show up as 500 errors on a live site.
+
+ .. method:: __unicode__()
+
+ Returns :meth:`self.title <title>`
+
+.. class:: Template
+
+ Subclasses :class:`TreeModel`. Represents a database-driven django template. Defines the following additional methods and attributes:
+
+ .. attribute:: name
+
+ The name of the template. Used for organization and debugging.
+
+ .. attribute:: documentation
+
+ Can be used to let users know what the template is meant to be used for.
+
+ .. attribute:: mimetype
+
+ Defines the mimetype of the template. This is not validated. Default: ``text/html``.
+
+ .. attribute:: code
+
+ An insecure :class:`~philo.models.fields.TemplateField` containing the django template code for this template.
+
+ .. attribute:: containers
+
+ Returns a tuple where the first item is a list of names of contentlets referenced by containers, and the second item is a list of tuples of names and contenttypes of contentreferences referenced by containers. This will break if there is a recursive extends or includes in the template code. Due to the use of an empty Context, any extends or include tags with dynamic arguments probably won't work.
+
+ .. method:: __unicode__()
+
+ Returns the results of the :meth:`~TreeModel.get_path` method, using the "name" field and a chevron joiner.
+
+.. class:: Contentlet
+
+ Defines a piece of content on a page. This content is treated as a secure :class:`~philo.models.fields.TemplateField`.
+
+ .. attribute:: page
+
+ The page which this :class:`Contentlet` is related to.
+
+ .. attribute:: name
+
+ This represents the name of the container as defined by a :ttag:`container` tag.
+
+ .. attribute:: content
+
+ A secure :class:`~philo.models.fields.TemplateField` holding the content for this :class:`Contentlet`. Note that actually using this field as a template requires use of the :ttag:`include_string` template tag.
+
+ .. method:: __unicode__()
+
+ Returns :attr:`self.name <name>`
+
+.. class:: ContentReference
+
+ Defines a model instance related to a page.
+
+ .. attribute:: page
+
+ The page which this :class:`ContentReference` is related to.
+
+ .. attribute:: name
+
+ This represents the name of the container as defined by a :ttag:`container` tag.
+
+ .. attribute:: content
+
+ A :class:`GenericForeignKey` to a model instance. The content type of this instance is defined by the :ttag:`container` tag which defines this :class:`ContentReference`.
+
+ .. method:: __unicode__()
+
+ Returns :attr:`self.name <name>`
\ No newline at end of file
+++ /dev/null
-from django import forms
-from django.db import models
-from django.utils import simplejson as json
-from philo.forms.fields import JSONFormField
-from philo.validators import TemplateValidator, json_validator
-#from philo.models.fields.entities import *
-
-
-class TemplateField(models.TextField):
- def __init__(self, allow=None, disallow=None, secure=True, *args, **kwargs):
- super(TemplateField, self).__init__(*args, **kwargs)
- self.validators.append(TemplateValidator(allow, disallow, secure))
-
-
-class JSONDescriptor(object):
- def __init__(self, field):
- self.field = field
-
- def __get__(self, instance, owner):
- if instance is None:
- raise AttributeError # ?
-
- if self.field.name not in instance.__dict__:
- json_string = getattr(instance, self.field.attname)
- instance.__dict__[self.field.name] = json.loads(json_string)
-
- return instance.__dict__[self.field.name]
-
- def __set__(self, instance, value):
- instance.__dict__[self.field.name] = value
- setattr(instance, self.field.attname, json.dumps(value))
-
- def __delete__(self, instance):
- del(instance.__dict__[self.field.name])
- setattr(instance, self.field.attname, json.dumps(None))
-
-
-class JSONField(models.TextField):
- default_validators = [json_validator]
-
- def get_attname(self):
- return "%s_json" % self.name
-
- def contribute_to_class(self, cls, name):
- super(JSONField, self).contribute_to_class(cls, name)
- setattr(cls, name, JSONDescriptor(self))
- models.signals.pre_init.connect(self.fix_init_kwarg, sender=cls)
-
- def fix_init_kwarg(self, sender, args, kwargs, **signal_kwargs):
- if self.name in kwargs:
- kwargs[self.attname] = json.dumps(kwargs.pop(self.name))
-
- def formfield(self, *args, **kwargs):
- kwargs["form_class"] = JSONFormField
- return super(JSONField, self).formfield(*args, **kwargs)
-
-
-try:
- from south.modelsinspector import add_introspection_rules
-except ImportError:
- pass
-else:
- add_introspection_rules([], ["^philo\.models\.fields\.TemplateField"])
- add_introspection_rules([], ["^philo\.models\.fields\.JSONField"])
\ No newline at end of file
--- /dev/null
+VERSION = (0, 0)
template = 'admin/philo/edit_inline/tabular_attribute.html'
-def hide_proxy_fields(cls, attname, proxy_field_set):
- val_set = set(getattr(cls, attname))
- if proxy_field_set & val_set:
- cls._hidden_attributes[attname] = list(val_set)
- setattr(cls, attname, list(val_set - proxy_field_set))
+# HACK to bypass model validation for proxy fields
+class SpoofedHiddenFields(object):
+ def __init__(self, proxy_fields, value):
+ self.value = value
+ self.spoofed = list(set(value) - set(proxy_fields))
+
+ def __get__(self, instance, owner):
+ if instance is None:
+ return self.spoofed
+ return self.value
+
+
+class SpoofedAddedFields(SpoofedHiddenFields):
+ def __init__(self, proxy_fields, value):
+ self.value = value
+ self.spoofed = list(set(value) | set(proxy_fields))
+
+
+def hide_proxy_fields(cls, attname):
+ val = getattr(cls, attname, [])
+ proxy_fields = getattr(cls, 'proxy_fields')
+ if val:
+ setattr(cls, attname, SpoofedHiddenFields(proxy_fields, val))
+
+def add_proxy_fields(cls, attname):
+ val = getattr(cls, attname, [])
+ proxy_fields = getattr(cls, 'proxy_fields')
+ setattr(cls, attname, SpoofedAddedFields(proxy_fields, val))
class EntityAdminMetaclass(admin.ModelAdmin.__metaclass__):
def __new__(cls, name, bases, attrs):
- # HACK to bypass model validation for proxy fields by masking them as readonly fields
new_class = super(EntityAdminMetaclass, cls).__new__(cls, name, bases, attrs)
- form = getattr(new_class, 'form', None)
- if form:
- opts = form._meta
- if issubclass(form, EntityForm) and opts.model:
- proxy_fields = proxy_fields_for_entity_model(opts.model).keys()
-
- # Store readonly fields iff they have been declared.
- if 'readonly_fields' in attrs or not hasattr(new_class, '_real_readonly_fields'):
- new_class._real_readonly_fields = new_class.readonly_fields
-
- readonly_fields = new_class.readonly_fields
- new_class.readonly_fields = list(set(readonly_fields) | set(proxy_fields))
-
- # Additional HACKS to handle raw_id_fields and other attributes that the admin
- # uses model._meta.get_field to validate.
- new_class._hidden_attributes = {}
- proxy_fields = set(proxy_fields)
- hide_proxy_fields(new_class, 'raw_id_fields', proxy_fields)
- #END HACK
+ hide_proxy_fields(new_class, 'raw_id_fields')
+ add_proxy_fields(new_class, 'readonly_fields')
return new_class
-
+# END HACK
class EntityAdmin(admin.ModelAdmin):
__metaclass__ = EntityAdminMetaclass
form = EntityForm
inlines = [AttributeInline]
save_on_top = True
-
- def __init__(self, *args, **kwargs):
- # HACK PART 2 restores the actual readonly fields etc. on __init__.
- if hasattr(self, '_real_readonly_fields'):
- self.readonly_fields = self.__class__._real_readonly_fields
- if hasattr(self, '_hidden_attributes'):
- for name, value in self._hidden_attributes.items():
- setattr(self, name, value)
- # END HACK
- super(EntityAdmin, self).__init__(*args, **kwargs)
+ proxy_fields = []
def formfield_for_dbfield(self, db_field, **kwargs):
"""
classes = COLLAPSE_CLASSES
allow_add = True
fields = ('member_content_type', 'member_object_id', 'index')
+ sortable_field_name = 'index'
class CollectionAdmin(admin.ModelAdmin):
from django.contrib import admin
from philo.admin.base import EntityAdmin, TreeEntityAdmin, COLLAPSE_CLASSES
from philo.models import Node, Redirect, File
+from mptt.admin import MPTTModelAdmin
class NodeAdmin(TreeEntityAdmin):
list_display = ('slug', 'view', 'accepts_subpath')
+ raw_id_fields = ('parent',)
related_lookup_fields = {
- 'fk': [],
+ 'fk': raw_id_fields,
'm2m': [],
'generic': [['view_content_type', 'view_object_id']]
}
def accepts_subpath(self, obj):
return obj.accepts_subpath
accepts_subpath.boolean = True
+
+ def formfield_for_foreignkey(self, db_field, request, **kwargs):
+ return super(MPTTModelAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
class ViewAdmin(EntityAdmin):
list_filter = ('template',)
search_fields = ['title', 'contentlets__content']
inlines = [ContentletInline, ContentReferenceInline] + ViewAdmin.inlines
+
+ def response_add(self, request, obj, post_url_continue='../%s/'):
+ # Shamelessly cribbed from django/contrib/auth/admin.py:143
+ if '_addanother' not in request.POST and '_popup' not in request.POST:
+ request.POST['_continue'] = 1
+ return super(PageAdmin, self).response_add(request, obj, post_url_continue)
class TemplateAdmin(TreeAdmin):
from django import forms
from django.conf import settings
-from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.contrib.admin.widgets import FilteredSelectMultiple, url_params_from_lookup_dict
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from django.utils.text import truncate_words
class ModelLookupWidget(forms.TextInput):
# is_hidden = False
- def __init__(self, content_type, attrs=None):
+ def __init__(self, content_type, attrs=None, limit_choices_to=None):
self.content_type = content_type
+ self.limit_choices_to = limit_choices_to
super(ModelLookupWidget, self).__init__(attrs)
def render(self, name, value, attrs=None):
related_url = '../../../%s/%s/' % (self.content_type.app_label, self.content_type.model)
+ params = url_params_from_lookup_dict(self.limit_choices_to)
+ if params:
+ url = u'?' + u'&'.join([u'%s=%s' % (k, v) for k, v in params.items()])
+ else:
+ url = u''
if attrs is None:
attrs = {}
- if not attrs.has_key('class'):
+ if "class" not in attrs:
attrs['class'] = 'vForeignKeyRawIdAdminField'
- output = super(ModelLookupWidget, self).render(name, value, attrs)
- output += '<a href="%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);">' % (related_url, name)
- output += '<img src="%simg/admin/selector-search.gif" width="16" height="16" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, _('Lookup'))
- output += '</a>'
+ output = [super(ModelLookupWidget, self).render(name, value, attrs)]
+ output.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);">' % (related_url, url, name))
+ output.append('<img src="%simg/admin/selector-search.gif" width="16" height="16" alt="%s" />' % (settings.ADMIN_MEDIA_PREFIX, _('Lookup')))
+ output.append('</a>')
if value:
value_class = self.content_type.model_class()
try:
value_object = value_class.objects.get(pk=value)
- output += ' <strong>%s</strong>' % escape(truncate_words(value_object, 14))
+ output.append(' <strong>%s</strong>' % escape(truncate_words(value_object, 14)))
except value_class.DoesNotExist:
pass
- return mark_safe(output)
+ return mark_safe(u''.join(output))
class TagFilteredSelectMultiple(FilteredSelectMultiple):
catalog has been loaded in the page
"""
class Media:
- js = (settings.ADMIN_MEDIA_PREFIX + "js/core.js",
- settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js",
- settings.ADMIN_MEDIA_PREFIX + "js/SelectFilter2.js")
-
- if 'staticmedia' in settings.INSTALLED_APPS:
- import staticmedia
- js += (staticmedia.url('admin/js/TagCreation.js'),)
- else:
- js += (settings.ADMIN_MEDIA_PREFIX + "js/TagCreation.js",)
+ js = (
+ settings.ADMIN_MEDIA_PREFIX + "js/core.js",
+ settings.ADMIN_MEDIA_PREFIX + "js/SelectBox.js",
+ settings.ADMIN_MEDIA_PREFIX + "js/SelectFilter2.js",
+ settings.ADMIN_MEDIA_PREFIX + "js/TagCreation.js",
+ )
def render(self, name, value, attrs=None, choices=()):
if attrs is None: attrs = {}
--- /dev/null
+Gilbert requires Django 1.3+.
\ No newline at end of file
-import sys
-import datetime
+from django.db.models import Q
+from django.http import HttpResponse
+from django.utils import simplejson as json
+from django.utils.encoding import smart_str
+from django.views.debug import ExceptionReporter
from inspect import isclass, ismethod, isfunction, getmembers, getargspec
from traceback import format_tb
from abc import ABCMeta, abstractproperty
from collections import Callable, Sized, Mapping
-from django.utils import simplejson as json
-from django.views.debug import ExceptionReporter
-from django.http import HttpResponse
-from django.db.models import Q
+import sys, datetime
# __all__ = ('ext_action', 'ext_method', 'is_ext_action', 'is_ext_method', 'ExtAction', 'ExtMethod')
keywords = {}
if self.accepts_keywords:
- keywords = args.pop()
+ keywords = dict([(smart_str(k, 'ascii'), v) for k,v in args.pop().items()])
varargs = []
if self.accepts_varargs:
+from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.forms import PasswordChangeForm
-import staticmedia
from .base import Plugin
from ..extdirect import ext_action, ext_method
from ..models import UserPreferences
@property
def index_js_urls(self):
return super(Auth, self).index_js_urls + [
- staticmedia.url('gilbert/plugins/auth.js'),
+ settings.STATIC_URL + 'gilbert/plugins/auth.js',
]
@property
-import operator
-from django.forms.models import ModelForm, modelform_factory
+from django.conf import settings
+from django.contrib.admin.util import lookup_field, label_for_field, display_for_field, NestedObjects
+from django.core.exceptions import PermissionDenied
+from django.db import router
from django.db.models import Q
from django.db.models.fields.related import ManyToOneRel
from django.db.models.fields.files import FieldFile, ImageFieldFile, FileField
-from django.contrib.admin.util import lookup_field, label_for_field, display_for_field, NestedObjects
+from django.forms.models import ModelForm, modelform_factory
+from django.template.defaultfilters import capfirst
+from django.utils import simplejson as json
from django.utils.encoding import smart_unicode
-import staticmedia
from .base import Plugin
from ..extdirect import ext_action, ext_method
-from django.core.exceptions import PermissionDenied
-from django.utils import simplejson as json
+import operator
@ext_action(name='models')
@property
def index_js_urls(self):
return super(Models, self).index_js_urls + [
- staticmedia.url('gilbert/extjs/examples/ux/SearchField.js'),
- staticmedia.url('gilbert/plugins/models.js'),
+ settings.STATIC_URL + 'gilbert/extjs/examples/ux/SearchField.js',
+ settings.STATIC_URL + 'gilbert/plugins/models.js',
]
@property
def data_serialize_model_instance(cls, obj):
return {
'app_label': obj._meta.app_label,
- 'name': obj._meta.object_name,
+ 'name': obj._meta.module_name,
'pk': obj.pk,
'__unicode__': unicode(obj),
}
@property
def data_columns_spec(self):
spec = []
+
for field_name in self.data_columns:
column = {
'dataIndex': field_name,
'editable': False,
}
header, attr = label_for_field(field_name, self.model, model_admin=self, return_attr=True)
- column['header'] = header
+ column['header'] = capfirst(header)
if (field_name in self.sortable_fields) or (getattr(attr, 'admin_order_field', None) in self.sortable_fields):
column['sortable'] = True
if field_name in self.data_editable_columns:
column['editable'] = True
+ if field_name in [field.name for field in self.model_meta.fields if isinstance(field.rel, ManyToOneRel)]:
+ column['xtype'] = 'foreignkeycolumn'
spec.append(column)
return spec
raise PermissionDenied
return self.model._default_manager.all()
+ def queryset(self, request):
+ return self.model._default_manager.get_query_set()
+
@ext_method
def filter(self, request, **kwargs):
if not self.has_read_permission(request):
raise PermissionDenied
- return self.model._default_manager.all().filter(**kwargs)
+ return self.queryset(request).filter(**kwargs)
@ext_method
def get(self, request, **kwargs):
if not self.has_read_permission(request):
raise PermissionDenied
- return self.model._default_manager.all().values().get(**kwargs)
+ return self.queryset(request).values().get(**kwargs)
@property
def form_class(self):
pks = [pks]
objs = [self.model._default_manager.all().get(pk=pk) for pk in pks]
- collector = NestedObjects()
-
- for obj in objs:
- obj._collect_sub_objects(collector)
+ using = router.db_for_write(self.model)
+ collector = NestedObjects(using=using)
+ collector.collect(objs)
return collector.nested(self.data_serialize_model_instance)
\ No newline at end of file
+from django.conf import settings
+from django.contrib.auth import authenticate, login
+from django.core.context_processors import csrf
from django.conf.urls.defaults import url, patterns, include
from django.core.urlresolvers import reverse
+from django.db.models.base import ModelBase
+from django.forms.models import model_to_dict
+from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
-from django.conf import settings
+from django.template import RequestContext
from django.utils import simplejson as json
from django.utils.datastructures import SortedDict
-
-from django.db.models.base import ModelBase
-from philo.utils import fattr
-from .exceptions import AlreadyRegistered, NotRegistered
-from django.forms.models import model_to_dict
-import sys
-from inspect import getargspec
from django.views.decorators.cache import never_cache
+from philo.utils import fattr
from . import __version__ as gilbert_version
-import staticmedia
-import os
-import datetime
+from .exceptions import AlreadyRegistered, NotRegistered
from .extdirect import ExtAction, ExtRouter
-
-from functools import partial
-from django.http import HttpResponse, HttpResponseRedirect
-from django.template import RequestContext
-from django.core.context_processors import csrf
-from django.utils.functional import update_wrapper
-from django.contrib.auth import authenticate, login
-from .plugins.models import Models, ModelAdmin
from .plugins.auth import Auth
+from .plugins.models import Models, ModelAdmin
+from inspect import getargspec
+from functools import partial, update_wrapper
+import sys, os, datetime
+
__all__ = ('GilbertSite', 'site')
return render_to_response('gilbert/icons.css', {
'icon_names': set(icon_names),
+ 'STATIC_URL': settings.STATIC_URL
}, mimetype='text/css')
def router(self, request, app_label=None, extra_context=None):
--- /dev/null
+Subproject commit 3789b528d8dd8aad4558e38e22d775bcab1cbd36
Gilbert.lib.models.ModelInstance = Ext.extend(Object, {
- constructor: function (model, pk) {
+ constructor: function (model, pk, __unicode__) {
this.model = model;
this.pk = pk;
+ this.__unicode__ = __unicode__
},
});
convert: function (v, data) {
if (v) {
- return new Gilbert.lib.models.ModelInstance(Gilbert.get_model(v.app_label, v.name), v.pk);
+ return new Gilbert.lib.models.ModelInstance(Gilbert.get_model(v.app_label, v.name), v.pk, v.__unicode__);
} else {
return null;
}
// render DateField and TimeField
// create bounding table
var t;
- if ('below' === this.timePosition || 'bellow' === this.timePosition) {
+ if ('below' === this.timePosition) {
t = Ext.DomHelper.append(ct, {
tag: 'table',
style: 'border-collapse:collapse',
*/
,
isValid: function() {
- return this.df.isValid() && this.tf.isValid();
+ var valid = true;
+ var msg = "Both fields must be supplied."
+ if (!(this.df.isValid() && this.tf.isValid())) valid = false;
+ if (Boolean(this.df.getValue()) != Boolean(this.tf.getValue())) {
+ valid = false;
+ if (!this.df.getValue()){
+ if (!(this.tf.hasFocus || this.df.hasFocus)) this.df.markInvalid(msg);
+ } else {
+ if (!(this.tf.hasFocus || this.df.hasFocus)) this.tf.markInvalid(msg);
+ };
+ };
+ return valid;
}
// eo function isValid
// }}}
if (d) {
if (! (this.dateValue instanceof Date)) {
this.initDateValue();
- if (!this.tf.getValue()) {
- this.setTime(this.dateValue);
- }
}
this.dateValue.setMonth(0);
// because of leap years
}
else {
this.dateValue = '';
- this.setTime('');
}
}
// eo function updateDate
}
if (t && !this.df.getValue()) {
this.initDateValue();
- this.setDate(this.dateValue);
}
if (this.dateValue instanceof Date) {
if (t) {
*/
,
validate: function() {
- return this.df.validate() && this.tf.validate();
+ var valid = true;
+ var msg = "Both fields must be supplied."
+ if (!(this.df.validate() && this.tf.validate())) valid = false;
+ if (Boolean(this.df.getValue()) != Boolean(this.tf.getValue())) {
+ valid = false;
+ if (!this.df.getValue()){
+ if (!(this.tf.hasFocus || this.df.hasFocus)) this.df.markInvalid(msg);
+ } else {
+ if (!(this.tf.hasFocus || this.df.hasFocus)) this.tf.markInvalid(msg);
+ };
+ };
+ return valid;
}
// eo function validate
// }}}
--- /dev/null
+Murano
+------
+
+Murano is a glassy theme for Ext JS 4.
+
+Using Murano
+============
+
+Include ```path/to/murano/css/murano.css``` in place of the default Ext JS stylesheet, usually named ```ext-all.css```. Works with Ext JS 4.x.
+
+Modifying Murano
+================
+
+Editing Murano requires [Compass][].
+
+To edit Murano for contribution or your own use, you will need to update ```$ext_path``` in config.rb and run ```compass watch``` or ```compass compile``` from this directory.
+
+[Compass]:http://compass-style.org/
\ No newline at end of file
--- /dev/null
+# $ext_path: This should be the path of where the ExtJS SDK is installed
+# Generally this will be in a lib/extjs folder in your applications root
+# <root>/lib/extjs
+$ext_path = "../extjs"
+
+project_path = File.dirname(__FILE__)
+
+# sass_path: the directory your Sass files are in. THIS file should also be in the Sass folder
+# Generally this will be in a resources/sass folder
+# <root>/resources/sass
+sass_path = File.join(project_path, 'sass')
+
+# css_path: the directory you want your CSS files to be.
+# Generally this is a folder in the parent directory of your Sass files
+# <root>/resources/css
+css_path = File.join(project_path, "css")
+
+# output_style: The output style for your compiled CSS
+# nested, expanded, compact, compressed
+# More information can be found here http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#output_style
+output_style = :nested
+environment = :development
+
+# We need to load in the Ext4 themes folder, which includes all it's default styling, images, variables and mixins
+load File.join(project_path, $ext_path, 'resources', 'themes')
--- /dev/null
+/* BASE VARIABLES *
+ * -------------- */
+/* PANEL VARIABLES *
+ * --------------- */
+/* WINDOW VARIABLES *
+ * ---------------- */
+/* line 4, ../sass/murano/_core.scss */
+html, body {
+ background: #444; }
+
+/* line 8, ../sass/murano/_core.scss */
+body {
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); }
+
+/* WAT IS THIS I DON'T EVEN *
+ * ------------------------- */
+/* line 15, ../sass/murano/_core.scss */
+.x-border-layout-ct {
+ background: transparent !important; }
+
+/* line 19, ../sass/murano/_core.scss */
+.x-css-shadow {
+ display: none !important; }
+
+/* line 23, ../sass/murano/_core.scss */
+.x-tool img {
+ background-image: url("../img/tools/tool-sprites.png") !important; }
+
+/* line 27, ../sass/murano/_core.scss */
+.x-layout-split-left {
+ background: url("../img/util/splitter/mini-left.png") no-repeat top right !important; }
+
+/* line 31, ../sass/murano/_core.scss */
+.x-layout-split-right {
+ background: url("../img/util/splitter/mini-right.png") no-repeat top left !important; }
+
+/* line 35, ../sass/murano/_core.scss */
+.x-layout-split-top {
+ background: url("../img/util/splitter/mini-bottom.png") no-repeat top left !important; }
+
+/* line 39, ../sass/murano/_core.scss */
+.x-layout-split-bottom {
+ background: url("../img/util/splitter/mini-top.png") no-repeat top left !important; }
+
+/* line 44, ../sass/murano/_core.scss */
+.x-splitter-collapsed .x-layout-split-left {
+ background: url("../img/util/splitter/mini-right.png") no-repeat top left !important; }
+/* line 48, ../sass/murano/_core.scss */
+.x-splitter-collapsed .x-layout-split-right {
+ background: url("../img/util/splitter/mini-left.png") no-repeat top right !important; }
+/* line 52, ../sass/murano/_core.scss */
+.x-splitter-collapsed .x-layout-split-top {
+ background: url("../img/util/splitter/mini-top.png") no-repeat top left !important; }
+/* line 56, ../sass/murano/_core.scss */
+.x-splitter-collapsed .x-layout-split-bottom {
+ background: url("../img/util/splitter/mini-bottom.png") no-repeat top left !important; }
+
+/* VARIABLES THAT $include-default: false; DOES NOT GET RID OF *
+ * ----------------------------------------------------------- */
+/* line 1, ../sass/murano/components/_panel.scss */
+.x-panel {
+ background: rgba(0, 0, 0, 0.85);
+ overflow: hidden;
+ position: relative;
+ margin-top: 0; }
+
+/* line 10, ../sass/murano/components/_panel.scss */
+.x-panel .x-panel .x-panel-body, .x-window .x-panel .x-panel-body {
+ background: #222; }
+
+/* line 16, ../sass/murano/components/_panel.scss */
+.x-panel-header {
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ -moz-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ -webkit-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ -o-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ border-top: 1px solid #FFF;
+ line-height: 24px;
+ height: 24px;
+ padding: 0 3px 0 6px; }
+
+/* line 25, ../sass/murano/components/_panel.scss */
+.x-panel-header-vertical {
+ background: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -moz-linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -o-linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%); }
+
+/* line 29, ../sass/murano/components/_panel.scss */
+.x-panel-body {
+ position: relative;
+ padding: 0; }
+
+/* FRAMED PANEL
+ * ------------ */
+/* line 36, ../sass/murano/components/_panel.scss */
+.x-panel-default-framed {
+ border: 1px solid rgba(255, 255, 255, 0.5);
+ border-top-color: white;
+ -moz-border-radius: 6px 6px 0 0;
+ -webkit-border-radius: 6px 6px 0 0;
+ -o-border-radius: 6px 6px 0 0;
+ -ms-border-radius: 6px 6px 0 0;
+ -khtml-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0; }
+
+/* line 42, ../sass/murano/components/_panel.scss */
+.x-panel-default-framed .x-panel-header {
+ border-top: 0;
+ -moz-border-radius: 6px 6px 0 0;
+ -webkit-border-radius: 6px 6px 0 0;
+ -o-border-radius: 6px 6px 0 0;
+ -ms-border-radius: 6px 6px 0 0;
+ -khtml-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0;
+ margin-top: 1px;
+ margin-left: 1px;
+ margin-right: 1px; }
+
+/* MASKED PANEL
+ * ------------ */
+/* line 55, ../sass/murano/components/_panel.scss */
+.x-mask-msg {
+ background: #333333 !important;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))) !important;
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ -o-border-radius: 4px;
+ -ms-border-radius: 4px;
+ -khtml-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
+ -o-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
+ border: 1px solid #333333 !important;
+ border-top: 1px solid #888888 !important; }
+ /* line 62, ../sass/murano/components/_panel.scss */
+ .x-mask-msg div {
+ background-color: black !important;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ -o-border-radius: 3px;
+ -ms-border-radius: 3px;
+ -khtml-border-radius: 3px;
+ border-radius: 3px;
+ border: 1px solid #333333 !important;
+ border-bottom: 1px solid #888888 !important;
+ color: #cccccc !important; }
+
+/* line 1, ../sass/murano/components/_window.scss */
+.x-window {
+ background: rgba(0, 0, 0, 0.85);
+ -moz-border-radius: 6px 6px 0 0;
+ -webkit-border-radius: 6px 6px 0 0;
+ -o-border-radius: 6px 6px 0 0;
+ -ms-border-radius: 6px 6px 0 0;
+ -khtml-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0;
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.425), 0 3px 8px 0 rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.425) inset;
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.425), 0 3px 8px 0 rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.425) inset;
+ -o-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.425), 0 3px 8px 0 rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.425) inset;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.425), 0 3px 8px 0 rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.425) inset;
+ border: 1px solid rgba(255, 255, 255, 0.5);
+ border-top-color: white; }
+
+/* line 9, ../sass/murano/components/_window.scss */
+.x-window-header {
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ -moz-border-radius: 6px 6px 0 0;
+ -webkit-border-radius: 6px 6px 0 0;
+ -o-border-radius: 6px 6px 0 0;
+ -ms-border-radius: 6px 6px 0 0;
+ -khtml-border-radius: 6px 6px 0 0;
+ border-radius: 6px 6px 0 0;
+ -moz-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ -webkit-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ -o-box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.35);
+ padding: 0 3px 0 6px;
+ line-height: 24px;
+ height: 24px; }
+
+/* line 18, ../sass/murano/components/_window.scss */
+.x-window-body {
+ position: relative;
+ padding: 0;
+ background-color: rgba(0, 0, 0, 0.1); }
+
+/* line 1, ../sass/murano/components/_button.scss */
+button {
+ margin: 0;
+ padding: 0;
+ background: none;
+ border-width: 0; }
+
+/* line 8, ../sass/murano/components/_button.scss */
+.x-btn, .x-btn-pressed {
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.213);
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.213);
+ -o-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.213);
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.213);
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -o-border-radius: 2px;
+ -ms-border-radius: 2px;
+ -khtml-border-radius: 2px;
+ border-radius: 2px;
+ background-color: rgba(0, 0, 0, 0.425);
+ border: 1px solid rgba(255, 255, 255, 0.3);
+ border-top-color: rgba(255, 255, 255, 0.5);
+ border-bottom-color: rgba(255, 255, 255, 0.05);
+ margin-top: 1px;
+ margin-bottom: 1px;
+ position: relative;
+ white-space: nowrap;
+ display: inline-block;
+ padding: 2px; }
+ /* line 24, ../sass/murano/components/_button.scss */
+ .x-btn em, .x-btn-pressed em {
+ display: block; }
+
+/* line 29, ../sass/murano/components/_button.scss */
+.x-btn-over {
+ border-color: #066cd1;
+ border-top-color: #439ffa;
+ border-bottom-color: #05529f; }
+
+/* line 35, ../sass/murano/components/_button.scss */
+.x-btn-pressed {
+ background-color: rgba(255, 255, 255, 0.2);
+ border-color: rgba(255, 255, 255, 0.2);
+ border-top-color: rgba(255, 255, 255, 0.4);
+ border-bottom-color: rgba(255, 255, 255, 0.1); }
+
+/* line 43, ../sass/murano/components/_button.scss */
+.x-btn-menu-active {
+ background: rgba(0, 0, 0, 0.5);
+ -moz-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5) inset, 0 0 0 1px rgba(0, 0, 0, 0.213);
+ -webkit-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5) inset, 0 0 0 1px rgba(0, 0, 0, 0.213);
+ -o-box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5) inset, 0 0 0 1px rgba(0, 0, 0, 0.213);
+ box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.5) inset, 0 0 0 1px rgba(0, 0, 0, 0.213);
+ border: 1px solid rgba(255, 255, 255, 0.5); }
+
+/* line 49, ../sass/murano/components/_button.scss */
+.x-btn-inner {
+ display: block;
+ padding: 0 5px;
+ color: white;
+ background-repeat: no-repeat; }
+
+/* different sizes */
+/* line 63, ../sass/murano/components/_button.scss */
+.x-btn-noicon .x-btn-inner, .x-btn-default-icon .x-btn-inner, .x-btn-icon-text-left .x-btn-inner, .x-btn-icon-text-right .x-btn-inner {
+ line-height: 16px; }
+
+/* line 69, ../sass/murano/components/_button.scss */
+.x-btn-default-medium-noicon .x-btn-inner, .x-btn-default-medium-icon-text-left .x-btn-inner, .x-btn-default-medium-icon-text-right .x-btn-inner {
+ line-height: 24px; }
+
+/* line 75, ../sass/murano/components/_button.scss */
+.x-btn-default-large-noicon .x-btn-inner, .x-btn-default-large-icon-text-left .x-btn-inner, .x-btn-default-large-icon-text-right .x-btn-inner {
+ line-height: 32px; }
+
+/* icons
+ * ----- */
+/* icon only */
+/* line 85, ../sass/murano/components/_button.scss */
+.x-btn-default-small-icon .x-btn-inner, .x-btn-icon .x-btn-inner {
+ padding: 0;
+ width: 16px;
+ height: 16px; }
+
+/* line 90, ../sass/murano/components/_button.scss */
+.x-btn-default-medium-icon .x-btn-inner {
+ padding: 0;
+ width: 24px;
+ height: 24px; }
+
+/* line 95, ../sass/murano/components/_button.scss */
+.x-btn-default-large-icon .x-btn-inner {
+ padding: 0;
+ width: 32px;
+ height: 32px; }
+
+/* text w/ icon left */
+/* line 103, ../sass/murano/components/_button.scss */
+.x-btn-icon-text-left {
+ background-position: 0 center; }
+
+/* line 107, ../sass/murano/components/_button.scss */
+.x-btn-icon-text-left .x-btn-inner {
+ padding-left: 18px; }
+
+/* line 110, ../sass/murano/components/_button.scss */
+.x-btn-default-medium-icon-text-left .x-btn-inner {
+ padding-left: 26px; }
+
+/* line 113, ../sass/murano/components/_button.scss */
+.x-btn-default-large-icon-text-left .x-btn-inner {
+ padding-left: 34px; }
+
+/* text w/ icon top */
+/* line 119, ../sass/murano/components/_button.scss */
+.x-btn-icon-text-top .x-btn-inner {
+ background-position: center 2px; }
+
+/* line 122, ../sass/murano/components/_button.scss */
+.x-btn-default-small-icon-text-top .x-btn-inner {
+ padding-top: 18px; }
+
+/* line 125, ../sass/murano/components/_button.scss */
+.x-btn-default-medium-icon-text-top .x-btn-inner {
+ padding-top: 26px; }
+
+/* line 128, ../sass/murano/components/_button.scss */
+.x-btn-default-large-icon-text-top .x-btn-inner {
+ padding-top: 34px; }
+
+/* text w/ icon right */
+/* line 134, ../sass/murano/components/_button.scss */
+.x-btn-icon-text-right .x-btn-inner {
+ background-position: right center; }
+
+/* line 137, ../sass/murano/components/_button.scss */
+.x-btn-default-small-icon-text-right .x-btn-inner {
+ padding-right: 18px; }
+
+/* line 140, ../sass/murano/components/_button.scss */
+.x-btn-default-medium-icon-text-right .x-btn-inner {
+ padding-right: 26px; }
+
+/* line 143, ../sass/murano/components/_button.scss */
+.x-btn-default-large-icon-text-right .x-btn-inner {
+ padding-right: 34px; }
+
+/* text w/ icon bottom */
+/* line 149, ../sass/murano/components/_button.scss */
+.x-btn-icon-text-bottom .x-btn-inner {
+ background-position: center bottom; }
+
+/* line 152, ../sass/murano/components/_button.scss */
+.x-btn-default-small-icon-text-bottom .x-btn-inner {
+ padding-bottom: 16px; }
+
+/* line 155, ../sass/murano/components/_button.scss */
+.x-btn-default-medium-icon-text-bottom .x-btn-inner {
+ padding-bottom: 24px; }
+
+/* line 158, ../sass/murano/components/_button.scss */
+.x-btn-default-large-icon-text-bottom .x-btn-inner {
+ padding-bottom: 32px; }
+
+/* arrow on right */
+/* line 163, ../sass/murano/components/_button.scss */
+.x-btn-arrow-right {
+ padding-right: 14px;
+ background: transparent url("../img/btn/menu.png") right center no-repeat; }
+
+/* arrow on botton */
+/* line 169, ../sass/murano/components/_button.scss */
+.x-btn-arrow-bottom {
+ padding-bottom: 14px;
+ background: transparent url("../img/btn/menu.png") center bottom no-repeat; }
+
+/* split on right */
+/* line 176, ../sass/murano/components/_button.scss */
+.x-btn-split-right {
+ padding-right: 16px;
+ background: transparent url("../img/btn/splith.png") right center no-repeat;
+ display: block; }
+
+/* split on bottom */
+/* line 184, ../sass/murano/components/_button.scss */
+.x-btn-split-bottom {
+ padding-bottom: 16px;
+ background: transparent url("../img/btn/splitv.png") center bottom no-repeat;
+ display: block; }
+
+/* line 1, ../sass/murano/components/_grid.scss */
+.x-grid-view {
+ position: relative;
+ overflow: hidden; }
+
+/* line 6, ../sass/murano/components/_grid.scss */
+.x-grid-header-ct {
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #cccccc), color-stop(100%, #aaaaaa));
+ background: -webkit-linear-gradient(top, #cccccc, #aaaaaa);
+ background: -moz-linear-gradient(top, #cccccc, #aaaaaa);
+ background: -o-linear-gradient(top, #cccccc, #aaaaaa);
+ background: linear-gradient(top, #cccccc, #aaaaaa);
+ -moz-box-shadow: 0 1px 0 0 #999999;
+ -webkit-box-shadow: 0 1px 0 0 #999999;
+ -o-box-shadow: 0 1px 0 0 #999999;
+ box-shadow: 0 1px 0 0 #999999; }
+
+/* line 11, ../sass/murano/components/_grid.scss */
+.x-column-header {
+ border-top: 1px solid #DDD;
+ padding: 2px 5px;
+ color: #222;
+ text-shadow: 0 1px 0 #FFF;
+ white-space: nowrap;
+ border-right: 1px solid rgba(0, 0, 0, 0.1); }
+
+/* line 20, ../sass/murano/components/_grid.scss */
+.x-column-header {
+ overflow: hidden; }
+ /* line 22, ../sass/murano/components/_grid.scss */
+ .x-column-header .x-column-header-trigger {
+ display: none;
+ background: transparent url("../img/triggericons/spinner-down.png") center 6px no-repeat;
+ width: 20px; }
+ /* line 28, ../sass/murano/components/_grid.scss */
+ .x-column-header-over .x-column-header-trigger, .x-column-header-open .x-column-header-trigger {
+ display: block;
+ background-color: #AAA;
+ border-left: 1px solid #FFF;
+ border-right: 1px solid #888; }
+
+/* line 38, ../sass/murano/components/_grid.scss */
+.x-column-header-sort-DESC, .x-column-header-sort-ASC {
+ border-top: 1px solid #BBB;
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #aaaaaa), color-stop(100%, #888888));
+ background: -webkit-linear-gradient(top, #aaaaaa, #888888);
+ background: -moz-linear-gradient(top, #aaaaaa, #888888);
+ background: -o-linear-gradient(top, #aaaaaa, #888888);
+ background: linear-gradient(top, #aaaaaa, #888888);
+ -moz-box-shadow: 0 1px 0 0 #777777;
+ -webkit-box-shadow: 0 1px 0 0 #777777;
+ -o-box-shadow: 0 1px 0 0 #777777;
+ box-shadow: 0 1px 0 0 #777777;
+ text-shadow: 0 1px 0 #DDD; }
+
+/* line 45, ../sass/murano/components/_grid.scss */
+.x-column-header-trigger {
+ width: 14px;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ right: 0; }
+
+/* line 54, ../sass/murano/components/_grid.scss */
+.x-grid-table {
+ font-size: inherit;
+ border-collapse: separate;
+ border-spacing: 0;
+ table-layout: fixed; }
+ /* line 59, ../sass/murano/components/_grid.scss */
+ .x-grid-table td, .x-grid-table th {
+ overflow: hidden;
+ text-align: left;
+ white-space: nowrap;
+ vertical-align: top; }
+
+/* line 66, ../sass/murano/components/_grid.scss */
+.x-grid-cell-inner {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ padding: 3px 6px; }
+
+/* line 75, ../sass/murano/components/_grid.scss */
+.x-grid-row td {
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent; }
+
+/* line 81, ../sass/murano/components/_grid.scss */
+.x-grid-row-alt {
+ background: rgba(255, 255, 255, 0.1); }
+ /* line 83, ../sass/murano/components/_grid.scss */
+ .x-grid-row-alt td {
+ border-top: 1px solid rgba(255, 255, 255, 0.05);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05); }
+
+/* line 90, ../sass/murano/components/_grid.scss */
+.x-grid-row-over td {
+ background: rgba(255, 255, 255, 0.05); }
+
+/* line 95, ../sass/murano/components/_grid.scss */
+.x-grid-row-selected {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-color: #000; }
+ /* line 98, ../sass/murano/components/_grid.scss */
+ .x-grid-row-selected td {
+ border-top: 1px solid #1286f8;
+ border-bottom: 1px solid #066cd1; }
+
+/* line 104, ../sass/murano/components/_grid.scss */
+.x-grid-resize-marker {
+ background: #FFF;
+ width: 1px;
+ position: absolute; }
+
+/* line 112, ../sass/murano/components/_grid.scss */
+.x-grid-row-editor {
+ position: absolute !important;
+ z-index: 1;
+ zoom: 1;
+ overflow: visible !important; }
+ /* line 120, ../sass/murano/components/_grid.scss */
+ .x-grid-row-editor .x-form-display-field {
+ padding-top: 0; }
+ /* line 124, ../sass/murano/components/_grid.scss */
+ .x-grid-row-editor .x-panel-body {
+ border-top: 1px solid #066cd1 !important;
+ border-bottom: 1px solid #066cd1 !important;
+ border-left: none !important;
+ border-right: none !important; }
+
+/* line 137, ../sass/murano/components/_grid.scss */
+.x-grid-row-editor .x-form-text {
+ padding-left: 2px; }
+
+/* line 143, ../sass/murano/components/_grid.scss */
+.x-grid-editor .x-form-cb-wrap {
+ text-align: center; }
+
+/* line 148, ../sass/murano/components/_grid.scss */
+.x-grid-row-editor-buttons {
+ position: absolute;
+ bottom: -31px;
+ padding: 4px;
+ width: 200px;
+ height: 32px;
+ background: #222;
+ -moz-border-radius: 0 0 4px 4px;
+ -webkit-border-radius: 0 0 4px 4px;
+ -o-border-radius: 0 0 4px 4px;
+ -ms-border-radius: 0 0 4px 4px;
+ -khtml-border-radius: 0 0 4px 4px;
+ border-radius: 0 0 4px 4px;
+ border-bottom: 1px solid #066cd1;
+ border-left: 1px solid #066cd1;
+ border-right: 1px solid #066cd1; }
+ /* line 162, ../sass/murano/components/_grid.scss */
+ .x-strict .x-grid-row-editor-buttons {
+ width: 192px;
+ height: 24px; }
+
+/* line 169, ../sass/murano/components/_grid.scss */
+.x-grid-row-editor-errors ul {
+ margin-left: 5px; }
+/* line 172, ../sass/murano/components/_grid.scss */
+.x-grid-row-editor-errors li {
+ list-style: disc;
+ margin-left: 15px; }
+
+/* line 1, ../sass/murano/components/_toolbar.scss */
+.x-toolbar {
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #222222), color-stop(10%, #444444), color-stop(90%, #666666), color-stop(100%, #444444));
+ background: -webkit-linear-gradient(top, #222222 0%, #444444 10%, #666666 90%, #444444 100%);
+ background: -moz-linear-gradient(top, #222222 0%, #444444 10%, #666666 90%, #444444 100%);
+ background: -o-linear-gradient(top, #222222 0%, #444444 10%, #666666 90%, #444444 100%);
+ background: linear-gradient(top, #222222 0%, #444444 10%, #666666 90%, #444444 100%);
+ padding: 3px 0; }
+
+/* line 7, ../sass/murano/components/_toolbar.scss */
+.x-toolbar-item {
+ margin-left: 3px;
+ margin-right: 3px;
+ white-space: nowrap; }
+
+/* line 14, ../sass/murano/components/_toolbar.scss */
+.x-toolbar-text {
+ font-size: 11px;
+ margin-left: 10px;
+ white-space: nowrap; }
+
+/* line 20, ../sass/murano/components/_toolbar.scss */
+.x-toolbar-separator {
+ border-right: 1px solid rgba(255, 255, 255, 0.25);
+ border-left: 1px solid rgba(0, 0, 0, 0.25);
+ height: 14px; }
+
+/* line 26, ../sass/murano/components/_toolbar.scss */
+.x-toolbar-separator-vertical {
+ width: 100%;
+ height: 0;
+ border-top: 1px solid rgba(0, 0, 0, 0.25);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.25);
+ margin: 9px 0; }
+
+/* line 2, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-wrap {
+ border: 1px solid black; }
+ /* line 5, ../sass/murano/components/form/_htmleditor.scss */
+ .x-html-editor-wrap .x-toolbar {
+ border-top-width: 0;
+ border-left-width: 0;
+ border-right-width: 0; }
+ /* line 11, ../sass/murano/components/form/_htmleditor.scss */
+ .x-html-editor-wrap textarea {
+ background-color: white; }
+
+/* line 16, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-btn-inner {
+ display: block;
+ width: 16px;
+ padding: 0;
+ height: 16px;
+ margin: 4px 2px;
+ background: transparent url("../img/editor/tb-sprite.png") no-repeat; }
+
+/* line 26, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-bold,
+.x-menu-item img.x-edit-bold {
+ background-position: 0 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 32, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-italic,
+.x-menu-item img.x-edit-italic {
+ background-position: -16px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 38, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-underline,
+.x-menu-item img.x-edit-underline {
+ background-position: -32px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 44, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-forecolor,
+.x-menu-item img.x-edit-forecolor {
+ background-position: -160px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 50, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-backcolor,
+.x-menu-item img.x-edit-backcolor {
+ background-position: -176px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 56, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-justifyleft,
+.x-menu-item img.x-edit-justifyleft {
+ background-position: -112px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 62, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-justifycenter,
+.x-menu-item img.x-edit-justifycenter {
+ background-position: -128px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 68, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-justifyright,
+.x-menu-item img.x-edit-justifyright {
+ background-position: -144px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 74, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-insertorderedlist,
+.x-menu-item img.x-edit-insertorderedlist {
+ background-position: -80px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 80, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-insertunorderedlist,
+.x-menu-item img.x-edit-insertunorderedlist {
+ background-position: -96px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 86, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-increasefontsize,
+.x-menu-item img.x-edit-increasefontsize {
+ background-position: -48px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 92, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-decreasefontsize,
+.x-menu-item img.x-edit-decreasefontsize {
+ background-position: -64px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 98, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-sourceedit,
+.x-menu-item img.x-edit-sourceedit {
+ background-position: -192px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 104, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-edit-createlink,
+.x-menu-item img.x-edit-createlink {
+ background-position: -208px 0;
+ background-image: url("../img/editor/tb-sprite.png"); }
+
+/* line 109, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tip .x-tip-bd .x-tip-bd-inner {
+ padding: 5px;
+ padding-bottom: 1px; }
+
+/* line 115, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-toolbar {
+ position: static !important; }
+/* line 118, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-tb .x-font-select {
+ font-size: 11px; }
+
+/* line 123, ../sass/murano/components/form/_htmleditor.scss */
+.x-html-editor-wrap textarea {
+ border: 0;
+ padding: 3px 2px;
+ overflow: auto; }
+
+/* line 6, ../sass/murano/components/_form.scss */
+.x-form-item {
+ margin-bottom: 6px; }
+
+/* line 10, ../sass/murano/components/_form.scss */
+.x-form-item-body, .x-form-item-label-left {
+ float: left;
+ position: relative; }
+
+/* line 15, ../sass/murano/components/_form.scss */
+.x-form-text {
+ background: #444;
+ -moz-box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
+ -webkit-box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
+ -o-box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
+ box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.35), 0 0 0 1px rgba(255, 255, 255, 0.05) inset;
+ border: 1px solid #000;
+ color: #FFF;
+ color: #FFF;
+ padding: 0 3px; }
+
+/* line 24, ../sass/murano/components/_form.scss */
+.x-form-text:focus, .x-form-trigger-wrap-focus .x-form-text {
+ outline: none;
+ background: #666; }
+
+/* line 29, ../sass/murano/components/_form.scss */
+input.x-form-text {
+ height: 21px; }
+
+/* line 32, ../sass/murano/components/_form.scss */
+.x-form-invalid-field {
+ background: #700; }
+
+/* line 35, ../sass/murano/components/_form.scss */
+.x-form-invalid-icon {
+ text-indent: -9999px; }
+
+/* line 38, ../sass/murano/components/_form.scss */
+.x-form-invalid-icon ul {
+ display: none; }
+
+/* line 42, ../sass/murano/components/_form.scss */
+.x-form-checkbox, .x-form-radio {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ height: 16px;
+ width: 16px; }
+
+/* line 50, ../sass/murano/components/_form.scss */
+.x-form-checkbox {
+ background: url("../img/form/unchecked.png"); }
+
+/* line 53, ../sass/murano/components/_form.scss */
+.x-form-cb-checked .x-form-checkbox {
+ background: url("../img/form/checked.png"); }
+
+/* line 57, ../sass/murano/components/_form.scss */
+.x-form-radio {
+ background: url("../img/form/unradioed.png"); }
+
+/* line 60, ../sass/murano/components/_form.scss */
+.x-form-cb-checked .x-form-radio {
+ background: url("../img/form/radioed.png"); }
+
+/* line 64, ../sass/murano/components/_form.scss */
+.x-form-cb-label-after {
+ margin-left: 3px; }
+
+/* line 68, ../sass/murano/components/_form.scss */
+.x-form-invalid-icon {
+ width: 20px;
+ height: 19px;
+ float: left;
+ background: url("../img/form/exclamation.png") right center no-repeat; }
+
+/* line 76, ../sass/murano/components/_form.scss */
+.x-form-field, .x-form-display-field {
+ float: left;
+ margin: 0; }
+
+/* line 82, ../sass/murano/components/_form.scss */
+.x-fieldset {
+ border: 1px solid #666;
+ padding: 10px;
+ margin-bottom: 10px; }
+
+/* line 87, ../sass/murano/components/_form.scss */
+.x-fieldset-header {
+ white-space: nowrap;
+ padding: 0 5px; }
+
+/* line 91, ../sass/murano/components/_form.scss */
+.x-fieldset-header-text {
+ float: left; }
+
+/* line 94, ../sass/murano/components/_form.scss */
+.x-fieldset-header .x-tool, .x-fieldset-header .x-form-item {
+ float: left;
+ margin-right: 3px; }
+
+/* line 98, ../sass/murano/components/_form.scss */
+.x-fieldset-collapsed {
+ border-width: 1px 1px 0 1px !important;
+ padding-bottom: 0px !important;
+ border-left-color: transparent;
+ border-right-color: transparent; }
+
+/* line 105, ../sass/murano/components/_form.scss */
+.x-boundlist, .x-menu {
+ background: #000;
+ border: 1px solid #333; }
+
+/* line 110, ../sass/murano/components/_form.scss */
+.x-boundlist-floating {
+ -moz-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.35);
+ -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.35);
+ -o-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.35);
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.35); }
+
+/* line 113, ../sass/murano/components/_form.scss */
+.x-boundlist-item {
+ padding: 1px 4px;
+ border: 1px solid transparent;
+ margin: 1px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -o-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -khtml-border-radius: 5px;
+ border-radius: 5px; }
+ /* line 118, ../sass/murano/components/_form.scss */
+ .x-boundlist-item-over {
+ border: 1px solid #1286f8;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #1286f8), color-stop(100%, #066cd1));
+ background-image: -webkit-linear-gradient(#1286f8, #066cd1);
+ background-image: -moz-linear-gradient(#1286f8, #066cd1);
+ background-image: -o-linear-gradient(#1286f8, #066cd1);
+ background-image: linear-gradient(#1286f8, #066cd1);
+ -moz-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ -webkit-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ -o-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset; }
+
+/* line 124, ../sass/murano/components/_form.scss */
+.x-boundlist-selected {
+ border: 1px solid #066cd1;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #066cd1), color-stop(100%, #05529f));
+ background-image: -webkit-linear-gradient(#066cd1, #05529f);
+ background-image: -moz-linear-gradient(#066cd1, #05529f);
+ background-image: -o-linear-gradient(#066cd1, #05529f);
+ background-image: linear-gradient(#066cd1, #05529f);
+ -moz-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ -webkit-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ -o-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset; }
+
+/* line 7, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger-wrap {
+ float: left;
+ -moz-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35);
+ -webkit-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35);
+ -o-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35);
+ box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35);
+ overflow: hidden;
+ border: 1px solid #000;
+ border-left: 0;
+ -moz-border-radius: 0 4px 4px 0;
+ -webkit-border-radius: 0 4px 4px 0;
+ -o-border-radius: 0 4px 4px 0;
+ -ms-border-radius: 0 4px 4px 0;
+ -khtml-border-radius: 0 4px 4px 0;
+ border-radius: 0 4px 4px 0; }
+
+/* line 17, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger-wrap .x-form-spinner-up {
+ height: 10px;
+ -moz-border-radius: 0 3px 0 0;
+ -webkit-border-radius: 0 3px 0 0;
+ -o-border-radius: 0 3px 0 0;
+ -ms-border-radius: 0 3px 0 0;
+ -khtml-border-radius: 0 3px 0 0;
+ border-radius: 0 3px 0 0;
+ background: #666666 url("../img/triggericons/spinner-up.png") center top no-repeat;
+ border-bottom: 1px solid #444; }
+ /* line 22, ../sass/murano/components/form/_triggers.scss */
+ .x-form-trigger-wrap .x-form-spinner-up-over {
+ background-color: #999; }
+/* line 26, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger-wrap .x-form-spinner-down {
+ height: 9px;
+ border-top: none;
+ -moz-border-radius: 0 0 3px 0;
+ -webkit-border-radius: 0 0 3px 0;
+ -o-border-radius: 0 0 3px 0;
+ -ms-border-radius: 0 0 3px 0;
+ -khtml-border-radius: 0 0 3px 0;
+ border-radius: 0 0 3px 0;
+ background: #555555 url("../img/triggericons/spinner-down.png") center top no-repeat;
+ border-top: 1px solid #888; }
+ /* line 32, ../sass/murano/components/form/_triggers.scss */
+ .x-form-trigger-wrap .x-form-spinner-down-over {
+ background-color: #888;
+ border-color: #888; }
+
+/* line 39, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger-wrap-focus .x-form-spinner-up {
+ background-color: #999; }
+/* line 42, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger-wrap-focus .x-form-spinner-down {
+ background-color: #888; }
+
+/* line 48, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger-wrap-focus .x-form-trigger {
+ background-color: #AAA;
+ border-color: #AAA; }
+ /* line 51, ../sass/murano/components/form/_triggers.scss */
+ .x-form-trigger-wrap-focus .x-form-trigger-click {
+ background-color: #888;
+ border-color: #888; }
+
+/* line 58, ../sass/murano/components/form/_triggers.scss */
+.x-form-trigger {
+ -moz-border-radius: 0 3px 3px 0;
+ -webkit-border-radius: 0 3px 3px 0;
+ -o-border-radius: 0 3px 3px 0;
+ -ms-border-radius: 0 3px 3px 0;
+ -khtml-border-radius: 0 3px 3px 0;
+ border-radius: 0 3px 3px 0;
+ width: 16px;
+ height: 19px;
+ float: left;
+ background-color: #666;
+ border: 1px solid #666; }
+ /* line 65, ../sass/murano/components/form/_triggers.scss */
+ .x-form-trigger-over {
+ background-color: #AAA;
+ border-color: #AAA; }
+ /* line 69, ../sass/murano/components/form/_triggers.scss */
+ .x-form-trigger-click {
+ background-color: #888;
+ border-color: #888; }
+
+/* line 76, ../sass/murano/components/form/_triggers.scss */
+.x-form-clear-trigger {
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+ -o-border-radius: 0;
+ -ms-border-radius: 0;
+ -khtml-border-radius: 0;
+ border-radius: 0;
+ border-right-color: #888; }
+
+/* line 2, ../sass/murano/components/form/_triggers.scss */
+.x-form-arrow-trigger {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.2)), color-stop(100%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))), url("../img/triggericons/chev.png");
+ background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/chev.png");
+ background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/chev.png");
+ background-image: -o-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/chev.png");
+ background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/chev.png"); }
+
+/* line 2, ../sass/murano/components/form/_triggers.scss */
+.x-form-time-trigger {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.2)), color-stop(100%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))), url("../img/triggericons/time.png");
+ background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/time.png");
+ background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/time.png");
+ background-image: -o-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/time.png");
+ background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/time.png"); }
+
+/* line 2, ../sass/murano/components/form/_triggers.scss */
+.x-form-date-trigger {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.2)), color-stop(100%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))), url("../img/triggericons/date.png");
+ background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/date.png");
+ background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/date.png");
+ background-image: -o-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/date.png");
+ background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/date.png"); }
+
+/* line 2, ../sass/murano/components/form/_triggers.scss */
+.x-form-clear-trigger {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.2)), color-stop(100%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))), url("../img/triggericons/clear.png");
+ background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/clear.png");
+ background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/clear.png");
+ background-image: -o-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/clear.png");
+ background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/clear.png"); }
+
+/* line 2, ../sass/murano/components/form/_triggers.scss */
+.x-form-search-trigger {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(0, 0, 0, 0.2)), color-stop(100%, rgba(0, 0, 0, 0))), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))), url("../img/triggericons/search.png");
+ background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/search.png");
+ background-image: -moz-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/search.png");
+ background-image: -o-linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/search.png");
+ background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0)), linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%), url("../img/triggericons/search.png"); }
+
+/* line 1, ../sass/murano/components/form/_slider.scss */
+.x-slider {
+ border: 1px solid #000;
+ -moz-border-radius: 6px;
+ -webkit-border-radius: 6px;
+ -o-border-radius: 6px;
+ -ms-border-radius: 6px;
+ -khtml-border-radius: 6px;
+ border-radius: 6px;
+ background: #333;
+ overflow: hidden;
+ position: relative; }
+
+/* line 9, ../sass/murano/components/form/_slider.scss */
+.x-slider-thumb {
+ height: 8px;
+ width: 8px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -o-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -khtml-border-radius: 5px;
+ border-radius: 5px;
+ border: 1px solid #DDD;
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #aaaaaa), color-stop(100%, #cccccc));
+ background: -webkit-linear-gradient(#aaaaaa, #cccccc);
+ background: -moz-linear-gradient(#aaaaaa, #cccccc);
+ background: -o-linear-gradient(#aaaaaa, #cccccc);
+ background: linear-gradient(#aaaaaa, #cccccc);
+ position: absolute;
+ -moz-box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.35);
+ -webkit-box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.35);
+ -o-box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.35);
+ box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.35); }
+
+/* line 19, ../sass/murano/components/form/_slider.scss */
+.x-slider-thumb-over {
+ border-color: #FFF;
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #cccccc), color-stop(100%, #ffffff));
+ background: -webkit-linear-gradient(#cccccc, #ffffff);
+ background: -moz-linear-gradient(#cccccc, #ffffff);
+ background: -o-linear-gradient(#cccccc, #ffffff);
+ background: linear-gradient(#cccccc, #ffffff); }
+
+/* line 24, ../sass/murano/components/form/_slider.scss */
+.x-slider-horz {
+ -moz-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.15), 0 2px 5px 0 rgba(0, 0, 0, 0.25) inset;
+ -webkit-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.15), 0 2px 5px 0 rgba(0, 0, 0, 0.25) inset;
+ -o-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.15), 0 2px 5px 0 rgba(0, 0, 0, 0.25) inset;
+ box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.15), 0 2px 5px 0 rgba(0, 0, 0, 0.25) inset;
+ height: 10px; }
+ /* line 27, ../sass/murano/components/form/_slider.scss */
+ .x-slider-horz .x-slider-end {
+ padding-right: 12px;
+ height: 10px; }
+ /* line 31, ../sass/murano/components/form/_slider.scss */
+ .x-slider-horz .x-slider-inner {
+ height: 10px; }
+ /* line 34, ../sass/murano/components/form/_slider.scss */
+ .x-slider-horz .x-slider-thumb {
+ margin-left: 5px; }
+
+/* line 39, ../sass/murano/components/form/_slider.scss */
+.x-slider-vert {
+ -moz-box-shadow: 1px 0 0 0 rgba(255, 255, 255, 0.15), 2px 0 5px 0 rgba(0, 0, 0, 0.25) inset;
+ -webkit-box-shadow: 1px 0 0 0 rgba(255, 255, 255, 0.15), 2px 0 5px 0 rgba(0, 0, 0, 0.25) inset;
+ -o-box-shadow: 1px 0 0 0 rgba(255, 255, 255, 0.15), 2px 0 5px 0 rgba(0, 0, 0, 0.25) inset;
+ box-shadow: 1px 0 0 0 rgba(255, 255, 255, 0.15), 2px 0 5px 0 rgba(0, 0, 0, 0.25) inset;
+ width: 10px; }
+ /* line 42, ../sass/murano/components/form/_slider.scss */
+ .x-slider-vert .x-slider-inner {
+ width: 10px; }
+ /* line 45, ../sass/murano/components/form/_slider.scss */
+ .x-slider-vert .x-slider-end {
+ padding-bottom: 10px;
+ width: 10px; }
+ /* line 49, ../sass/murano/components/form/_slider.scss */
+ .x-slider-vert .x-slider-thumb {
+ margin-top: 4px;
+ margin-bottom: 4px; }
+
+/* line 1, ../sass/murano/components/_tab.scss */
+.x-tab {
+ -moz-border-radius: 3px 3px 0 0;
+ -webkit-border-radius: 3px 3px 0 0;
+ -o-border-radius: 3px 3px 0 0;
+ -ms-border-radius: 3px 3px 0 0;
+ -khtml-border-radius: 3px 3px 0 0;
+ border-radius: 3px 3px 0 0;
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ border-top: 1px solid rgba(255, 255, 255, 0.5);
+ border-bottom: none;
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-color: #000;
+ margin-top: 2px;
+ margin-left: 4px;
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
+ -o-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
+ padding: 3px 5px 6px 5px;
+ white-space: nowrap; }
+ /* line 13, ../sass/murano/components/_tab.scss */
+ .x-tab button {
+ color: #CCC;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.75); }
+
+/* line 21, ../sass/murano/components/_tab.scss */
+.x-tab-over {
+ border-color: #066cd1;
+ border-top-color: #439ffa; }
+ /* line 24, ../sass/murano/components/_tab.scss */
+ .x-tab-over button {
+ color: #FFF; }
+
+/* line 29, ../sass/murano/components/_tab.scss */
+.x-tab-active {
+ border-color: rgba(255, 255, 255, 0.35);
+ border-top-color: #FFF;
+ z-index: 3;
+ -moz-box-shadow: none;
+ -webkit-box-shadow: none;
+ -o-box-shadow: none;
+ box-shadow: none; }
+ /* line 32, ../sass/murano/components/_tab.scss */
+ .x-tab-active button {
+ color: #FFF; }
+
+/* line 39, ../sass/murano/components/_tab.scss */
+.x-tab button {
+ height: 14px;
+ line-height: 14px; }
+
+/* line 44, ../sass/murano/components/_tab.scss */
+.x-tab em {
+ display: block;
+ padding: 0 3px; }
+
+/* line 49, ../sass/murano/components/_tab.scss */
+.x-tab-closable em {
+ padding-right: 15px; }
+
+/* line 53, ../sass/murano/components/_tab.scss */
+.x-tab-close-btn {
+ position: absolute;
+ top: 3px;
+ right: 3px;
+ width: 11px;
+ height: 11px;
+ background: url("../img/tab/tab-close.png");
+ text-indent: -119988px; }
+
+/* line 63, ../sass/murano/components/_tab.scss */
+.x-tab-bar-strip {
+ z-index: 2;
+ border-top: 1px solid rgba(255, 255, 255, 0.35);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.35);
+ margin-top: -1px;
+ height: 4px;
+ background: #000;
+ position: relative; }
+
+/* line 73, ../sass/murano/components/_tab.scss */
+.x-box-scroller {
+ width: 18px !important;
+ height: 22px !important; }
+
+/* line 78, ../sass/murano/components/_tab.scss */
+.x-tabbar-scroll-left {
+ background: url("../img/tab-bar/l.png") !important; }
+ /* line 80, ../sass/murano/components/_tab.scss */
+ .x-tabbar-scroll-left-hover {
+ background-position: left center !important; }
+ /* line 83, ../sass/murano/components/_tab.scss */
+ .x-tabbar-scroll-left-disabled {
+ background-position: left top !important; }
+
+/* line 89, ../sass/murano/components/_tab.scss */
+.x-tabbar-scroll-right {
+ background: url("../img/tab-bar/r.png") !important; }
+ /* line 91, ../sass/murano/components/_tab.scss */
+ .x-tabbar-scroll-right-hover {
+ background-position: left center !important; }
+ /* line 94, ../sass/murano/components/_tab.scss */
+ .x-tabbar-scroll-right-disabled {
+ background-position: left top !important; }
+
+/* line 99, ../sass/murano/components/_tab.scss */
+.x-tab-inner {
+ display: block; }
+ /* line 101, ../sass/murano/components/_tab.scss */
+ .x-tab-icon-text-left .x-tab-inner {
+ padding-left: 20px;
+ background-repeat: no-repeat;
+ background-position: left top; }
+
+/* line 1, ../sass/murano/components/_tooltip.scss */
+.x-tip, .x-form-invalid-tip {
+ background-color: #05529f;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ padding: 4px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -o-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -khtml-border-radius: 5px;
+ border-radius: 5px;
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.25) inset;
+ -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.25) inset;
+ -o-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.25) inset;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.25) inset; }
+
+/* line 9, ../sass/murano/components/_tooltip.scss */
+.x-form-invalid-tip {
+ background-color: #800000; }
+
+/* line 13, ../sass/murano/components/_tooltip.scss */
+.x-tip-header {
+ font-weight: bold; }
+
+/* line 17, ../sass/murano/components/_tooltip.scss */
+.x-tip-body {
+ position: relative; }
+
+/* line 1, ../sass/murano/components/_progress_bar.scss */
+.x-progress {
+ position: relative;
+ height: 16px;
+ border: 1px solid #000;
+ text-align: center;
+ text-shadow: none;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ -o-border-radius: 10px;
+ -ms-border-radius: 10px;
+ -khtml-border-radius: 10px;
+ border-radius: 10px;
+ overflow: hidden;
+ background: #333;
+ -moz-box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.25);
+ -webkit-box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.25);
+ -o-box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.25);
+ box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.35) inset, 0 1px 0 0 rgba(255, 255, 255, 0.25);
+ padding: 1px 0;
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 1px; }
+
+/* line 16, ../sass/murano/components/_progress_bar.scss */
+.x-progress-bar {
+ background: #FFF;
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 14px;
+ border: 1px solid #666;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ -o-border-radius: 10px;
+ -ms-border-radius: 10px;
+ -khtml-border-radius: 10px;
+ border-radius: 10px;
+ background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #444444), color-stop(100%, #666666));
+ background: -webkit-linear-gradient(#444444, #666666);
+ background: -moz-linear-gradient(#444444, #666666);
+ background: -o-linear-gradient(#444444, #666666);
+ background: linear-gradient(#444444, #666666);
+ -moz-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.5);
+ -webkit-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.5);
+ -o-box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.5);
+ box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.5);
+ overflow: hidden; }
+
+/* line 29, ../sass/murano/components/_progress_bar.scss */
+.x-progress-text {
+ color: #FFF;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.35); }
+
+/* line 34, ../sass/murano/components/_progress_bar.scss */
+.x-progress-text-back {
+ color: #999; }
+
+/* line 1, ../sass/murano/components/_datepicker.scss */
+.x-datepicker {
+ background-color: #000;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #333333), color-stop(100%, #000000));
+ background-image: -webkit-linear-gradient(#333333, #000000);
+ background-image: -moz-linear-gradient(#333333, #000000);
+ background-image: -o-linear-gradient(#333333, #000000);
+ background-image: linear-gradient(#333333, #000000);
+ border-left: 1px solid #000;
+ border-right: 1px solid #000; }
+
+/* line 7, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-prev, .x-datepicker-next {
+ position: absolute;
+ top: 8px;
+ left: 5px; }
+ /* line 11, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-prev a, .x-datepicker-next a {
+ display: block;
+ height: 15px;
+ width: 15px;
+ background: url("../img/shared/btn-left.png"); }
+
+/* line 18, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-next {
+ right: 5px;
+ left: auto; }
+ /* line 21, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-next a {
+ background: url("../img/shared/btn-right.png"); }
+
+/* line 25, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-header, .x-datepicker-footer {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #333333), color-stop(100%, #111111));
+ background-image: -webkit-linear-gradient(#333333, #111111);
+ background-image: -moz-linear-gradient(#333333, #111111);
+ background-image: -o-linear-gradient(#333333, #111111);
+ background-image: linear-gradient(#333333, #111111);
+ border-bottom: 1px solid #000;
+ border-top: 1px solid #444;
+ padding: 3px 28px;
+ text-align: center; }
+
+/* line 32, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-inner {
+ font-size: inherit;
+ margin-bottom: 0;
+ width: 100%;
+ table-layout: fixed; }
+ /* line 36, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-inner th, .x-datepicker-inner td {
+ text-align: center; }
+ /* line 39, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-inner thead {
+ border-top: 1px solid #777;
+ color: #CCC;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #666666), color-stop(100%, #444444));
+ background-image: -webkit-linear-gradient(#666666, #444444);
+ background-image: -moz-linear-gradient(#666666, #444444);
+ background-image: -o-linear-gradient(#666666, #444444);
+ background-image: linear-gradient(#666666, #444444);
+ border-bottom: 1px solid #222; }
+
+/* line 48, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-inner a {
+ display: block;
+ text-decoration: none;
+ color: #CCC;
+ border: 1px solid transparent; }
+ /* line 53, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-inner a em, .x-datepicker-inner a span {
+ display: block; }
+ /* line 56, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-inner a em {
+ border: 1px solid transparent; }
+
+/* line 60, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-prevday a {
+ color: #666; }
+
+/* line 63, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-today span {
+ background-color: #555;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ -o-border-radius: 2px;
+ -ms-border-radius: 2px;
+ -khtml-border-radius: 2px;
+ border-radius: 2px; }
+
+/* line 67, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-selected a {
+ border-color: rgba(0, 0, 0, 0.25); }
+ /* line 69, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-selected a em {
+ border-color: #066cd1;
+ border-top-color: #439ffa;
+ border-bottom-color: #05529f; }
+ /* line 74, ../sass/murano/components/_datepicker.scss */
+ .x-datepicker-selected a span {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ color: #FFF;
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+ -o-border-radius: 0;
+ -ms-border-radius: 0;
+ -khtml-border-radius: 0;
+ border-radius: 0; }
+
+/* line 81, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker {
+ background: #000;
+ font-size: 11px; }
+ /* line 83, ../sass/murano/components/_datepicker.scss */
+ .x-monthpicker a {
+ text-decoration: none;
+ color: #CCC; }
+
+/* line 89, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker-years {
+ width: 88px;
+ float: right; }
+
+/* line 93, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker-months {
+ width: 87px;
+ float: left;
+ border-right: 1px solid #444; }
+
+/* line 98, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker-item {
+ width: 43px;
+ float: left;
+ margin: 4px 0;
+ text-align: center; }
+ /* line 103, ../sass/murano/components/_datepicker.scss */
+ .x-monthpicker-item a {
+ display: block;
+ border: 1px solid transparent;
+ margin: 0 3px;
+ padding: 2px 0;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ -o-border-radius: 3px;
+ -ms-border-radius: 3px;
+ -khtml-border-radius: 3px;
+ border-radius: 3px; }
+ /* line 106, ../sass/murano/components/_datepicker.scss */
+ .x-monthpicker-item a:hover {
+ background-color: #333; }
+ /* line 113, ../sass/murano/components/_datepicker.scss */
+ .x-monthpicker-item .x-monthpicker-selected {
+ background-color: #333;
+ border: 1px solid #555;
+ border-top-color: #999;
+ border-bottom-color: #444;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ color: #FFF; }
+
+/* line 122, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker-yearnav-prev, .x-monthpicker-yearnav-next {
+ margin: 6px 12px 6px 15px;
+ float: left;
+ display: block;
+ height: 15px;
+ width: 15px;
+ background: url("../img/shared/btn-left.png"); }
+
+/* line 130, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker-yearnav-next {
+ background: url("../img/shared/btn-right.png"); }
+
+/* line 133, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker .x-btn, .x-monthpicker .x-btn-pressed {
+ width: 80px;
+ float: left;
+ margin: 4px; }
+
+/* line 138, ../sass/murano/components/_datepicker.scss */
+.x-monthpicker-buttons {
+ border-top: 1px solid #777;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #666666), color-stop(100%, #444444));
+ background-image: -webkit-linear-gradient(#666666, #444444);
+ background-image: -moz-linear-gradient(#666666, #444444);
+ background-image: -o-linear-gradient(#666666, #444444);
+ background-image: linear-gradient(#666666, #444444);
+ padding: 2px 1px;
+ overflow: hidden;
+ *zoom: 1; }
+
+/* line 145, ../sass/murano/components/_datepicker.scss */
+.x-datepicker-footer {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #666666), color-stop(100%, #444444));
+ background-image: -webkit-linear-gradient(#666666, #444444);
+ background-image: -moz-linear-gradient(#666666, #444444);
+ background-image: -o-linear-gradient(#666666, #444444);
+ background-image: linear-gradient(#666666, #444444);
+ border-top-color: #777;
+ border-bottom-color: #222; }
+
+/* line 1, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-west {
+ background: transparent url("../img/sizer/w.png") left center no-repeat !important; }
+
+/* line 4, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-east {
+ background: transparent url("../img/sizer/e.png") right center no-repeat !important; }
+
+/* line 7, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-north {
+ background: transparent url("../img/sizer/n.png") top center no-repeat !important; }
+
+/* line 10, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-south {
+ background: transparent url("../img/sizer/s.png") bottom center no-repeat !important; }
+
+/* line 13, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-northwest {
+ background: transparent url("../img/sizer/nw.png") left top no-repeat !important; }
+
+/* line 16, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-northeast {
+ background: transparent url("../img/sizer/ne.png") right top no-repeat !important; }
+
+/* line 19, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-southwest {
+ background: transparent url("../img/sizer/sw.png") left bottom no-repeat !important; }
+
+/* line 22, ../sass/murano/components/_sizer.scss */
+.x-resizable-handle-southeast {
+ background: transparent url("../img/sizer/se.png") right bottom no-repeat !important; }
+
+/* line 10, ../sass/murano/components/_tree.scss */
+.x-tree-panel .x-grid-row-selected {
+ background-color: #000;
+ color: #FFF; }
+ /* line 13, ../sass/murano/components/_tree.scss */
+ .x-tree-panel .x-grid-row-selected td {
+ -moz-box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
+ -webkit-box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
+ -o-box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1);
+ box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.1); }
+
+/* line 19, ../sass/murano/components/_tree.scss */
+.x-tree-no-lines .x-tree-elbow {
+ background-color: transparent; }
+
+/* line 23, ../sass/murano/components/_tree.scss */
+.x-tree-no-lines .x-tree-elbow-end {
+ background-color: transparent; }
+
+/* line 27, ../sass/murano/components/_tree.scss */
+.x-tree-no-lines .x-tree-elbow-line {
+ background-color: transparent; }
+
+/* line 32, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-plus {
+ background: transparent no-repeat 0 0; }
+
+/* line 36, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-end-plus {
+ background: transparent no-repeat 0 0; }
+
+/* line 40, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-end-minus {
+ background: transparent no-repeat -16px 0; }
+
+/* line 44, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-minus {
+ background: transparent no-repeat -16px 0; }
+
+/* line 48, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow {
+ background-color: transparent !important; }
+
+/* line 52, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-end {
+ background-color: transparent !important; }
+
+/* line 56, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-line {
+ background-color: transparent !important; }
+
+/* line 62, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-expander-over .x-tree-elbow-plus,
+.x-tree-arrows .x-tree-expander-over .x-tree-elbow-end-plus {
+ background-position: -32px 0; }
+
+/* line 67, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-expander-over .x-tree-elbow-minus,
+.x-tree-arrows .x-tree-expander-over .x-tree-elbow-end-minus {
+ background-position: -48px 0; }
+
+/* line 72, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-grid-tree-node-expanded .x-tree-elbow-plus,
+.x-tree-arrows .x-grid-tree-node-expanded .x-tree-elbow-end-plus {
+ background-position: -16px 0; }
+
+/* line 77, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-grid-tree-node-expanded .x-tree-expander-over .x-tree-elbow-plus,
+.x-tree-arrows .x-grid-tree-node-expanded .x-tree-expander-over .x-tree-elbow-end-plus {
+ background-position: -48px 0; }
+
+/* line 84, ../sass/murano/components/_tree.scss */
+.x-tree-elbow-plus,
+.x-tree-elbow-minus,
+.x-tree-elbow-end-plus,
+.x-tree-elbow-end-minus {
+ cursor: pointer; }
+
+/* line 90, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-tree-elbow {
+ background-image: url("../img/tree/elbow.gif"); }
+/* line 94, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-tree-elbow-end {
+ background-image: url("../img/tree/elbow-end.gif"); }
+/* line 98, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-tree-elbow-plus {
+ background-image: url("../../fugue-icons/icons-shadowless/plus-small-white.png"); }
+/* line 103, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-tree-elbow-end-plus {
+ background-image: url("../../fugue-icons/icons-shadowless/plus-small-white.png"); }
+/* line 108, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-grid-tree-node-expanded .x-tree-elbow-plus {
+ background-image: url("../../fugue-icons/icons-shadowless/minus-small-white.png"); }
+/* line 113, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-grid-tree-node-expanded .x-tree-elbow-end-plus {
+ background-image: url("../../fugue-icons/icons-shadowless/minus-small-white.png"); }
+/* line 118, ../sass/murano/components/_tree.scss */
+.x-tree-lines .x-tree-elbow-line {
+ background-image: url("../img/tree/elbow-line.gif"); }
+
+/* line 125, ../sass/murano/components/_tree.scss */
+.x-tree-no-lines .x-tree-elbow-plus,
+.x-tree-no-lines .x-tree-elbow-end-plus {
+ background-image: url("../img/tree/elbow-plus-nl.gif"); }
+/* line 130, ../sass/murano/components/_tree.scss */
+.x-tree-no-lines .x-grid-tree-node-expanded .x-tree-elbow-plus,
+.x-tree-no-lines .x-grid-tree-node-expanded .x-tree-elbow-end-plus {
+ background-image: url("../img/tree/elbow-end-minus-nl.gif"); }
+
+/* line 139, ../sass/murano/components/_tree.scss */
+.x-tree-arrows .x-tree-elbow-plus,
+.x-tree-arrows .x-tree-elbow-minus,
+.x-tree-arrows .x-tree-elbow-end-plus,
+.x-tree-arrows .x-tree-elbow-end-minus {
+ background-image: url("../img/tree/arrows.gif"); }
+
+/* line 144, ../sass/murano/components/_tree.scss */
+.x-tree-icon {
+ margin-right: 3px; }
+
+/* line 153, ../sass/murano/components/_tree.scss */
+.x-tree-elbow,
+.x-tree-elbow-end,
+.x-tree-elbow-plus,
+.x-tree-elbow-end-plus,
+.x-tree-elbow-empty,
+.x-tree-elbow-line {
+ height: 16px;
+ width: 16px; }
+
+/* line 158, ../sass/murano/components/_tree.scss */
+.x-tree-icon-leaf {
+ width: 16px;
+ background-image: url("../../fugue-icons/icons-shadowless/leaf.png"); }
+
+/* line 163, ../sass/murano/components/_tree.scss */
+.x-tree-icon-parent {
+ width: 16px;
+ background-image: url("../../fugue-icons/icons-shadowless/folder-horizontal.png"); }
+
+/* line 168, ../sass/murano/components/_tree.scss */
+.x-grid-tree-node-expanded .x-tree-icon-parent {
+ background-image: url("../../fugue-icons/icons-shadowless/folder-horizontal-open.png"); }
+
+/* line 172, ../sass/murano/components/_tree.scss */
+.x-grid-rowbody {
+ padding: 0; }
+
+/* line 176, ../sass/murano/components/_tree.scss */
+.x-tree-panel .x-grid-cell-inner {
+ padding: 0px; }
+
+/* line 180, ../sass/murano/components/_tree.scss */
+.x-tree-panel .x-grid-row .x-grid-cell {
+ border: none; }
+
+/* line 184, ../sass/murano/components/_tree.scss */
+.x-tree-panel .x-grid-row .x-grid-cell-inner {
+ height: 16px;
+ line-height: 16px;
+ vertical-align: middle;
+ cursor: pointer; }
+ /* line 191, ../sass/murano/components/_tree.scss */
+ .x-tree-panel .x-grid-row .x-grid-cell-inner img {
+ float: left; }
+
+/* line 197, ../sass/murano/components/_tree.scss */
+.x-ie .x-tree-panel .x-grid-row .x-grid-cell-inner {
+ white-space: normal; }
+
+/* line 203, ../sass/murano/components/_tree.scss */
+.x-tree-checkbox {
+ float: left;
+ margin: 2px 3px 0 0;
+ display: block;
+ width: 16px;
+ height: 16px;
+ background: url('../img/url("../img/form/unchecked.png")') no-repeat;
+ overflow: hidden;
+ padding: 0;
+ border: 0; }
+ /* line 215, ../sass/murano/components/_tree.scss */
+ .x-tree-checkbox::-moz-focus-inner {
+ padding: 0;
+ border: 0; }
+
+/* Hack for IE; causes alignment problem in IE9 standards mode so exclude that */
+/* line 223, ../sass/murano/components/_tree.scss */
+.x-nbr.x-ie .x-tree-checkbox {
+ font-size: 0; }
+
+/* line 228, ../sass/murano/components/_tree.scss */
+.x-tree-checkbox-checked {
+ background: url('../img/url("../img/form/checked.png")') no-repeat; }
+
+/* line 233, ../sass/murano/components/_tree.scss */
+.x-tree-panel .x-grid-cell-inner {
+ border-width: 0 !important; }
+
+/* line 240, ../sass/murano/components/_tree.scss */
+.x-gecko .x-tree-panel .x-grid-row .x-grid-cell-inner {
+ line-height: 14px; }
+
+/* line 246, ../sass/murano/components/_tree.scss */
+.x-tree-drop-ok-append .x-dd-drop-icon {
+ background-image: url("../img/tree/drop-append.gif"); }
+
+/* line 250, ../sass/murano/components/_tree.scss */
+.x-tree-drop-ok-above .x-dd-drop-icon {
+ background-image: url("../img/tree/drop-above.gif"); }
+
+/* line 254, ../sass/murano/components/_tree.scss */
+.x-tree-drop-ok-below .x-dd-drop-icon {
+ background-image: url("../img/tree/drop-below.gif"); }
+
+/* line 258, ../sass/murano/components/_tree.scss */
+.x-tree-drop-ok-between .x-dd-drop-icon {
+ background-image: url("../img/tree/drop-between.gif"); }
+
+/* line 262, ../sass/murano/components/_tree.scss */
+.x-grid-tree-loading .x-tree-icon {
+ background-image: url("../img/tree/loading.gif"); }
+
+/* line 266, ../sass/murano/components/_tree.scss */
+.x-tree-ddindicator {
+ height: 1px;
+ border-width: 1px 0px 0px;
+ border-style: dotted;
+ border-color: green; }
+
+/* line 273, ../sass/murano/components/_tree.scss */
+.x-grid-tree-loading span {
+ font-style: italic;
+ color: #444444; }
+
+/* line 278, ../sass/murano/components/_tree.scss */
+.x-tree-animator-wrap {
+ overflow: hidden; }
+
+/* line 1, ../sass/murano/components/_menu.scss */
+.x-menu {
+ -moz-box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.35);
+ -webkit-box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.35);
+ -o-box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.35);
+ box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.35);
+ white-space: nowrap; }
+
+/* line 7, ../sass/murano/components/_menu.scss */
+.x-menu-body {
+ position: absolute; }
+
+/* line 11, ../sass/murano/components/_menu.scss */
+.x-menu-item {
+ padding: 2px; }
+
+/* line 15, ../sass/murano/components/_menu.scss */
+.x-menu-item-link {
+ padding: 4px;
+ border: 1px solid transparent;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ -o-border-radius: 5px;
+ -ms-border-radius: 5px;
+ -khtml-border-radius: 5px;
+ border-radius: 5px;
+ text-decoration: none;
+ display: block;
+ color: #FFF; }
+
+/* line 24, ../sass/murano/components/_menu.scss */
+.x-menu-item-active .x-menu-item-link {
+ border-color: #066cd1;
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #066cd1), color-stop(100%, #05529f));
+ background-image: -webkit-linear-gradient(#066cd1, #05529f);
+ background-image: -moz-linear-gradient(#066cd1, #05529f);
+ background-image: -o-linear-gradient(#066cd1, #05529f);
+ background-image: linear-gradient(#066cd1, #05529f);
+ -moz-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ -webkit-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ -o-box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset;
+ box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.15) inset; }
+
+/* line 30, ../sass/murano/components/_menu.scss */
+.x-menu-item-icon {
+ width: 16px;
+ height: 16px;
+ margin-right: 5px;
+ float: left; }
+
+/* line 38, ../sass/murano/components/_menu.scss */
+.x-menu-item-unchecked .x-menu-item-icon {
+ background: url("../img/form/unchecked.png"); }
+/* line 41, ../sass/murano/components/_menu.scss */
+.x-menu-item-unchecked .x-menu-group-icon {
+ background: url("../img/form/unradioed.png"); }
+
+/* line 46, ../sass/murano/components/_menu.scss */
+.x-menu-item-checked .x-menu-item-icon {
+ background: url("../img/form/checked.png"); }
+/* line 49, ../sass/murano/components/_menu.scss */
+.x-menu-item-checked .x-menu-group-icon {
+ background: url("../img/form/radioed.png"); }
+
+/* line 54, ../sass/murano/components/_menu.scss */
+.x-menu-item-separator {
+ height: 0;
+ padding: 0;
+ margin: 3px 9px 3px 10px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.25); }
+
+/* line 3, ../sass/murano/components/_scroller.scss */
+.x-scroller {
+ border: none !important; }
+ /* line 5, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar {
+ width: 16px;
+ height: 16px; }
+ /* line 8, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar-track {
+ background: transparent; }
+ /* line 11, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar-track-piece:start {
+ margin-left: 1px;
+ margin-top: 1px; }
+ /* line 15, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar-track-piece:end {
+ margin-right: 1px;
+ margin-bottom: 1px; }
+ /* line 19, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar-thumb {
+ border: 1px solid #000;
+ background-color: #666666;
+ -moz-border-radius: 8px;
+ -webkit-border-radius: 8px;
+ -o-border-radius: 8px;
+ -ms-border-radius: 8px;
+ -khtml-border-radius: 8px;
+ border-radius: 8px;
+ -moz-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35) inset, 0 -1px 0 0 black inset;
+ -webkit-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35) inset, 0 -1px 0 0 black inset;
+ -o-box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35) inset, 0 -1px 0 0 black inset;
+ box-shadow: 0 1px 0 0 rgba(255, 255, 255, 0.35) inset, 0 -1px 0 0 black inset; }
+ /* line 24, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar-thumb:hover {
+ background-color: #737373; }
+ /* line 27, ../sass/murano/components/_scroller.scss */
+ .x-scroller::-webkit-scrollbar-thumb:active {
+ background-color: gray; }
+
+/* line 34, ../sass/murano/components/_scroller.scss */
+.x-scroller-vertical::-webkit-scrollbar-thumb {
+ background-image: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background-image: -webkit-linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -moz-linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -o-linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: linear-gradient(left, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%); }
+
+/* line 37, ../sass/murano/components/_scroller.scss */
+.x-scroller-horizontal::-webkit-scrollbar-thumb {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%);
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%); }
+
+/* line 1, ../sass/murano/components/_splitter.scss */
+.x-splitter {
+ background-color: #000; }
+
+/* line 1, ../sass/murano/components/_icons.scss */
+.x-tbar-page-prev {
+ background: transparent url("../../fugue-icons/icons-shadowless/control-180.png") center center no-repeat; }
+
+/* line 4, ../sass/murano/components/_icons.scss */
+.x-tbar-page-first {
+ background: transparent url("../../fugue-icons/icons-shadowless/control-stop-180.png") center center no-repeat; }
+
+/* line 7, ../sass/murano/components/_icons.scss */
+.x-tbar-page-next {
+ background: transparent url("../../fugue-icons/icons-shadowless/control.png") center center no-repeat; }
+
+/* line 10, ../sass/murano/components/_icons.scss */
+.x-tbar-page-last {
+ background: transparent url("../../fugue-icons/icons-shadowless/control-stop.png") center center no-repeat; }
+
+/* line 13, ../sass/murano/components/_icons.scss */
+.x-tbar-loading {
+ background: transparent url("../../fugue-icons/icons-shadowless/arrow-circle-double-135.png") center center no-repeat; }
+
+/**
+ * @var {string} $prefix
+ * The prefix to be applied to all CSS selectors. If this is changed, it must also be changed in your
+ * JavaScript application.
+ */
+/**
+ * @var {string} $theme-name
+ * The name of the theme. This must match the the output directory of the images.
+ * (defaults to 'default')
+ */
+/**
+ * @var {boolean/string} $relative-image-path-for-uis
+ * True to use a relative image path for all new UIs. If true, the path will be "../images/".
+ * It can also be a string of the path value.
+ * It defaults to false, which means it will look for the images in the ExtJS SDK folder.
+ */
+/**
+ * @var {string} $font-family
+ * The default font-family to be used throughout the theme.
+ */
+/**
+ * @var {string} $base-gradient
+ * The base gradient to be used throughout the theme.
+ */
+/**
+ * @var {color} $base-color
+ * The base color to be used throughout the theme.
+ */
+/**
+ * @var {boolean} $include-ie
+ * True to include Internet Explorer specific rules
+ */
+/**
+ * @var {boolean} $include-ff
+ * True to include Firefox specific rules
+ */
+/**
+ * @var {boolean} $include-chrome
+ * True to include Chrome specific rules
+ */
+/**
+ * @var {boolean} $include-safari
+ * True to include Safari specific rules
+ */
+/**
+ * @var {boolean} $include-opera
+ * True to include Opera specific rules
+ */
+/**
+ * @var {boolean} $include-webkit
+ * True to include Webkit specific rules
+ */
+/**
+ * @var {boolean} $compile-all
+ * True to copile all CSS, even if above include rules are false
+ */
+/**
+ * @var {boolean} $scope-reset-css
+ * True to scope the reset CSS within the $prefix variable.
+ */
+/**
+ * @var {color} $css-shadow-background-color
+ * The base color for CSS shadows
+ */
+/**
+ * Toolbar buttons
+ */
+/**
+ * @class Ext.form.*
+ */
+/**
+ * @class Ext.form.field.Base
+ */
+/**
+ * @class Ext.form.field.TextArea
+ */
+/**
+ * @class Ext.form.Label
+ */
+/**
+ * @class Ext.form.field.Checkbox
+ */
+/**
+ * @class Ext.form.field.Radio
+ */
+/**
+ * Error messages
+ */
+/**
+ * Trigger Field
+ */
+/**
+ * Fieldsets
+ */
+/**
+ * @mixin background-gradient
+ *
+ * @param {Color} $background-color The background color of the gradient
+ * @param {String/List} $type The type of gradient to be used. Can either be a String which is a predefined gradient, or it can
+ * can be a list of color_stops. If none is set, it will still set the `background-color` to the $background-color.
+ * @param {String} $direction The direction of the gradient. Can either me `top` or `left`. (defaults to `top`)
+ */
+/* line 69, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+html, body, div, dl, dt, dd, ul, ol, li, h1, h2, h3,
+h4, h5, h6, pre, code, form, fieldset, legend,
+input, textarea, p, blockquote, th, td {
+ margin: 0;
+ padding: 0; }
+
+/* line 74, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+table {
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+/* line 79, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+fieldset, img {
+ border: 0; }
+
+/* line 84, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+address, caption, cite, code,
+dfn, em, strong, th, var {
+ font-style: normal;
+ font-weight: normal; }
+
+/* line 89, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+li {
+ list-style: none; }
+
+/* line 93, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+caption, th {
+ text-align: left; }
+
+/* line 97, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+h1, h2, h3, h4, h5, h6 {
+ font-size: 100%; }
+
+/* line 102, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+q:before,
+q:after {
+ content: ""; }
+
+/* line 106, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+abbr, acronym {
+ border: 0;
+ font-variant: normal; }
+
+/* line 111, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+sup {
+ vertical-align: text-top; }
+
+/* line 115, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+sub {
+ vertical-align: text-bottom; }
+
+/* line 119, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+input, textarea, select {
+ font-family: inherit;
+ font-size: inherit;
+ font-weight: inherit; }
+
+/* line 125, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+*:focus {
+ outline: none; }
+
+/* line 131, ../../extjs/resources/themes/stylesheets/ext4/default/core/_reset.scss */
+.x-border-box .x-reset,
+.x-border-box .x-reset * {
+ box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ -ms-box-sizing: border-box;
+ -webkit-box-sizing: border-box; }
+
+/* line 1, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+body {
+ color: white;
+ font-size: 12px;
+ font-family: "Lucida Grande", "Lucida Sans", Tahoma, Verdana, sans-serif; }
+
+/* line 7, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-clear {
+ overflow: hidden;
+ clear: both;
+ height: 0;
+ width: 0;
+ font-size: 0;
+ line-height: 0; }
+
+/* line 16, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-layer {
+ position: absolute;
+ overflow: hidden;
+ zoom: 1; }
+
+/* line 22, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-shim {
+ position: absolute;
+ left: 0;
+ top: 0;
+ overflow: hidden;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
+ opacity: 0; }
+
+/* line 30, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-hide-display {
+ display: none !important; }
+
+/* line 34, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-hide-visibility {
+ visibility: hidden !important; }
+
+/* line 38, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-item-disabled {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40);
+ opacity: 0.4; }
+
+/* line 42, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-ie6 .x-item-disabled {
+ filter: none; }
+
+/* line 47, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-hidden,
+.x-hide-offsets {
+ display: block !important;
+ position: absolute !important;
+ left: -10000px !important;
+ top: -10000px !important; }
+
+/* line 54, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-hide-nosize {
+ height: 0 !important;
+ width: 0 !important; }
+
+/* line 59, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-masked-relative {
+ position: relative; }
+
+/* line 65, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-ie6 .x-masked select,
+.x-ie6.x-body-masked select {
+ visibility: hidden !important; }
+
+/* line 71, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-css-shadow {
+ position: absolute;
+ -moz-border-radius: 5px 5px;
+ -webkit-border-radius: 5px 5px;
+ -o-border-radius: 5px 5px;
+ -ms-border-radius: 5px 5px;
+ -khtml-border-radius: 5px 5px;
+ border-radius: 5px 5px; }
+
+/* line 76, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-ie-shadow {
+ background-color: #777;
+ display: none;
+ position: absolute;
+ overflow: hidden;
+ zoom: 1; }
+
+/* line 84, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow {
+ display: none;
+ position: absolute;
+ overflow: hidden; }
+
+/* line 90, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow * {
+ overflow: hidden; }
+
+/* line 94, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow * {
+ padding: 0;
+ border: 0;
+ margin: 0;
+ clear: none;
+ zoom: 1; }
+
+/* top bottom */
+/* line 104, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xstc,
+.x-frame-shadow .xsbc {
+ height: 6px;
+ float: left; }
+
+/* line 109, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsc {
+ width: 100%; }
+
+/* line 113, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsml {
+ background: transparent repeat-y 0 0; }
+
+/* line 117, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsmr {
+ background: transparent repeat-y -6px 0; }
+
+/* line 121, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xstl {
+ background: transparent no-repeat 0 0; }
+
+/* line 125, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xstc {
+ background: transparent repeat-x 0 -30px; }
+
+/* line 129, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xstr {
+ background: transparent repeat-x 0 -18px; }
+
+/* line 133, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsbl {
+ background: transparent no-repeat 0 -12px; }
+
+/* line 137, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsbc {
+ background: transparent repeat-x 0 -36px; }
+
+/* line 141, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsbr {
+ background: transparent repeat-x 0 -6px; }
+
+/* line 149, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xstl,
+.x-frame-shadow .xstc,
+.x-frame-shadow .xstr,
+.x-frame-shadow .xsbl,
+.x-frame-shadow .xsbc,
+.x-frame-shadow .xsbr {
+ width: 6px;
+ height: 6px;
+ float: left;
+ background-image: url('../extjs/resources/themes/images/default/shared/shadow.png'); }
+
+/* line 157, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsml,
+.x-frame-shadow .xsmr {
+ width: 6px;
+ float: left;
+ height: 100%;
+ background-image: url('../extjs/resources/themes/images/default/shared/shadow-lr.png'); }
+
+/* line 164, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xsmc {
+ float: left;
+ height: 100%;
+ background-image: url('../extjs/resources/themes/images/default/shared/shadow-c.png'); }
+
+/* line 171, ../../extjs/resources/themes/stylesheets/ext4/default/core/_core.scss */
+.x-frame-shadow .xst,
+.x-frame-shadow .xsb {
+ height: 6px;
+ overflow: hidden;
+ width: 100%; }
+
+/* line 1, ../../extjs/resources/themes/stylesheets/ext4/default/util/_focus.scss */
+.x-focus-element {
+ position: absolute;
+ top: -10px;
+ left: -10px;
+ width: 0px;
+ height: 0px; }
+
+/* line 9, ../../extjs/resources/themes/stylesheets/ext4/default/util/_focus.scss */
+.x-focus-frame {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ z-index: 100000000;
+ width: 0px;
+ height: 0px; }
+
+/* line 21, ../../extjs/resources/themes/stylesheets/ext4/default/util/_focus.scss */
+.x-focus-frame-top,
+.x-focus-frame-bottom,
+.x-focus-frame-left,
+.x-focus-frame-right {
+ position: absolute;
+ top: 0px;
+ left: 0px; }
+
+/* line 28, ../../extjs/resources/themes/stylesheets/ext4/default/util/_focus.scss */
+.x-focus-frame-top,
+.x-focus-frame-bottom {
+ border-top: solid 2px #15428b;
+ height: 2px; }
+
+/* line 34, ../../extjs/resources/themes/stylesheets/ext4/default/util/_focus.scss */
+.x-focus-frame-left,
+.x-focus-frame-right {
+ border-left: solid 2px #15428b;
+ width: 2px; }
+
+/**
+ * @class Ext.Button
+ * Used to create the base structure of an Ext.Button
+ */
+/**
+ * @mixin extjs-btn-group-ui
+ * @class Ext.ButtonGroup
+ */
+/**
+ * @class Ext.menu.*
+ */
+/**
+ * @class Ext.Panel
+ * Used to create the base structure of an Ext.Panel
+ */
+/**
+ * @class Ext.Panel
+ * Used to create a visual theme for an Ext.Panel
+ */
+/**
+ * @mixin ext-toolbar-ui
+ * @class Ext.toolbar.Toolbar
+ * @param {String} $ui The name of the UI
+ * @param {Color} $background-color The background color of the toolbar (defaults to transparent)
+ * @param {Gradient/color-stops} $background-gradient The background gradient of the toolbar (defaults to null)
+ * @param {Color} $border-color The border color of the toolbar (defaults to null)
+ */
+/**
+ * @class Ext.Window
+ * Used to create a visual theme for an Ext.Panel
+ */
+/**
+ * @class Ext.tab.Bar
+ */
+/**
+ * @class Ext.Tab
+ */
+/**
+ * @class Ext.LoadMask
+ * Component used to mask a component
+ */
+/* line 5, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_loadmask.scss */
+.x-mask {
+ z-index: 100;
+ position: absolute;
+ top: 0;
+ left: 0;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
+ opacity: 0.5;
+ width: 100%;
+ height: 100%;
+ zoom: 1;
+ background: #cccccc; }
+
+/* line 21, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_loadmask.scss */
+.x-mask-msg {
+ z-index: 20001;
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: 2px;
+ border: 1px solid;
+ border-color: #99bbe8;
+ background-image: none;
+ background-color: #dfe8f6; }
+ /* line 40, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_loadmask.scss */
+ .x-mask-msg div {
+ padding: 5px 10px 5px 25px;
+ background-image: url('../extjs/resources/themes/images/default/grid/loading.gif');
+ background-repeat: no-repeat;
+ background-position: 5px center;
+ cursor: wait;
+ border: 1px solid #a3bad9;
+ background-color: #eeeeee;
+ color: #222222;
+ font: normal 11px "Lucida Grande", "Lucida Sans", Tahoma, Verdana, sans-serif; }
+
+/**
+ * @mixin extjs-progress-ui
+ */
+/**
+ * W3C Suggested Default style sheet for HTML 4
+ * http://www.w3.org/TR/CSS21/sample.html
+ */
+/* line 7, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drag-repair .x-dd-drag-ghost {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60);
+ opacity: 0.6; }
+/* line 11, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drag-repair .x-dd-drop-icon {
+ display: none; }
+
+/* line 16, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drag-ghost {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=85)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=85);
+ opacity: 0.85;
+ padding: 5px;
+ padding-left: 20px;
+ white-space: nowrap;
+ color: #000;
+ font: normal 11px "Lucida Grande", "Lucida Sans", Tahoma, Verdana, sans-serif;
+ border: 1px solid;
+ border-color: #ddd #bbb #bbb #ddd;
+ background-color: #fff; }
+
+/* line 33, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drop-icon {
+ position: absolute;
+ top: 3px;
+ left: 3px;
+ display: block;
+ width: 16px;
+ height: 16px;
+ background-color: transparent;
+ background-position: center;
+ background-repeat: no-repeat;
+ z-index: 1; }
+
+/* line 50, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-view-selector {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 0;
+ background-color: #c3daf9;
+ border: 1px dotted #3399bb;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
+ opacity: 0.5;
+ zoom: 1; }
+
+/* line 65, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drop-nodrop .x-dd-drop-icon {
+ background-image: url('../extjs/resources/themes/images/default/dd/drop-no.gif'); }
+
+/* line 69, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drop-ok .x-dd-drop-icon {
+ background-image: url('../extjs/resources/themes/images/default/dd/drop-yes.gif'); }
+
+/* line 73, ../../extjs/resources/themes/stylesheets/ext4/default/util/_dragdrop.scss */
+.x-dd-drop-ok-add .x-dd-drop-icon {
+ background-image: url('../extjs/resources/themes/images/default/dd/drop-add.gif'); }
+
+/* line 2, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle {
+ position: absolute;
+ z-index: 100;
+ font-size: 1px;
+ line-height: 6px;
+ overflow: hidden;
+ zoom: 1;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
+ opacity: 0;
+ background-color: #fff; }
+
+/* line 19, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-east {
+ width: 6px;
+ height: 100%;
+ right: 0;
+ top: 0; }
+
+/* line 28, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-east {
+ cursor: e-resize; }
+
+/* line 33, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-south {
+ width: 100%;
+ height: 6px;
+ left: 0;
+ bottom: 0; }
+
+/* line 42, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-south {
+ cursor: s-resize; }
+
+/* line 47, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-west {
+ width: 6px;
+ height: 100%;
+ left: 0;
+ top: 0; }
+
+/* line 56, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-west {
+ cursor: w-resize; }
+
+/* line 61, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-north {
+ width: 100%;
+ height: 6px;
+ left: 0;
+ top: 0; }
+
+/* line 70, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-north {
+ cursor: n-resize; }
+
+/* line 75, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-southeast {
+ width: 6px;
+ height: 6px;
+ right: 0;
+ bottom: 0;
+ z-index: 101; }
+
+/* line 86, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-southeast {
+ cursor: se-resize; }
+
+/* line 91, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-northwest {
+ width: 6px;
+ height: 6px;
+ left: 0;
+ top: 0;
+ z-index: 101; }
+
+/* line 102, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-northwest {
+ cursor: nw-resize; }
+
+/* line 107, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-northeast {
+ width: 6px;
+ height: 6px;
+ right: 0;
+ top: 0;
+ z-index: 101; }
+
+/* line 118, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-northeast {
+ cursor: ne-resize; }
+
+/* line 123, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-handle-southwest {
+ width: 6px;
+ height: 6px;
+ left: 0;
+ bottom: 0;
+ z-index: 101; }
+
+/* line 134, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-southwest {
+ cursor: sw-resize; }
+
+/*IE rounding error*/
+/* line 141, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-ie .x-resizable-handle-east {
+ margin-right: -1px;
+ /*IE rounding error*/ }
+/* line 145, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-ie .x-resizable-handle-south {
+ margin-bottom: -1px; }
+
+/* line 150, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle, .x-resizable-pinned .x-resizable-handle {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+ opacity: 1; }
+
+/* line 154, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-window .x-window-handle {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
+ opacity: 0; }
+
+/* line 158, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-window-collapsed .x-window-handle {
+ display: none; }
+
+/* line 162, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-proxy {
+ border: 1px dashed #3b5a82;
+ position: absolute;
+ left: 0;
+ top: 0;
+ overflow: hidden;
+ z-index: 50000; }
+
+/* line 171, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-overlay {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ display: none;
+ z-index: 200000;
+ background-color: #fff;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
+ opacity: 0; }
+
+/* line 191, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-east,
+.x-resizable-over .x-resizable-handle-west,
+.x-resizable-pinned .x-resizable-handle-east,
+.x-resizable-pinned .x-resizable-handle-west {
+ background-position: left;
+ background-image: url('../extjs/resources/themes/images/default/sizer/e-handle.gif'); }
+/* line 197, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-south,
+.x-resizable-over .x-resizable-handle-north,
+.x-resizable-pinned .x-resizable-handle-south,
+.x-resizable-pinned .x-resizable-handle-north {
+ background-position: top;
+ background-image: url('../extjs/resources/themes/images/default/sizer/s-handle.gif'); }
+/* line 202, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-southeast,
+.x-resizable-pinned .x-resizable-handle-southeast {
+ background-position: top left;
+ background-image: url('../extjs/resources/themes/images/default/sizer/se-handle.gif'); }
+/* line 207, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-northwest,
+.x-resizable-pinned .x-resizable-handle-northwest {
+ background-position: bottom right;
+ background-image: url('../extjs/resources/themes/images/default/sizer/nw-handle.gif'); }
+/* line 212, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-northeast,
+.x-resizable-pinned .x-resizable-handle-northeast {
+ background-position: bottom left;
+ background-image: url('../extjs/resources/themes/images/default/sizer/ne-handle.gif'); }
+/* line 217, ../../extjs/resources/themes/stylesheets/ext4/default/util/_resizable.scss */
+.x-resizable-over .x-resizable-handle-southwest,
+.x-resizable-pinned .x-resizable-handle-southwest {
+ background-position: top right;
+ background-image: url('../extjs/resources/themes/images/default/sizer/sw-handle.gif'); }
+
+/* line 3, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter .x-collapse-el {
+ position: absolute;
+ cursor: pointer;
+ background-color: transparent;
+ background-repeat: no-repeat !important; }
+
+/* line 14, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-layout-split-left,
+.x-layout-split-right {
+ top: 50%;
+ margin-top: -17px;
+ width: 5px;
+ height: 35px; }
+
+/* line 24, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-layout-split-top,
+.x-layout-split-bottom {
+ left: 50%;
+ width: 35px;
+ height: 5px;
+ margin-left: -17px; }
+
+/* line 33, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-layout-split-left {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-left.gif') no-repeat top right; }
+
+/* line 37, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-layout-split-right {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-right.gif') no-repeat top left; }
+
+/* line 41, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-layout-split-top {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-top.gif') no-repeat top left; }
+
+/* line 45, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-layout-split-bottom {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-bottom.gif') no-repeat top left; }
+
+/* line 50, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-collapsed .x-layout-split-left {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-right.gif') no-repeat top left; }
+/* line 54, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-collapsed .x-layout-split-right {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-left.gif') no-repeat top right; }
+/* line 58, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-collapsed .x-layout-split-top {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-bottom.gif') no-repeat top left; }
+/* line 62, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-collapsed .x-layout-split-bottom {
+ background: url('../extjs/resources/themes/images/default/util/splitter/mini-top.gif') no-repeat top left; }
+
+/* line 67, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-horizontal {
+ cursor: e-resize;
+ cursor: row-resize;
+ font-size: 1px; }
+
+/* line 72, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-vertical {
+ cursor: e-resize;
+ cursor: col-resize;
+ font-size: 1px; }
+
+/* line 77, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-collapsed {
+ cursor: default; }
+
+/* line 81, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-active {
+ z-index: 4;
+ font-size: 1px;
+ background-color: #b4b4b4;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
+ opacity: 0.8; }
+
+/* line 88, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-splitter-active .x-collapse-el {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30);
+ opacity: 0.3; }
+
+/* line 93, ../../extjs/resources/themes/stylesheets/ext4/default/util/_splitter.scss */
+.x-proxy-el {
+ position: absolute;
+ background: #b4b4b4;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80);
+ opacity: 0.8; }
+
+/* line 2, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked {
+ position: absolute;
+ z-index: 1; }
+
+/**
+ * Dock Layouts
+ * @todo move this somewhere else?
+ */
+/* line 11, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-top {
+ border-bottom-width: 0 !important; }
+
+/* line 15, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-bottom {
+ border-top-width: 0 !important; }
+
+/* line 19, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-left {
+ border-right-width: 0 !important; }
+
+/* line 23, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-right {
+ border-left-width: 0 !important; }
+
+/* line 27, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-noborder-top {
+ border-top-width: 0 !important; }
+
+/* line 31, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-noborder-right {
+ border-right-width: 0 !important; }
+
+/* line 35, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-noborder-bottom {
+ border-bottom-width: 0 !important; }
+
+/* line 39, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-docked-noborder-left {
+ border-left-width: 0 !important; }
+
+/* line 43, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-inner {
+ overflow: hidden;
+ zoom: 1;
+ position: relative;
+ left: 0;
+ top: 0; }
+
+/* line 53, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-item {
+ position: absolute !important;
+ left: 0;
+ top: 0; }
+
+/* line 60, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-layout-ct,
+.x-border-layout-ct {
+ overflow: hidden;
+ zoom: 1; }
+
+/* line 65, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-overflow-hidden {
+ overflow: hidden !important; }
+
+/* line 69, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-inline-children > * {
+ display: inline-block !important; }
+
+/* line 73, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-abs-layout-item {
+ position: absolute; }
+
+/* line 77, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-border-layout-ct {
+ background-color: #dfe8f6; }
+
+/* line 81, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-border-region-slide-in {
+ z-index: 5; }
+
+/* line 85, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-region-collapsed-placeholder {
+ z-index: 4; }
+
+/* line 89, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-accordion-hd .x-panel-header-text {
+ color: black;
+ font-weight: normal; }
+
+/* line 94, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-accordion-hd {
+ background: #d9e7f8 !important;
+ -moz-box-shadow: inset 0 0 0 0 #d9e7f8;
+ -webkit-box-shadow: inset 0 0 0 0 #d9e7f8;
+ -o-box-shadow: inset 0 0 0 0 #d9e7f8;
+ box-shadow: inset 0 0 0 0 #d9e7f8; }
+ /* line 98, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-accordion-hd .x-tool-collapse-top,
+ .x-accordion-hd .x-tool-collapse-right,
+ .x-accordion-hd .x-tool-collapse-bottom,
+ .x-accordion-hd .x-tool-collapse-left {
+ background-position: 0 -255px; }
+ /* line 105, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-accordion-hd .x-tool-expand-top,
+ .x-accordion-hd .x-tool-expand-right,
+ .x-accordion-hd .x-tool-expand-bottom,
+ .x-accordion-hd .x-tool-expand-left {
+ background-position: 0 -240px; }
+ /* line 113, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-accordion-hd .x-tool-over .x-tool-collapse-top,
+ .x-accordion-hd .x-tool-over .x-tool-collapse-right,
+ .x-accordion-hd .x-tool-over .x-tool-collapse-bottom,
+ .x-accordion-hd .x-tool-over .x-tool-collapse-left {
+ background-position: -15px -255px; }
+ /* line 122, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-accordion-hd .x-tool-over .x-tool-expand-top,
+ .x-accordion-hd .x-tool-over .x-tool-expand-right,
+ .x-accordion-hd .x-tool-over .x-tool-expand-bottom,
+ .x-accordion-hd .x-tool-over .x-tool-expand-left {
+ background-position: -15px -240px; }
+
+/* line 131, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-accordion-hd {
+ border-width: 1px 0 1px 0 !important;
+ padding: 4px 5px 5px 5px;
+ border-top-color: #f3f7fb !important; }
+
+/* line 137, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-accordion-body {
+ border-width: 0 !important; }
+
+/* line 141, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-accordion-hd-sibling-expanded {
+ border-top-color: #99bbe8 !important;
+ -moz-box-shadow: inset 0 1px 0 0 #f3f7fb;
+ -webkit-box-shadow: inset 0 1px 0 0 #f3f7fb;
+ -o-box-shadow: inset 0 1px 0 0 #f3f7fb;
+ box-shadow: inset 0 1px 0 0 #f3f7fb; }
+
+/* line 146, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-accordion-hd-last-collapsed {
+ border-bottom-color: #d9e7f8 !important; }
+
+/* line 155, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-frame-tl,
+.x-frame-tr,
+.x-frame-tc,
+.x-frame-bl,
+.x-frame-br,
+.x-frame-bc {
+ overflow: hidden;
+ background-repeat: no-repeat; }
+
+/* line 161, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-frame-tc,
+.x-frame-bc {
+ background-repeat: repeat-x; }
+
+/* line 165, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-frame-mc {
+ position: relative;
+ background-repeat: repeat-x;
+ overflow: hidden; }
+
+/* line 174, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-scroller-left {
+ float: left;
+ height: 100%;
+ z-index: 5; }
+ /* line 181, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left,
+ .x-box-scroller-left .x-tabbar-scroll-left {
+ width: 18px;
+ position: relative;
+ cursor: pointer;
+ height: 20px;
+ background: url('../extjs/resources/themes/images/default/tab-bar/scroll-left.gif') transparent no-repeat -18px 0; }
+ /* line 188, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left-hover {
+ background-position: 0 0; }
+ /* line 192, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left-disabled,
+ .x-box-scroller-left .x-tabbar-scroll-left-disabled {
+ background-position: -18px 0;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
+ opacity: 0.5; }
+ /* line 197, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left {
+ background-image: url('../extjs/resources/themes/images/default/toolbar/scroll-left.gif');
+ background-position: -14px 0; }
+ /* line 201, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left-hover {
+ background-position: 0 0; }
+ /* line 204, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left-disabled {
+ background-position: -14px 0; }
+ /* line 208, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-left .x-toolbar-scroll-left {
+ width: 14px;
+ height: 22px;
+ border-bottom: 1px solid #8db2e3; }
+
+/* line 216, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-horizontal-box-overflow-body {
+ float: left; }
+
+/* line 219, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-scroller-right {
+ float: right;
+ height: 100%;
+ z-index: 5; }
+ /* line 226, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right,
+ .x-box-scroller-right .x-tabbar-scroll-right {
+ width: 18px;
+ position: relative;
+ cursor: pointer;
+ height: 20px;
+ background: url('../extjs/resources/themes/images/default/tab-bar/scroll-right.gif') transparent no-repeat 0 0; }
+ /* line 233, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right-hover {
+ background-position: -18px 0; }
+ /* line 237, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right-disabled,
+ .x-box-scroller-right .x-tabbar-scroll-right-disabled {
+ background-position: 0 0;
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
+ opacity: 0.5; }
+ /* line 242, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right {
+ background-image: url('../extjs/resources/themes/images/default/toolbar/scroll-right.gif'); }
+ /* line 245, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right-hover {
+ background-position: -14px 0; }
+ /* line 248, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right-disabled {
+ background-position: 0 0; }
+ /* line 252, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+ .x-box-scroller-right .x-toolbar-scroll-right {
+ width: 14px;
+ height: 22px;
+ border-bottom: 1px solid #8db2e3; }
+
+/* line 262, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-scroller-top .x-box-scroller {
+ line-height: 0;
+ font-size: 0; }
+/* line 266, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-scroller-top .x-menu-scroll-top {
+ background: url('../extjs/resources/themes/images/default/layout/mini-top.gif') transparent no-repeat center center;
+ height: 8px;
+ cursor: pointer; }
+
+/* line 273, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-scroller-bottom .x-box-scroller {
+ line-height: 0;
+ font-size: 0; }
+/* line 277, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-scroller-bottom .x-menu-scroll-bottom {
+ background: url('../extjs/resources/themes/images/default/layout/mini-bottom.gif') transparent no-repeat center center;
+ height: 8px;
+ cursor: pointer; }
+
+/* line 284, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-box-menu-right {
+ float: right;
+ padding-right: 2px; }
+
+/* line 289, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-column {
+ float: left; }
+
+/* line 293, ../../extjs/resources/themes/stylesheets/ext4/default/layout/_layout.scss */
+.x-ie6 .x-column {
+ display: inline;
+ /*prevent IE6 double-margin bug*/ }
+
+/* line 2, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool {
+ height: 15px; }
+ /* line 5, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+ .x-tool img {
+ overflow: hidden;
+ width: 15px;
+ height: 15px;
+ cursor: pointer;
+ background-color: transparent;
+ background-repeat: no-repeat;
+ background-image: url('../extjs/resources/themes/images/default/tools/tool-sprites.gif');
+ margin: 0; }
+
+/* line 23, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-panel-header-horizontal .x-tool,
+.x-window-header-horizontal .x-tool {
+ margin-left: 2px; }
+
+/* line 30, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-panel-header-vertical .x-tool,
+.x-window-header-vertical .x-tool {
+ margin-bottom: 2px; }
+
+/* line 35, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-placeholder {
+ visibility: hidden; }
+
+/* line 39, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-toggle {
+ background-position: 0 -60px; }
+
+/* line 44, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-toggle {
+ background-position: -15px -60px; }
+
+/* line 51, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-panel-collapsed .x-tool-toggle,
+.x-fieldset-collapsed .x-tool-toggle {
+ background-position: 0 -75px; }
+/* line 56, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-panel-collapsed .x-tool-over .x-tool-toggle,
+.x-fieldset-collapsed .x-tool-over .x-tool-toggle {
+ background-position: -15px -75px; }
+
+/* line 62, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-close {
+ background-position: 0 0; }
+
+/* line 66, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-minimize {
+ background-position: 0 -15px; }
+
+/* line 70, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-maximize {
+ background-position: 0 -30px; }
+
+/* line 74, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-restore {
+ background-position: 0 -45px; }
+
+/* line 78, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-gear {
+ background-position: 0 -90px; }
+
+/* line 82, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-prev {
+ background-position: 0 -105px; }
+
+/* line 86, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-next {
+ background-position: 0 -120px; }
+
+/* line 90, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-pin {
+ background-position: 0 -135px; }
+
+/* line 94, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-unpin {
+ background-position: 0 -150px; }
+
+/* line 98, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-right {
+ background-position: 0 -165px; }
+
+/* line 102, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-left {
+ background-position: 0 -180px; }
+
+/* line 106, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-help {
+ background-position: 0 -300px; }
+
+/* line 110, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-save {
+ background-position: 0 -285px; }
+
+/* line 114, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-search {
+ background-position: 0 -270px; }
+
+/* line 118, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-minus {
+ background-position: 0 -255px; }
+
+/* line 122, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-plus {
+ background-position: 0 -240px; }
+
+/* line 126, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-refresh {
+ background-position: 0 -225px; }
+
+/* line 130, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-up {
+ background-position: 0 -210px; }
+
+/* line 134, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-down {
+ background-position: 0 -195px; }
+
+/* line 138, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-move {
+ background-position: 0 -375px; }
+
+/* line 142, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-resize {
+ background-position: 0 -360px; }
+
+/* line 146, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-collapse {
+ background-position: 0 -345px; }
+
+/* line 150, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-expand {
+ background-position: 0 -330px; }
+
+/* line 154, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-print {
+ background-position: 0 -315px; }
+
+/* line 159, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-expand-bottom,
+.x-tool-collapse-bottom {
+ background-position: 0 -195px; }
+
+/* line 164, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-expand-top,
+.x-tool-collapse-top {
+ background-position: 0 -210px; }
+
+/* line 169, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-expand-left,
+.x-tool-collapse-left {
+ background-position: 0 -180px; }
+
+/* line 174, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-expand-right,
+.x-tool-collapse-right {
+ background-position: 0 -165px; }
+
+/* line 179, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-close {
+ background-position: -15px 0; }
+/* line 183, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-minimize {
+ background-position: -15px -15px; }
+/* line 187, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-maximize {
+ background-position: -15px -30px; }
+/* line 191, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-restore {
+ background-position: -15px -45px; }
+/* line 195, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-gear {
+ background-position: -15px -90px; }
+/* line 199, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-prev {
+ background-position: -15px -105px; }
+/* line 203, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-next {
+ background-position: -15px -120px; }
+/* line 207, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-pin {
+ background-position: -15px -135px; }
+/* line 211, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-unpin {
+ background-position: -15px -150px; }
+/* line 215, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-right {
+ background-position: -15px -165px; }
+/* line 219, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-left {
+ background-position: -15px -180px; }
+/* line 223, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-down {
+ background-position: -15px -195px; }
+/* line 227, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-up {
+ background-position: -15px -210px; }
+/* line 231, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-refresh {
+ background-position: -15px -225px; }
+/* line 235, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-plus {
+ background-position: -15px -240px; }
+/* line 239, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-minus {
+ background-position: -15px -255px; }
+/* line 243, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-search {
+ background-position: -15px -270px; }
+/* line 247, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-save {
+ background-position: -15px -285px; }
+/* line 251, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-help {
+ background-position: -15px -300px; }
+/* line 255, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-print {
+ background-position: -15px -315px; }
+/* line 259, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-expand {
+ background-position: -15px -330px; }
+/* line 263, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-collapse {
+ background-position: -15px -345px; }
+/* line 267, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-resize {
+ background-position: -15px -360px; }
+/* line 271, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-move {
+ background-position: -15px -375px; }
+/* line 276, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-expand-bottom,
+.x-tool-over .x-tool-collapse-bottom {
+ background-position: -15px -195px; }
+/* line 281, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-expand-top,
+.x-tool-over .x-tool-collapse-top {
+ background-position: -15px -210px; }
+/* line 286, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-expand-left,
+.x-tool-over .x-tool-collapse-left {
+ background-position: -15px -180px; }
+/* line 291, ../../extjs/resources/themes/stylesheets/ext4/default/util/_tool.scss */
+.x-tool-over .x-tool-expand-right,
+.x-tool-over .x-tool-collapse-right {
+ background-position: -15px -165px; }
+
+/* line 2, ../../extjs/resources/themes/stylesheets/ext4/default/util/_scroller.scss */
+.x-horizontal-scroller-present .x-grid-body {
+ border-bottom: none; }
+
+/* line 6, ../../extjs/resources/themes/stylesheets/ext4/default/util/_scroller.scss */
+.x-vertical-scroller-present .x-grid-body {
+ border-right: none; }
+
+/* line 10, ../../extjs/resources/themes/stylesheets/ext4/default/util/_scroller.scss */
+.x-scroller-vertical {
+ overflow-x: hidden;
+ overflow-y: scroll;
+ border: 1px solid #99bbe8;
+ border-top-color: #c5c5c5; }
+
+/* line 18, ../../extjs/resources/themes/stylesheets/ext4/default/util/_scroller.scss */
+.x-scroller-horizontal {
+ overflow-y: hidden;
+ overflow-x: scroll;
+ border: 1px solid #99bbe8; }
+
+/* line 6, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+.x-html {
+ /* Begin bidirectionality settings (do not change) */ }
+ /* line 32, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html html,
+ .x-html address,
+ .x-html blockquote,
+ .x-html body,
+ .x-html dd,
+ .x-html div,
+ .x-html dl,
+ .x-html dt,
+ .x-html fieldset,
+ .x-html form,
+ .x-html frame, .x-html frameset,
+ .x-html h1,
+ .x-html h2,
+ .x-html h3,
+ .x-html h4,
+ .x-html h5,
+ .x-html h6,
+ .x-html noframes,
+ .x-html ol,
+ .x-html p,
+ .x-html ul,
+ .x-html center,
+ .x-html dir,
+ .x-html hr,
+ .x-html menu,
+ .x-html pre {
+ display: block; }
+ /* line 33, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html li {
+ display: list-item;
+ list-style: disc; }
+ /* line 34, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html head {
+ display: none; }
+ /* line 35, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html table {
+ display: table; }
+ /* line 36, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html tr {
+ display: table-row; }
+ /* line 37, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html thead {
+ display: table-header-group; }
+ /* line 38, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html tbody {
+ display: table-row-group; }
+ /* line 39, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html tfoot {
+ display: table-footer-group; }
+ /* line 40, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html col {
+ display: table-column; }
+ /* line 41, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html colgroup {
+ display: table-column-group; }
+ /* line 43, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html td,
+ .x-html th {
+ display: table-cell; }
+ /* line 44, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html caption {
+ display: table-caption; }
+ /* line 45, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html th {
+ font-weight: bolder;
+ text-align: center; }
+ /* line 46, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html caption {
+ text-align: center; }
+ /* line 47, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html body {
+ margin: 8px; }
+ /* line 48, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h1 {
+ font-size: 2em;
+ margin: .67em 0; }
+ /* line 49, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h2 {
+ font-size: 1.5em;
+ margin: .75em 0; }
+ /* line 50, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h3 {
+ font-size: 1.17em;
+ margin: .83em 0; }
+ /* line 60, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h4,
+ .x-html p,
+ .x-html blockquote,
+ .x-html ul,
+ .x-html fieldset,
+ .x-html form,
+ .x-html ol,
+ .x-html dl,
+ .x-html dir,
+ .x-html menu {
+ margin: 1.12em 0; }
+ /* line 61, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h5 {
+ font-size: .83em;
+ margin: 1.5em 0; }
+ /* line 62, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h6 {
+ font-size: .75em;
+ margin: 1.67em 0; }
+ /* line 70, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html h1,
+ .x-html h2,
+ .x-html h3,
+ .x-html h4,
+ .x-html h5,
+ .x-html h6,
+ .x-html b,
+ .x-html strong {
+ font-weight: bolder; }
+ /* line 71, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html blockquote {
+ margin-left: 40px;
+ margin-right: 40px; }
+ /* line 76, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html i,
+ .x-html cite,
+ .x-html em,
+ .x-html var,
+ .x-html address {
+ font-style: italic; }
+ /* line 81, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html pre,
+ .x-html tt,
+ .x-html code,
+ .x-html kbd,
+ .x-html samp {
+ font-family: monospace; }
+ /* line 82, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html pre {
+ white-space: pre; }
+ /* line 86, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html button,
+ .x-html textarea,
+ .x-html input,
+ .x-html select {
+ display: inline-block; }
+ /* line 87, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html big {
+ font-size: 1.17em; }
+ /* line 90, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html small,
+ .x-html sub,
+ .x-html sup {
+ font-size: .83em; }
+ /* line 91, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html sub {
+ vertical-align: sub; }
+ /* line 92, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html sup {
+ vertical-align: super; }
+ /* line 93, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html table {
+ border-spacing: 2px; }
+ /* line 96, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html thead,
+ .x-html tbody,
+ .x-html tfoot {
+ vertical-align: middle; }
+ /* line 98, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html td,
+ .x-html th {
+ vertical-align: inherit; }
+ /* line 101, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html s,
+ .x-html strike,
+ .x-html del {
+ text-decoration: line-through; }
+ /* line 102, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html hr {
+ border: 1px inset; }
+ /* line 107, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html ol,
+ .x-html ul,
+ .x-html dir,
+ .x-html menu,
+ .x-html dd {
+ margin-left: 40px; }
+ /* line 108, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html ul, .x-html menu, .x-html dir {
+ list-style-type: disc; }
+ /* line 109, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html ol {
+ list-style-type: decimal; }
+ /* line 113, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html ol ul,
+ .x-html ul ol,
+ .x-html ul ul,
+ .x-html ol ol {
+ margin-top: 0;
+ margin-bottom: 0; }
+ /* line 115, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html u,
+ .x-html ins {
+ text-decoration: underline; }
+ /* line 116, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html br:before {
+ content: "\A"; }
+ /* line 117, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html :before, .x-html :after {
+ white-space: pre-line; }
+ /* line 118, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html center {
+ text-align: center; }
+ /* line 119, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html :link, .x-html :visited {
+ text-decoration: underline; }
+ /* line 120, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html :focus {
+ outline: invert dotted thin; }
+ /* line 123, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html BDO[DIR="ltr"] {
+ direction: ltr;
+ unicode-bidi: bidi-override; }
+ /* line 124, ../../extjs/resources/themes/stylesheets/ext4/default/widgets/_html.scss */
+ .x-html BDO[DIR="rtl"] {
+ direction: rtl;
+ unicode-bidi: bidi-override; }
+
+/* line 1, ../sass/murano/overrides/_accordion.scss */
+.x-accordion-hd {
+ background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(255, 255, 255, 0.25)), color-stop(50%, rgba(255, 255, 255, 0.15)), color-stop(50%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0))) !important;
+ background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-image: linear-gradient(top, rgba(255, 255, 255, 0.25) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0) 100%) !important;
+ background-color: #666666 !important;
+ padding: 0 5px;
+ border-top: 1px solid #999999 !important;
+ border-bottom: 1px solid #555555 !important; }
+ /* line 2, ../sass/murano/overrides/_accordion.scss */
+ .x-accordion-hd .x-panel-header-text {
+ color: white !important;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.35); }
+ /* line 11, ../sass/murano/overrides/_accordion.scss */
+ .x-accordion-hd .x-tool {
+ top: 3px !important; }
--- /dev/null
+@import 'murano/init';
\ No newline at end of file
--- /dev/null
+$include-default: false;
+$scope-reset-css: false;
+
+html, body{
+ background: #444;
+}
+
+body{
+ text-shadow: 0 -1px 0 rgba(0,0,0,.25);
+}
+
+/* WAT IS THIS I DON'T EVEN *
+ * ------------------------- */
+
+.x-border-layout-ct{
+ background: transparent !important;
+}
+
+.x-css-shadow{
+ display:none !important;
+}
+
+.x-tool img{
+ background-image: murano-image('tools/tool-sprites.png') !important;
+}
+
+.x-layout-split-left {
+ background: murano-image('util/splitter/mini-left.png') no-repeat top right !important;
+}
+
+.x-layout-split-right {
+ background: murano-image('util/splitter/mini-right.png') no-repeat top left !important;
+}
+
+.x-layout-split-top {
+ background: murano-image('util/splitter/mini-bottom.png') no-repeat top left !important;
+}
+
+.x-layout-split-bottom {
+ background: murano-image('util/splitter/mini-top.png') no-repeat top left !important;
+}
+
+.x-splitter-collapsed {
+ .x-layout-split-left {
+ background: murano-image('util/splitter/mini-right.png') no-repeat top left !important;
+ }
+
+ .x-layout-split-right {
+ background: murano-image('util/splitter/mini-left.png') no-repeat top right !important;
+ }
+
+ .x-layout-split-top {
+ background: murano-image('util/splitter/mini-top.png') no-repeat top left !important;
+ }
+
+ .x-layout-split-bottom {
+ background: murano-image('util/splitter/mini-bottom.png') no-repeat top left !important;
+ }
+}
+
+
+/* VARIABLES THAT $include-default: false; DOES NOT GET RID OF *
+ * ----------------------------------------------------------- */
+
+$font-family: "Lucida Grande", "Lucida Sans", Tahoma, Verdana, sans-serif;
+$font-size: 12px;
+$color: $base-text-color;
+$datepicker-tool-sprite-image: 'tools/tool-sprites.png';
\ No newline at end of file
--- /dev/null
+@function bla($value){
+ @return rgba(0,0,0,$value);
+}
+
+@function wha($value){
+ @return rgba(255,255,255,$value);
+}
+
+@function murano-image($file){
+ @return url("../img/"+$file)
+}
+
+@function fugue-image($file){
+ @return url("../../fugue-icons/icons-shadowless/"+$file)
+}
\ No newline at end of file
--- /dev/null
+$prefix: 'x-';
+
+@import 'compass',
+ 'functions',
+ 'variables',
+ 'core',
+ 'components/all';
+
+
+@import 'ext4/default/all';
+
+@import 'overrides/all';
\ No newline at end of file
--- /dev/null
+$gloss-gradient: linear-gradient(top, rgba(255,255,255, .25) 0%, rgba(255,255,255, .15) 50%,rgba(255,255,255, 0) 50%, rgba(255,255,255, 0) 100%);
+$gloss-vertical-gradient: linear-gradient(left, rgba(255,255,255, .25) 0%, rgba(255,255,255, .15) 50%,rgba(255,255,255, 0) 50%, rgba(255,255,255, 0) 100%);
+
+
+/* BASE VARIABLES *
+ * -------------- */
+
+$base-text-color: #FFF;
+
+$base-background-alpha: .85;
+$base-background-color: bla($base-background-alpha);
+
+$base-border-radius-width: 6px;
+
+$base-header-padding: 0 3px 0 6px;
+$base-header-height: 24px;
+$base-body-padding: 0;
+
+$accent-color: #066cd1;
+
+
+/* PANEL VARIABLES *
+ * --------------- */
+
+$panel-background: $base-background-color;
+$panel-header-padding: $base-header-padding;
+$panel-header-height: $base-header-height;
+$panel-body-padding: $base-body-padding;
+
+
+/* WINDOW VARIABLES *
+ * ---------------- */
+
+$window-header-padding: $base-header-padding;
+$window-header-height: $base-header-height;
+$window-body-padding: $base-body-padding;
\ No newline at end of file
--- /dev/null
+@import 'panel',
+ 'window',
+ 'button',
+ 'grid',
+ 'toolbar',
+ 'form',
+ 'form/triggers',
+ 'form/slider',
+ 'tab',
+ 'tooltip',
+ 'progress_bar',
+ 'datepicker',
+ 'sizer',
+ 'tree',
+ 'menu',
+ 'scroller',
+ 'splitter',
+ 'icons';
\ No newline at end of file
--- /dev/null
+button{
+ margin:0;
+ padding:0;
+ background:none;
+ border-width:0;
+}
+
+.x-btn{
+ @include background($gloss-gradient);
+ @include box-shadow(0 0 0 1px bla($base-background-alpha*.25));
+ @include border-radius(2px);
+ background-color: bla($base-background-alpha*.5);
+ border:1px solid wha(.3);
+ border-top-color:wha(.5);
+ border-bottom-color:wha(.05);
+ margin:{
+ top:1px;
+ bottom:1px;
+ };
+ position:relative;
+ white-space:nowrap;
+ display:inline-block;
+ padding:2px;
+ em{
+ display:block;
+ }
+}
+
+.x-btn-over{
+ border-color:$accent-color;
+ border-top-color:lighten($accent-color, 20%);
+ border-bottom-color:darken($accent-color, 10%);
+}
+
+.x-btn-pressed{
+ @extend .x-btn;
+ background-color:wha(.2);
+ border-color:wha(.2);
+ border-top-color:wha(.4);
+ border-bottom-color:wha(.1);
+}
+
+.x-btn-menu-active{
+ background: bla(.5);
+ @include box-shadow(0 2px 4px 0 rgba(0,0,0,.5) inset, 0 0 0 1px bla($base-background-alpha*.25));
+ border:1px solid wha(.5);
+}
+
+.x-btn-inner{
+ display:block;
+ padding:0 5px;
+ color:$base-text-color;
+ background-repeat:no-repeat;
+}
+
+$small: 16px;
+$medium: 24px;
+$large: 32px;
+
+/* different sizes */
+
+.x-btn-noicon, .x-btn-default-icon, .x-btn-icon-text-left, .x-btn-icon-text-right{
+ .x-btn-inner{
+ line-height:$small;
+ }
+}
+
+.x-btn-default-medium-noicon, .x-btn-default-medium-icon-text-left, .x-btn-default-medium-icon-text-right{
+ .x-btn-inner{
+ line-height:$medium;
+ }
+}
+
+.x-btn-default-large-noicon, .x-btn-default-large-icon-text-left, .x-btn-default-large-icon-text-right{
+ .x-btn-inner{
+ line-height:$large;
+ }
+}
+
+/* icons
+ * ----- */
+
+/* icon only */
+
+.x-btn-default-small-icon .x-btn-inner, .x-btn-icon .x-btn-inner{
+ padding:0;
+ width:$small;
+ height:$small;
+}
+.x-btn-default-medium-icon .x-btn-inner{
+ padding:0;
+ width:$medium;
+ height:$medium;
+}
+.x-btn-default-large-icon .x-btn-inner{
+ padding:0;
+ width:$large;
+ height:$large;
+}
+
+/* text w/ icon left */
+
+.x-btn-icon-text-left{
+ background-position:0 center;
+}
+
+.x-btn-icon-text-left .x-btn-inner{
+ padding-left:$small+2px;
+}
+.x-btn-default-medium-icon-text-left .x-btn-inner{
+ padding-left:$medium+2px;
+}
+.x-btn-default-large-icon-text-left .x-btn-inner{
+ padding-left:$large+2px;
+}
+
+/* text w/ icon top */
+
+.x-btn-icon-text-top .x-btn-inner{
+ background-position:center 2px;
+}
+.x-btn-default-small-icon-text-top .x-btn-inner{
+ padding-top:$small+2px;
+}
+.x-btn-default-medium-icon-text-top .x-btn-inner{
+ padding-top:$medium+2px;
+}
+.x-btn-default-large-icon-text-top .x-btn-inner{
+ padding-top:$large+2px;
+}
+
+/* text w/ icon right */
+
+.x-btn-icon-text-right .x-btn-inner{
+ background-position: right center;
+}
+.x-btn-default-small-icon-text-right .x-btn-inner{
+ padding-right:$small+2px;
+}
+.x-btn-default-medium-icon-text-right .x-btn-inner{
+ padding-right:$medium+2px;
+}
+.x-btn-default-large-icon-text-right .x-btn-inner{
+ padding-right:$large+2px;
+}
+
+/* text w/ icon bottom */
+
+.x-btn-icon-text-bottom .x-btn-inner{
+ background-position: center bottom;
+}
+.x-btn-default-small-icon-text-bottom .x-btn-inner{
+ padding-bottom:$small;
+}
+.x-btn-default-medium-icon-text-bottom .x-btn-inner{
+ padding-bottom:$medium;
+}
+.x-btn-default-large-icon-text-bottom .x-btn-inner{
+ padding-bottom:$large;
+}
+
+/* arrow on right */
+.x-btn-arrow-right{
+ padding-right:14px;
+ background: transparent murano-image('btn/menu.png') right center no-repeat;
+}
+
+/* arrow on botton */
+.x-btn-arrow-bottom{
+ padding-bottom:14px;
+ background: transparent murano-image('btn/menu.png') center bottom no-repeat;
+}
+
+/* split on right */
+
+.x-btn-split-right{
+ padding-right:16px;
+ background: transparent murano-image('btn/splith.png') right center no-repeat;
+ display:block;
+}
+
+/* split on bottom */
+
+.x-btn-split-bottom{
+ padding-bottom:16px;
+ background: transparent murano-image('btn/splitv.png') center bottom no-repeat;
+ display:block;
+}
\ No newline at end of file
--- /dev/null
+.x-datepicker{
+ background-color: #000;
+ @include background-image(linear-gradient(#333, #000));
+ border-left:1px solid #000;
+ border-right:1px solid #000;
+}
+.x-datepicker-prev, .x-datepicker-next{
+ position:absolute;
+ top:8px;
+ left:5px;
+ a{
+ display:block;
+ height:15px;
+ width:15px;
+ background: murano-image('shared/btn-left.png');
+ }
+}
+.x-datepicker-next{
+ right:5px;
+ left:auto;
+ a{
+ background: murano-image('shared/btn-right.png');
+ }
+}
+.x-datepicker-header, .x-datepicker-footer{
+ @include background-image(linear-gradient(#333, #111));
+ border-bottom:1px solid #000;
+ border-top:1px solid #444;
+ padding:3px 28px;
+ text-align:center;
+}
+.x-datepicker-inner{
+ font-size:inherit;
+ margin-bottom:0;
+ width:100%;
+ th, td{
+ text-align:center;
+ }
+ thead{
+ border-top:1px solid #777;
+ color:#CCC;
+ @include background-image(linear-gradient(#666, #444));
+ border-bottom:1px solid #222;
+ }
+ table-layout: fixed;
+}
+
+.x-datepicker-inner a{
+ display:block;
+ text-decoration:none;
+ color:#CCC;
+ border:1px solid transparent;
+ em, span{
+ display:block;
+ }
+ em{
+ border:1px solid transparent;
+ }
+}
+.x-datepicker-prevday a{
+ color: #666;
+}
+.x-datepicker-today span{
+ background-color:#555;
+ @include border-radius(2px);
+}
+.x-datepicker-selected a{
+ border-color:bla(.25);
+ em{
+ border-color:$accent-color;
+ border-top-color:lighten($accent-color, 20%);
+ border-bottom-color:darken($accent-color, 10%);
+ }
+ span{
+ @include background-image($gloss-gradient);
+ color:#FFF;
+ @include border-radius(0);
+ }
+}
+
+.x-monthpicker{
+ background:#000;
+ a{
+ text-decoration:none;
+ color:#CCC;
+ }
+ font-size:11px;
+}
+.x-monthpicker-years{
+ width:88px;
+ float:right;
+}
+.x-monthpicker-months{
+ width:87px;
+ float:left;
+ border-right:1px solid #444;
+}
+.x-monthpicker-item{
+ width:43px;
+ float:left;
+ margin:4px 0;
+ text-align:center;
+ a{
+ display:block;
+ border:1px solid transparent;
+ &:hover{
+ background-color:#333;
+ }
+ margin:0 3px;
+ padding:2px 0;
+ @include border-radius(3px);
+ }
+ .x-monthpicker-selected{
+ background-color:#333;
+ border:1px solid #555;
+ border-top-color:#999;
+ border-bottom-color:#444;
+ @include background-image($gloss-gradient);
+ color:#FFF;
+ }
+}
+.x-monthpicker-yearnav-prev, .x-monthpicker-yearnav-next{
+ margin:6px 12px 6px 15px;
+ float:left;
+ display:block;
+ height:15px;
+ width:15px;
+ background: murano-image('shared/btn-left.png');
+}
+.x-monthpicker-yearnav-next{
+ background: murano-image('shared/btn-right.png');
+}
+.x-monthpicker .x-btn{
+ width:80px;
+ float:left;
+ margin:4px;
+}
+.x-monthpicker-buttons{
+ border-top:1px solid #777;
+ @include background-image(linear-gradient(#666, #444));
+ padding:2px 1px;
+ @include clearfix;
+}
+
+.x-datepicker-footer{
+ @include background-image(linear-gradient(#666, #444));
+ border-top-color:#777;
+ border-bottom-color:#222;
+}
\ No newline at end of file
--- /dev/null
+$html-editor-border-color: #000;
+$html-editor-background-color: #FFF;
+@import 'form/htmleditor';
+@include extjs-form-htmleditor;
+
+.x-form-item{
+ margin-bottom:6px;
+}
+
+.x-form-item-body, .x-form-item-label-left{
+ float:left;
+ position:relative;
+}
+
+.x-form-text{
+ background:#444;
+ @include box-shadow(0 5px 8px 0 bla(.35) inset, 0 1px 0 0 wha(.35), 0 0 0 1px wha(.05) inset);
+ border:1px solid #000;
+ color:#FFF;
+ color:#FFF;
+ padding:0 3px;
+}
+
+.x-form-text:focus, .x-form-trigger-wrap-focus .x-form-text{
+ outline:none;
+ background:#666;
+}
+
+input.x-form-text{
+ height:21px;
+}
+.x-form-invalid-field{
+ background:#700;
+}
+.x-form-invalid-icon{
+ text-indent:-9999px;
+}
+.x-form-invalid-icon ul{
+ display:none;
+}
+
+.x-form-checkbox, .x-form-radio{
+ @include reset-box-model;
+ @include reset-focus;
+ height:16px;
+ width:16px;
+
+}
+
+.x-form-checkbox{
+ background: murano-image('form/unchecked.png');
+}
+.x-form-cb-checked .x-form-checkbox{
+ background: murano-image('form/checked.png');
+}
+
+.x-form-radio{
+ background: murano-image('form/unradioed.png');
+}
+.x-form-cb-checked .x-form-radio{
+ background: murano-image('form/radioed.png');
+}
+
+.x-form-cb-label-after{
+ margin-left:3px;
+}
+
+.x-form-invalid-icon{
+ width:20px;
+ height:19px;
+ float:left;
+ background: murano-image('form/exclamation.png') right center no-repeat;
+}
+
+
+.x-form-field, .x-form-display-field{
+ float:left;
+ margin:0;
+}
+
+
+.x-fieldset{
+ border:1px solid #666;
+ padding:10px;
+ margin-bottom:10px;
+}
+.x-fieldset-header{
+ white-space:nowrap;
+ padding:0 5px;
+}
+.x-fieldset-header-text{
+ float:left;
+}
+.x-fieldset-header .x-tool, .x-fieldset-header .x-form-item{
+ float:left;
+ margin-right:3px;
+}
+.x-fieldset-collapsed{
+ border-width: 1px 1px 0 1px !important;
+ padding-bottom:0px !important;
+ border-left-color:transparent;
+ border-right-color:transparent;
+}
+
+.x-boundlist{
+ background:#000;
+ border:1px solid #333;
+}
+
+.x-boundlist-floating{
+ @include box-shadow(0 1px 3px 0 bla(.35));
+}
+.x-boundlist-item{
+ padding:1px 4px;
+ border:1px solid transparent;
+ margin:1px;
+ @include border-radius(5px);
+ &-over{
+ border:1px solid lighten($accent-color, 10%);
+ @include background-image(linear-gradient(lighten($accent-color, 10%),$accent-color));
+ @include box-shadow(0 -1px 0 0 bla(.15) inset);
+ }
+}
+.x-boundlist-selected{
+ border:1px solid $accent-color;
+ @include background-image(linear-gradient($accent-color,darken($accent-color, 10%)));
+ @include box-shadow(0 -1px 0 0 bla(.15) inset);
+}
\ No newline at end of file
--- /dev/null
+.x-grid-view{
+ position:relative;
+ overflow:hidden;
+}
+
+.x-grid-header-ct{
+ @include background(linear-gradient(top, #ccc, #aaa));
+ @include box-shadow(0 1px 0 0 #999);
+}
+
+.x-column-header{
+ border-top:1px solid #DDD;
+ padding:2px 5px;
+ color:#222;
+ text-shadow:0 1px 0 #FFF;
+ white-space:nowrap;
+ border-right:1px solid bla(.1);
+}
+
+.x-column-header{
+ overflow:hidden;
+ .x-column-header-trigger{
+ display:none;
+ background: transparent murano-image('triggericons/spinner-down.png') center 6px no-repeat;
+ width:20px;
+ }
+ &-over, &-open{
+ .x-column-header-trigger{
+ display:block;
+ background-color:#AAA;
+ border-left:1px solid #FFF;
+ border-right:1px solid #888;
+ }
+ }
+}
+
+
+.x-column-header-sort-DESC, .x-column-header-sort-ASC{
+ border-top:1px solid #BBB;
+ @include background(linear-gradient(top, #AAA, #888));
+ @include box-shadow(0 1px 0 0 #777);
+ text-shadow:0 1px 0 #DDD;
+}
+
+.x-column-header-trigger{
+ width:14px;
+ height:100%;
+ position:absolute;
+ top:0;
+ right:0;
+}
+
+
+.x-grid-table{
+ font-size:inherit;
+ border-collapse:separate;
+ border-spacing:0;
+ table-layout:fixed;
+ td, th{
+ overflow:hidden;
+ text-align:left;
+ white-space:nowrap;
+ vertical-align:top;
+ }
+}
+.x-grid-cell-inner{
+ white-space:nowrap;
+ overflow:hidden;
+ text-overflow:ellipsis;
+ padding:3px 6px;
+}
+
+
+.x-grid-row{
+ td{
+ border-top:1px solid transparent;
+ border-bottom:1px solid transparent;
+ }
+}
+
+.x-grid-row-alt{
+ background: wha(.1);
+ td{
+ border-top:1px solid wha(.05);
+ border-bottom:1px solid wha(.05);
+ }
+}
+
+.x-grid-row-over{
+ td{
+ background: wha(.05);
+ }
+}
+
+.x-grid-row-selected{
+ @include background-image($gloss-gradient);
+ background-color:#000;
+ td{
+ border-top:1px solid lighten($accent-color, 10%);
+ border-bottom:1px solid $accent-color;
+ }
+}
+
+.x-grid-resize-marker{
+ background:#FFF;
+ width:1px;
+ position:absolute;
+}
+
+
+// Row Editor
+.#{$prefix}grid-row-editor {
+ position: absolute !important;
+ z-index: 1;
+ zoom: 1;
+ overflow: visible !important;
+
+ .#{$prefix}form-field {
+ }
+ .#{$prefix}form-display-field {
+ padding-top: 0;
+ }
+
+ .#{$prefix}panel-body {
+ border:{
+ top:1px solid $accent-color !important;
+ bottom:1px solid $accent-color !important;
+ left:none !important;
+ right:none !important;
+ };
+ }
+}
+
+// Perfect alignment of input text with cell text
+.#{$prefix}grid-row-editor {
+ // Align input text with text value in cell
+ .#{$prefix}form-text {
+ padding-left: 2px;
+ }
+}
+.#{$prefix}grid-editor {
+ // Align checkboxes input
+ .#{$prefix}form-cb-wrap {
+ text-align: center;
+ }
+}
+
+.#{$prefix}grid-row-editor-buttons {
+ position: absolute;
+ bottom: -31px;
+ padding: 4px;
+ width: 200px;
+ height: 32px;
+ background:#222;
+ @include border-radius(0 0 4px 4px);
+ border:{
+ bottom: 1px solid $accent-color;
+ left: 1px solid $accent-color;
+ right: 1px solid $accent-color;
+ };
+
+ .#{$prefix}strict & {
+ width: 192px;
+ height: 24px;
+ }
+ }
+
+ .#{$prefix}grid-row-editor-errors {
+ ul {
+ margin-left: 5px;
+ }
+ li {
+ list-style: disc;
+ margin-left: 15px;
+ }
+ }
\ No newline at end of file
--- /dev/null
+.x-tbar-page-prev{
+ background: transparent fugue-image('control-180.png') center center no-repeat;
+}
+.x-tbar-page-first{
+ background: transparent fugue-image('control-stop-180.png') center center no-repeat;
+}
+.x-tbar-page-next{
+ background: transparent fugue-image('control.png') center center no-repeat;
+}
+.x-tbar-page-last{
+ background: transparent fugue-image('control-stop.png') center center no-repeat;
+}
+.x-tbar-loading{
+ background: transparent fugue-image('arrow-circle-double-135.png') center center no-repeat;
+}
\ No newline at end of file
--- /dev/null
+.x-menu{
+ @include box-shadow(0 1px 4px 0 bla(.35));
+ white-space:nowrap;
+ @extend .x-boundlist;
+}
+
+.x-menu-body{
+ position:absolute;
+}
+
+.x-menu-item{
+ padding:2px;
+}
+
+.x-menu-item-link{
+ padding:4px;
+ border:1px solid transparent;
+ @include border-radius(5px);
+ text-decoration:none;
+ display:block;
+ color:#FFF;
+}
+
+.x-menu-item-active .x-menu-item-link{
+ border-color:$accent-color;
+ @include background-image(linear-gradient($accent-color, darken($accent-color, 10%)));
+ @include box-shadow(0 -1px 0 0 bla(.15) inset);
+}
+
+.x-menu-item-icon{
+ width:16px;
+ height:16px;
+ margin-right:5px;
+ float:left;
+}
+
+.x-menu-item-unchecked{
+ .x-menu-item-icon{
+ background: murano-image('form/unchecked.png');
+ }
+ .x-menu-group-icon{
+ background: murano-image('form/unradioed.png');
+ }
+}
+.x-menu-item-checked{
+ .x-menu-item-icon{
+ background: murano-image('form/checked.png');
+ }
+ .x-menu-group-icon{
+ background: murano-image('form/radioed.png');
+ }
+}
+
+.x-menu-item-separator{
+ height:0;
+ padding:0;
+ margin: 3px 9px 3px 10px;
+ border-bottom:1px solid wha(.25);
+}
--- /dev/null
+.x-panel{
+ background: $panel-background;
+ overflow:hidden;
+ position:relative;
+ margin-top:0;
+}
+
+.x-panel, .x-window{
+ .x-panel {
+ .x-panel-body{
+ background: #222;
+ }
+ }
+}
+
+.x-panel-header{
+ @include background($gloss-gradient);
+ @include box-shadow(0 1px 0 0 bla(.35));
+ border-top:1px solid #FFF;
+ line-height: $panel-header-height;
+ height: $panel-header-height;
+ padding: $panel-header-padding;
+}
+
+.x-panel-header-vertical{
+ @include background($gloss-vertical-gradient);
+}
+
+.x-panel-body{
+ position:relative;
+ padding: $panel-body-padding;
+}
+
+/* FRAMED PANEL
+ * ------------ */
+.x-panel-default-framed{
+ border:1px solid wha(.5);
+ border-top-color: wha(1);
+ @include border-radius($base-border-radius-width $base-border-radius-width 0 0);
+}
+
+.x-panel-default-framed .x-panel-header{
+ border-top:0;
+ @include border-radius($base-border-radius-width $base-border-radius-width 0 0);
+ margin:{
+ top:1px;
+ left:1px;
+ right:1px;
+ };
+}
+
+/* MASKED PANEL
+ * ------------ */
+
+.x-mask-msg{
+ background:#333 !important;
+ @include background-image($gloss-gradient !important);
+ @include border-radius(4px);
+ @include box-shadow(0 0 0 1px bla(.75));
+ border:1px solid #333 !important;
+ border-top:1px solid #888 !important;
+ div{
+ background-color:#000 !important;
+ @include border-radius(3px);
+ border:1px solid #333 !important;
+ border-bottom:1px solid #888 !important;
+ color:#CCC !important;
+ }
+}
\ No newline at end of file
--- /dev/null
+.x-progress{
+ position:relative;
+ height:16px;
+ border:1px solid #000;
+ text-align:center;
+ text-shadow:none;
+ @include border-radius(10px);
+ overflow:hidden;
+ background:#333;
+ @include box-shadow(0 3px 5px 0 bla(.35) inset, 0 1px 0 0 wha(.25));
+ padding:1px 0;
+ font-size:10px;
+ text-transform:uppercase;
+ letter-spacing:1px;
+}
+.x-progress-bar{
+ background:#FFF;
+ position:absolute;
+ left:0;
+ top:0;
+ height:14px;
+ border:1px solid #666;
+ @include border-radius(10px);
+ @include background(linear-gradient(#444, #666));
+ @include box-shadow(0 0 4px 0 bla(.5));
+ overflow:hidden;
+}
+
+.x-progress-text{
+ color:#FFF;
+ text-shadow:0 -1px 0 bla(.35);
+}
+
+.x-progress-text-back{
+ color:#999;
+}
\ No newline at end of file
--- /dev/null
+$scroller-thumb-color: #666 !default;
+
+.x-scroller{
+ border:none !important;
+ &::-webkit-scrollbar {
+ width: 16px;
+ height: 16px;
+ &-track{
+ background:transparent;
+ }
+ &-track-piece:start{
+ margin-left:1px;
+ margin-top:1px;
+ }
+ &-track-piece:end{
+ margin-right:1px;
+ margin-bottom:1px;
+ }
+ &-thumb{
+ border:1px solid #000;
+ background-color:$scroller-thumb-color;
+ @include border-radius(8px);
+ @include box-shadow(0 1px 0 0 wha(.35) inset, 0 -1px 0 0 #000 inset);
+ &:hover{
+ background-color:lighten($scroller-thumb-color, 5%);
+ }
+ &:active{
+ background-color:lighten($scroller-thumb-color, 10%);
+ }
+ }
+ }
+}
+
+.x-scroller-vertical::-webkit-scrollbar-thumb{
+ @include background-image($gloss-vertical-gradient);
+}
+.x-scroller-horizontal::-webkit-scrollbar-thumb{
+ @include background-image($gloss-gradient);
+}
\ No newline at end of file
--- /dev/null
+.x-resizable-handle-west {
+ background: transparent murano-image('sizer/w.png') left center no-repeat !important;
+}
+.x-resizable-handle-east {
+ background: transparent murano-image('sizer/e.png') right center no-repeat !important;
+}
+.x-resizable-handle-north {
+ background: transparent murano-image('sizer/n.png') top center no-repeat !important;
+}
+.x-resizable-handle-south {
+ background: transparent murano-image('sizer/s.png') bottom center no-repeat !important;
+}
+.x-resizable-handle-northwest {
+ background: transparent murano-image('sizer/nw.png') left top no-repeat !important;
+}
+.x-resizable-handle-northeast {
+ background: transparent murano-image('sizer/ne.png') right top no-repeat !important;
+}
+.x-resizable-handle-southwest {
+ background: transparent murano-image('sizer/sw.png') left bottom no-repeat !important;
+}
+.x-resizable-handle-southeast {
+ background: transparent murano-image('sizer/se.png') right bottom no-repeat !important;
+}
\ No newline at end of file
--- /dev/null
+.x-splitter{
+ background-color:#000;
+}
\ No newline at end of file
--- /dev/null
+.x-tab{
+ @include border-radius(3px 3px 0 0);
+ border:1px solid wha(.15);
+ border-top:1px solid wha(.5);
+ border-bottom:none;
+ @include background($gloss-gradient);
+ background-color: #000;
+ margin:{
+ top:2px;
+ left:4px;
+ };
+ @include box-shadow(0 0 0 1px bla(.5));
+ button{
+ color:#CCC;
+ text-shadow: 0 -1px 0 bla(.75);
+ }
+ padding:3px 5px 6px 5px;
+ white-space: nowrap;
+}
+
+.x-tab-over{
+ border-color:$accent-color;
+ border-top-color:lighten($accent-color, 20%);
+ button{
+ color:#FFF;
+ }
+}
+
+.x-tab-active{
+ border-color: wha(.35);
+ border-top-color:#FFF;
+ button{
+ color:#FFF;
+ }
+ z-index:3;
+ @include box-shadow(none);
+}
+
+.x-tab button{
+ height:14px;
+ line-height:14px;
+}
+
+.x-tab em{
+ display:block;
+ padding:0 3px;
+}
+
+.x-tab-closable em{
+ padding-right:15px;
+}
+
+.x-tab-close-btn{
+ position:absolute;
+ top:3px;
+ right:3px;
+ width:11px;
+ height:11px;
+ background: murano-image('tab/tab-close.png');
+ text-indent:-119988px;
+}
+
+.x-tab-bar-strip{
+ z-index:2;
+ border-top:1px solid wha(.35);
+ border-bottom:1px solid wha(.35);
+ margin-top:-1px;
+ height:4px;
+ background:#000;
+ position:relative;
+}
+
+.x-box-scroller{
+ width:18px !important;
+ height:22px !important;
+}
+
+.x-tabbar-scroll-left{
+ background: murano-image('tab-bar/l.png') !important;
+ &-hover{
+ background-position:left center !important;
+ }
+ &-disabled{
+ background-position:left top !important;
+ }
+}
+
+
+.x-tabbar-scroll-right{
+ background: murano-image('tab-bar/r.png') !important;
+ &-hover{
+ background-position:left center !important;
+ }
+ &-disabled{
+ background-position:left top !important;
+ }
+}
+
+.x-tab-inner{
+ display:block;
+ .x-tab-icon-text-left &{
+ padding-left:20px;
+ background-repeat:no-repeat;
+ background-position:left top;
+ }
+}
\ No newline at end of file
--- /dev/null
+.x-toolbar{
+// @include background(linear-gradient(top, #444 0%, #666 10%, #888 90%, #777 100%));
+ @include background(linear-gradient(top, #222 0%, #444 10%, #666 90%, #444 100%));
+ padding:3px 0;
+}
+
+.x-toolbar-item{
+ margin:{
+ left:3px;
+ right:3px;
+ };
+ white-space:nowrap;
+}
+.x-toolbar-text{
+ font-size:11px;
+ margin-left:10px;
+ white-space:nowrap;
+}
+
+.x-toolbar-separator{
+ border-right:1px solid wha(.25);
+ border-left:1px solid bla(.25);
+ height:14px;
+}
+
+.x-toolbar-separator-vertical{
+ width:100%;
+ height:0;
+ border-top:1px solid bla(.25);
+ border-bottom:1px solid wha(.25);
+ margin:9px 0;
+}
\ No newline at end of file
--- /dev/null
+.x-tip, .x-form-invalid-tip{
+ background-color: darken($accent-color, 10%);
+ @include background-image($gloss-gradient);
+ padding:4px;
+ @include border-radius(5px);
+ @include box-shadow(0 0 0 1px bla(.7), 0 0 0 1px wha(.25) inset);
+}
+
+.x-form-invalid-tip{
+ background-color:#800000;
+}
+
+.x-tip-header{
+ font-weight:bold;
+}
+
+.x-tip-body{
+ position:relative;
+}
\ No newline at end of file
--- /dev/null
+$tree-elbow-height: 16px;
+$tree-elbow-width: 16px;
+$form-checkbox-size: 16px;
+$form-checkbox-image-unchecked: murano-image('form/unchecked.png');
+$form-checkbox-image-checked: murano-image('form/checked.png');
+$include-ie: true;
+$include-ff: true;
+
+.x-tree-panel .x-grid-row{
+ &-selected{
+ background-color:#000;
+ color:#FFF;
+ td{
+ @include box-shadow(0 0 0 1px wha(.1));
+ }
+ }
+}
+
+.#{$prefix}tree-no-lines .#{$prefix}tree-elbow {
+ background-color: transparent;
+}
+
+.#{$prefix}tree-no-lines .#{$prefix}tree-elbow-end {
+ background-color: transparent;
+}
+
+.#{$prefix}tree-no-lines .#{$prefix}tree-elbow-line {
+ background-color: transparent;
+}
+
+//arrows
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow-plus {
+ background: transparent no-repeat 0 0;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow-end-plus {
+ background: transparent no-repeat 0 0;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow-end-minus {
+ background: transparent no-repeat -16px 0;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow-minus {
+ background: transparent no-repeat -16px 0;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow {
+ background-color: transparent !important;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow-end {
+ background-color: transparent !important;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-elbow-line {
+ background-color: transparent !important;
+}
+
+//elbows
+.#{$prefix}tree-arrows .#{$prefix}tree-expander-over .#{$prefix}tree-elbow-plus,
+.#{$prefix}tree-arrows .#{$prefix}tree-expander-over .#{$prefix}tree-elbow-end-plus {
+ background-position: -32px 0;
+}
+
+.#{$prefix}tree-arrows .#{$prefix}tree-expander-over .#{$prefix}tree-elbow-minus,
+.#{$prefix}tree-arrows .#{$prefix}tree-expander-over .#{$prefix}tree-elbow-end-minus {
+ background-position: -48px 0;
+}
+
+.#{$prefix}tree-arrows .x-grid-tree-node-expanded .#{$prefix}tree-elbow-plus,
+.#{$prefix}tree-arrows .x-grid-tree-node-expanded .#{$prefix}tree-elbow-end-plus {
+ background-position: -16px 0;
+}
+
+.#{$prefix}tree-arrows .x-grid-tree-node-expanded .#{$prefix}tree-expander-over .#{$prefix}tree-elbow-plus,
+.#{$prefix}tree-arrows .x-grid-tree-node-expanded .#{$prefix}tree-expander-over .#{$prefix}tree-elbow-end-plus {
+ background-position: -48px 0;
+}
+
+.#{$prefix}tree-elbow-plus,
+.#{$prefix}tree-elbow-minus,
+.#{$prefix}tree-elbow-end-plus,
+.#{$prefix}tree-elbow-end-minus{
+ cursor: pointer;
+}
+
+//elbows
+.#{$prefix}tree-lines {
+ .#{$prefix}tree-elbow {
+ background-image: murano-image('tree/elbow.gif');
+ }
+
+ .#{$prefix}tree-elbow-end {
+ background-image: murano-image('tree/elbow-end.gif');
+ }
+
+ .#{$prefix}tree-elbow-plus {
+ // background-image: murano-image('tree/elbow-plus.gif');
+ background-image: fugue-image('plus-small-white.png');
+ }
+
+ .#{$prefix}tree-elbow-end-plus {
+ // background-image: murano-image('tree/elbow-end-plus.gif');
+ background-image: fugue-image('plus-small-white.png');
+ }
+
+ .#{$prefix}grid-tree-node-expanded .#{$prefix}tree-elbow-plus {
+ // background-image: murano-image('tree/elbow-minus.gif');
+ background-image: fugue-image('minus-small-white.png');
+ }
+
+ .#{$prefix}grid-tree-node-expanded .#{$prefix}tree-elbow-end-plus {
+ // background-image: murano-image('tree/elbow-end-minus.gif');
+ background-image: fugue-image('minus-small-white.png');
+ }
+
+ .#{$prefix}tree-elbow-line {
+ background-image: murano-image('tree/elbow-line.gif');
+ }
+}
+
+.#{$prefix}tree-no-lines {
+ .#{$prefix}tree-elbow-plus,
+ .#{$prefix}tree-elbow-end-plus {
+ background-image: murano-image('tree/elbow-plus-nl.gif');
+ }
+
+ .#{$prefix}grid-tree-node-expanded .#{$prefix}tree-elbow-plus,
+ .#{$prefix}grid-tree-node-expanded .#{$prefix}tree-elbow-end-plus {
+ background-image: murano-image('tree/elbow-end-minus-nl.gif');
+ }
+}
+
+.#{$prefix}tree-arrows {
+ .#{$prefix}tree-elbow-plus,
+ .#{$prefix}tree-elbow-minus,
+ .#{$prefix}tree-elbow-end-plus,
+ .#{$prefix}tree-elbow-end-minus {
+ background-image: murano-image('tree/arrows.gif');
+ }
+}
+
+.#{$prefix}tree-icon {
+ margin-right: 3px;
+}
+
+.#{$prefix}tree-elbow,
+.#{$prefix}tree-elbow-end,
+.#{$prefix}tree-elbow-plus,
+.#{$prefix}tree-elbow-end-plus,
+.#{$prefix}tree-elbow-empty,
+.#{$prefix}tree-elbow-line {
+ height: $tree-elbow-height;
+ width: $tree-elbow-width;
+}
+
+.#{$prefix}tree-icon-leaf {
+ width: $tree-elbow-width;
+ background-image: fugue-image('leaf.png');
+}
+
+.#{$prefix}tree-icon-parent {
+ width: $tree-elbow-width;
+ background-image: fugue-image('folder-horizontal.png');
+}
+
+.#{$prefix}grid-tree-node-expanded .#{$prefix}tree-icon-parent {
+ background-image: fugue-image('folder-horizontal-open.png');
+}
+
+.#{$prefix}grid-rowbody {
+ padding: 0;
+}
+
+.#{$prefix}tree-panel .#{$prefix}grid-cell-inner {
+ padding: 0px;
+}
+
+.#{$prefix}tree-panel .#{$prefix}grid-row .#{$prefix}grid-cell {
+ border: none;
+}
+
+.#{$prefix}tree-panel .#{$prefix}grid-row .#{$prefix}grid-cell-inner {
+ height: $tree-elbow-height;
+
+ line-height: $tree-elbow-height;
+ vertical-align: middle;
+ cursor: pointer;
+
+ img {
+ float: left;
+ }
+}
+
+.#{$prefix}ie {
+ .#{$prefix}tree-panel .#{$prefix}grid-row .#{$prefix}grid-cell-inner {
+ white-space: normal;
+ }
+}
+
+
+.#{$prefix}tree-checkbox {
+ float: left;
+ margin: 2px 3px 0 0;
+ display: block;
+
+ width: $form-checkbox-size;
+ height: $form-checkbox-size;
+ background: murano-image($form-checkbox-image-unchecked) no-repeat;
+
+ overflow: hidden;
+ padding: 0;
+ border: 0;
+ &::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+ }
+}
+@if $include-ie {
+ /* Hack for IE; causes alignment problem in IE9 standards mode so exclude that */
+ .#{$prefix}nbr.#{$prefix}ie {
+ .#{$prefix}tree-checkbox {
+ font-size: 0;
+ }
+ }
+}
+.#{$prefix}tree-checkbox-checked {
+ background: murano-image($form-checkbox-image-checked) no-repeat;
+}
+
+@if $include-ie {
+ .#{$prefix}tree-panel .#{$prefix}grid-cell-inner {
+ border-width: 0 !important;
+ }
+}
+
+@if $include-ff {
+ .#{$prefix}gecko {
+ .#{$prefix}tree-panel .#{$prefix}grid-row .#{$prefix}grid-cell-inner {
+ line-height: $tree-elbow-height - 2;
+ }
+ }
+}
+
+.#{$prefix}tree-drop-ok-append .#{$prefix}dd-drop-icon {
+ background-image: murano-image('tree/drop-append.gif');
+}
+
+.#{$prefix}tree-drop-ok-above .#{$prefix}dd-drop-icon {
+ background-image: murano-image('tree/drop-above.gif');
+}
+
+.#{$prefix}tree-drop-ok-below .#{$prefix}dd-drop-icon {
+ background-image: murano-image('tree/drop-below.gif');
+}
+
+.#{$prefix}tree-drop-ok-between .#{$prefix}dd-drop-icon {
+ background-image: murano-image('tree/drop-between.gif');
+}
+
+.#{$prefix}grid-tree-loading .#{$prefix}tree-icon {
+ background-image: murano-image('tree/loading.gif');
+}
+
+.#{$prefix}tree-ddindicator {
+ height: 1px;
+ border-width: 1px 0px 0px;
+ border-style: dotted;
+ border-color: green;
+}
+
+.#{$prefix}grid-tree-loading span {
+ font-style: italic;
+ color: #444444;
+}
+
+.#{$prefix}tree-animator-wrap {
+ overflow: hidden;
+}
\ No newline at end of file
--- /dev/null
+.x-window{
+ background: $base-background-color;
+ @include border-radius($base-border-radius-width $base-border-radius-width 0 0);
+ @include box-shadow(0 0 0 1px bla($base-background-alpha*.5), 0 3px 8px 0 bla(.35), 0 0 0 1px bla($base-background-alpha*.5) inset);
+ border:1px solid wha(.5);
+ border-top-color: wha(1);
+}
+
+.x-window-header{
+ @include background($gloss-gradient);
+ @include border-radius($base-border-radius-width $base-border-radius-width 0 0);
+ @include box-shadow(0 1px 0 0 bla(.35));
+ padding: $window-header-padding;
+ line-height: $window-header-height;
+ height: $window-header-height;
+}
+
+.x-window-body{
+ position:relative;
+ padding: $window-body-padding;
+ background-color:bla(.1);
+}
\ No newline at end of file
--- /dev/null
+@mixin extjs-form-htmleditor {
+ .#{$prefix}html-editor-wrap {
+ border: 1px solid $html-editor-border-color;
+
+ .#{$prefix}toolbar {
+ border-top-width: 0;
+ border-left-width: 0;
+ border-right-width: 0;
+ }
+
+ textarea {
+ background-color: $html-editor-background-color;
+ }
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}btn-inner {
+ display:block;
+ width:16px;
+ padding:0;
+ height:16px;
+ margin:4px 2px;
+ background:transparent murano-image('editor/tb-sprite.png') no-repeat;
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-bold,
+ .#{$prefix}menu-item img.#{$prefix}edit-bold {
+ background-position:0 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-italic,
+ .#{$prefix}menu-item img.#{$prefix}edit-italic {
+ background-position:-16px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-underline,
+ .#{$prefix}menu-item img.#{$prefix}edit-underline {
+ background-position:-32px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-forecolor,
+ .#{$prefix}menu-item img.#{$prefix}edit-forecolor {
+ background-position:-160px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-backcolor,
+ .#{$prefix}menu-item img.#{$prefix}edit-backcolor {
+ background-position:-176px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-justifyleft,
+ .#{$prefix}menu-item img.#{$prefix}edit-justifyleft {
+ background-position:-112px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-justifycenter,
+ .#{$prefix}menu-item img.#{$prefix}edit-justifycenter {
+ background-position:-128px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-justifyright,
+ .#{$prefix}menu-item img.#{$prefix}edit-justifyright {
+ background-position:-144px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-insertorderedlist,
+ .#{$prefix}menu-item img.#{$prefix}edit-insertorderedlist {
+ background-position:-80px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-insertunorderedlist,
+ .#{$prefix}menu-item img.#{$prefix}edit-insertunorderedlist {
+ background-position:-96px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-increasefontsize,
+ .#{$prefix}menu-item img.#{$prefix}edit-increasefontsize {
+ background-position:-48px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-decreasefontsize,
+ .#{$prefix}menu-item img.#{$prefix}edit-decreasefontsize {
+ background-position:-64px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-sourceedit,
+ .#{$prefix}menu-item img.#{$prefix}edit-sourceedit {
+ background-position:-192px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tb .#{$prefix}edit-createlink,
+ .#{$prefix}menu-item img.#{$prefix}edit-createlink {
+ background-position: -208px 0;
+ background-image: murano-image('editor/tb-sprite.png');
+ }
+
+ .#{$prefix}html-editor-tip .#{$prefix}tip-bd .#{$prefix}tip-bd-inner {
+ padding: 5px;
+ padding-bottom: 1px;
+ }
+
+ .#{$prefix}html-editor-tb {
+ .#{$prefix}toolbar {
+ position: static !important;
+ }
+ .#{$prefix}font-select {
+ font-size: 11px;
+ }
+ }
+
+ .x-html-editor-wrap textarea {
+ border: 0;
+ padding: 3px 2px;
+ overflow: auto;
+ }
+}
\ No newline at end of file
--- /dev/null
+.x-slider{
+ border:1px solid #000;
+ @include border-radius(6px);
+ background:#333;
+ overflow:hidden;
+ position:relative;
+}
+
+.x-slider-thumb{
+ height:8px;
+ width:8px;
+ @include border-radius(5px);
+ border:1px solid #DDD;
+ @include background(linear-gradient(#AAA, #CCC));
+ position:absolute;
+ @include box-shadow(0 0 3px 0 bla(.35))
+}
+
+.x-slider-thumb-over{
+ border-color:#FFF;
+ @include background(linear-gradient(#CCC, #FFF));
+}
+
+.x-slider-horz{
+ @include box-shadow(0 1px 0 0 wha(.15), 0 2px 5px 0 bla(.25) inset);
+ height:10px;
+ .x-slider-end{
+ padding-right:12px;
+ height:10px;
+ }
+ .x-slider-inner{
+ height:10px;
+ }
+ .x-slider-thumb{
+ margin-left:5px;
+ }
+}
+
+.x-slider-vert{
+ @include box-shadow(1px 0 0 0 wha(.15), 2px 0 5px 0 bla(.25) inset);
+ width:10px;
+ .x-slider-inner{
+ width:10px;
+ }
+ .x-slider-end{
+ padding-bottom:10px;
+ width:10px;
+ }
+ .x-slider-thumb{
+ margin-top:4px;
+ margin-bottom:4px;
+ }
+}
\ No newline at end of file
--- /dev/null
+@mixin trigger($type, $image){
+ .x-form-#{$type}-trigger{
+ @include background-image(linear-gradient(bla(.2), bla(0)), $gloss-gradient, $image);
+ }
+}
+
+.x-form-trigger-wrap{
+ float:left;
+ @include box-shadow(0 1px 0 0 wha(.35));
+ overflow:hidden;
+ border:1px solid #000;
+ border-left:0;
+ @include border-radius(0 4px 4px 0);
+}
+
+.x-form-trigger-wrap{
+ .x-form-spinner-up{
+ height:10px;
+ @include border-radius(0 3px 0 0);
+ background:#666 murano-image('triggericons/spinner-up.png') center top no-repeat;
+ border-bottom:1px solid #444;
+ &-over{
+ background-color:#999;
+ }
+ }
+ .x-form-spinner-down{
+ height:9px;
+ border-top:none;
+ @include border-radius(0 0 3px 0);
+ background:#555 murano-image('triggericons/spinner-down.png') center top no-repeat;
+ border-top:1px solid #888;
+ &-over{
+ background-color:#888;
+ border-color:#888;
+ }
+ }
+}
+.x-form-trigger-wrap-focus{
+ .x-form-spinner-up{
+ background-color:#999;
+ }
+ .x-form-spinner-down{
+ background-color:#888;
+ }
+}
+
+.x-form-trigger-wrap-focus{
+ .x-form-trigger{
+ background-color:#AAA;
+ border-color:#AAA;
+ &-click{
+ background-color:#888;
+ border-color:#888;
+ }
+ }
+}
+
+.x-form-trigger{
+ @include border-radius(0 3px 3px 0);
+ width:16px;
+ height:19px;
+ float:left;
+ background-color:#666;
+ border:1px solid #666;
+ &-over{
+ background-color:#AAA;
+ border-color:#AAA;
+ }
+ &-click{
+ background-color:#888;
+ border-color:#888;
+ }
+}
+
+
+.x-form-clear-trigger{
+ @include border-radius(0);
+ border-right-color:#888;
+}
+
+@include trigger(arrow, murano-image('triggericons/chev.png'));
+@include trigger(time, murano-image('triggericons/time.png'));
+@include trigger(date, murano-image('triggericons/date.png'));
+@include trigger(clear, murano-image('triggericons/clear.png'));
+@include trigger(search, murano-image('triggericons/search.png'));
\ No newline at end of file
--- /dev/null
+.x-accordion-hd{
+ .x-panel-header-text{
+ color:#FFF !important;
+ text-shadow:0 -1px 0 bla(.35);
+ }
+ @include background-image($gloss-gradient !important);
+ background-color:#666 !important;
+ padding:0 5px;
+ border-top:1px solid #999 !important;
+ border-bottom:1px solid #555 !important;
+ .x-tool{
+ top:3px !important;
+ }
+}
\ No newline at end of file
--- /dev/null
+@import 'accordion';
\ No newline at end of file
});
}
callback(new Gilbert.lib.ui.DjangoForm(Ext.applyIf(Ext.applyIf(config||{},{
- title: 'Editing '+model.verbose_name+' ('+pk+')',
+ title: 'Editing '+model.verbose_name.capfirst()+' ('+pk+')',
header: false,
iconCls: 'icon-pencil',
baseCls: 'x-plain',
});
+Gilbert.lib.plugins.models.ui.ForeignKeyColumn = Ext.extend(Ext.grid.Column, {
+ renderer: function(v) {
+ return v.__unicode__
+ }
+})
+
+
+Ext.grid.Column.types['foreignkeycolumn'] = Gilbert.lib.plugins.models.ui.ForeignKeyColumn
+
+
Gilbert.lib.plugins.models.ui.ModelPanel = Ext.extend(Ext.Panel, {
constructor: function (model, plugin, config) {
var model = this.model = model;
return new_consequences;
};
+ var new_consequences = convert_consequences_array(consequences);
+ var nested_consequences = false;
+ for(var i=0;i<new_consequences.length;i++){
+ if (!new_consequences[i]['leaf']) {
+ nested_consequences = true;
+ break;
+ }
+ }
+
var tree = this.tree = new Ext.tree.TreePanel({
loader: new Ext.tree.TreeLoader(),
enableDD: false,
'text': 'To be deleted',
'iconCls': 'icon-minus',
'leaf': false,
- 'children': convert_consequences_array(consequences),
+ 'children': new_consequences,
},
useArrows: true,
rootVisible: false,
{
region: 'north',
xtype: 'panel',
- html: 'Are you sure you want to delete these ' + model.verbose_name_plural + '?',
+ html: 'Are you sure you want to delete these ' + model.verbose_name_plural + '?' + (nested_consequences ? ' Nested objects will also be deleted.' : ''),
bodyStyle: 'padding: 15px;',
},
tree,
contextmenu.showAt(e.xy);
});
+ grid.on('rowdblclick', function(grid, rowIndex, e) {
+ var record = grid.getStore().getAt(rowIndex)
+ plugin.create_instance_window(model, record.id, function (win) {
+ win.on('saved', function () {
+ store.reload();
+ });
+ win.show();
+ });
+ });
+
grid.getSelectionModel().on('selectionchange', function (selmodel) {
if (selmodel.hasSelection()) {
edit_action.setDisabled(false);
{ xtype: 'tbseparator' },
edit_action,
delete_action,
- '->',
- {
- text: 'Advanced',
- iconCls: 'icon-gear',
- disabled: true,
- menu: [],
- },
+ //'->',
+ //{
+ // text: 'Advanced',
+ // iconCls: 'icon-gear',
+ // disabled: true,
+ // menu: [],
+ //},
],
}),
items: [grid],
application.on('model_registered', function (model) {
this.handle_new_model(model);
}, this);
+
+ this.instance_windows = {}
},
handle_new_model: function (model) {
},
create_instance_window: function (model, pk, callback, config, cls) {
+ if (pk != undefined) {
+ var win = this.instance_windows[[model.app_label, model.name, pk]];
+ if (win != undefined){
+ win.show();
+ return;
+ };
+ };
var pk = pk;
var callback = callback;
var application = this.application;
},
],
});
+ if (pk != undefined) {
+ outer.instance_windows[[model.app_label, model.name, pk]] = win
+ win.on('close', function(){
+ delete outer.instance_windows[[model.app_label, model.name, pk]];
+ });
+ }
win.addEvents({
'saved': true,
});
Gilbert.on('ready', function (application) {
- application.register_plugin('auth', new Gilbert.lib.plugins.models.Plugin());
+ application.register_plugin('models', new Gilbert.lib.plugins.models.Plugin());
});
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>{% block head %}
+ <title>{% block title %}{{ gilbert.title }}{% endblock %}</title>
+
+ {% block css %}
+ <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.murano" title="murano" href="{{ STATIC_URL }}gilbert/murano/css/murano.css"{% if request.GET.theme and request.GET.theme != 'murano' %} disabled="disabled"{% endif %} />
+ <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.access" title="access" href="{{ STATIC_URL }}gilbert/extjs/resources/css/ext-all-access.css"{% if request.GET.theme != 'access' %} disabled="disabled"{% endif %} />
+ <link rel="stylesheet" type="text/css" class="gilbert.theme" id="gilbert.theme.blue" title="blue" href="{{ STATIC_URL }}gilbert/extjs/resources/css/ext-all.css"{% if request.GET.theme != 'blue' %} disabled="disabled"{% endif %} />
+ {% endblock %}
+
+ {% block js %}
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/adapter/ext/ext-base.js"></script>
+ {% if request.GET.debug %}
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/ext-all-debug.js"></script>
+ {% else %}
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/ext-all.js"></script>
+ {% endif %}
+ <script type="text/javascript">
+ Ext.BLANK_IMAGE_URL = '{{ STATIC_URL }}gilbert/extjs/resources/images/default/s.gif';
+ </script>
+ {% endblock %}
+
+ {% block extrahead %}
+ {% endblock %}
+
+{% endblock %}</head>
+<body style="background-image: url({{ STATIC_URL }}gilbert/wallpaper.jpg);">{% block body %}{% endblock %}</body>
+</html>
--- /dev/null
+{% for icon_name in icon_names %}
+.icon-{{ icon_name }} {
+ background: url({{ STATIC_URL }}gilbert/fugue-icons/icons-shadowless/{{ icon_name }}.png) 0 no-repeat !important;
+}
+{% endfor %}
\ No newline at end of file
--- /dev/null
+{% extends 'gilbert/base.html' %}
+
+{% block css %}{{ block.super }}
+ <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}gilbert/extjs/examples/ux/fileuploadfield/css/fileuploadfield.css" />
+ <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}gilbert/superboxselect/superboxselect.css" />
+ <link rel="stylesheet" type="text/css" href="{% url gilbert:icons %}" />
+
+ {% for router in gilbert.model_routers.values %}{% for admin in router.models.values %}{% for css_url in admin.index_css_urls %}
+ <link rel="stylesheet" type="text/css" href="{{ css_url }}" />
+ {% endfor %}{% endfor %}{% endfor %}
+
+ {% for plugin in plugins %}{% for css_url in plugin.index_css_urls %}
+ <link rel="stylesheet" type="text/css" href="{{ css_url }}" />
+ {% endfor %}{% endfor %}
+{% endblock %}
+
+{% block js %}{{ block.super }}
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/examples/ux/FieldLabeler.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/examples/ux/fileuploadfield/FileUploadField.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/superboxselect/SuperBoxSelect.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/examples/ux/Reorderer.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/examples/ux/ToolbarReorderer.js"></script>
+
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/lib/app.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/lib/models.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/lib/plugins.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/lib/ui/forms.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/lib/ui/windows.js"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/gilbert.js"></script>
+
+ <script type="text/javascript" src="{% url gilbert:api %}"></script>
+
+ {% for router in gilbert.model_routers.values %}{% for admin in router.models.values %}{% for js_url in admin.index_js_urls %}
+ <script type="text/javascript" src="{{ js_url }}"></script>
+ {% endfor %}{% endfor %}{% endfor %}
+
+ {% for plugin in plugins %}{% for js_url in plugin.index_js_urls %}
+ <script type="text/javascript" src="{{ js_url }}"></script>
+ {% endfor %}{% endfor %}
+{% endblock %}
+
+{% block extrahead %}
+ {% for router in gilbert.model_routers.values %}{% for admin in router.models.values %}{{ admin.index_extrahead }}{% endfor %}{% endfor %}
+ {% for plugin in plugins %}{{ plugin.index_extrahead }}{% endfor %}
+{% endblock %}
\ No newline at end of file
{% extends 'gilbert/base.html' %}
-{% load staticmedia %}
{% block css %}{{ block.super }}
- <link rel="stylesheet" type="text/css" href="{% mediaurl 'gilbert/extjs/examples/ux/statusbar/css/statusbar.css' %}" />
+ <link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}gilbert/extjs/examples/ux/statusbar/css/statusbar.css" />
<style type="text/css">
.icon-door-open-in {
- background: url({% mediaurl 'gilbert/fugue-icons/icons-shadowless' %}/door-open-in.png) no-repeat !important;
+ background: url({{ STATIC_URL }}gilbert/fugue-icons/icons-shadowless/door-open-in.png) no-repeat !important;
}
.x-statusbar .x-status-error {
cursor: help;
- background-image: url({% mediaurl 'gilbert/fugue-icons/icons-shadowless' %}/exclamation-red.png) !important;
+ background-image: url({{ STATIC_URL }}gilbert/fugue-icons/icons-shadowless/exclamation-red.png) !important;
}
</style>
{% endblock %}
{% block js %}{{ block.super }}
- <script type="text/javascript" src="{% mediaurl 'gilbert/extjs/examples/ux/statusbar/StatusBar.js' %}"></script>
+ <script type="text/javascript" src="{{ STATIC_URL }}gilbert/extjs/examples/ux/statusbar/StatusBar.js"></script>
<script type="text/javascript" charset="utf-8">
Ext.onReady(function () {
--- /dev/null
+from django.contrib import admin
+from philo.admin import EntityAdmin, COLLAPSE_CLASSES
+from philo.contrib.julian.models import Location, Event, Calendar, CalendarView
+
+
+class LocationAdmin(EntityAdmin):
+ pass
+
+
+class EventAdmin(EntityAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': ('name', 'slug', 'description', 'tags', 'owner')
+ }),
+ ('Location', {
+ 'fields': ('location_content_type', 'location_pk')
+ }),
+ ('Time', {
+ 'fields': (('start_date', 'start_time'), ('end_date', 'end_time'),),
+ }),
+ ('Advanced', {
+ 'fields': ('parent_event', 'site',),
+ 'classes': COLLAPSE_CLASSES
+ })
+ )
+ filter_horizontal = ['tags']
+ raw_id_fields = ['parent_event']
+ related_lookup_fields = {
+ 'fk': raw_id_fields,
+ 'generic': [["location_content_type", "location_pk"]]
+ }
+ prepopulated_fields = {'slug': ('name',)}
+
+
+class CalendarAdmin(EntityAdmin):
+ prepopulated_fields = {'slug': ('name',)}
+ filter_horizontal = ['events']
+ fieldsets = (
+ (None, {
+ 'fields': ('name', 'description', 'events')
+ }),
+ ('Advanced', {
+ 'fields': ('slug', 'site', 'language',),
+ 'classes': COLLAPSE_CLASSES
+ })
+ )
+
+
+class CalendarViewAdmin(EntityAdmin):
+ fieldsets = (
+ (None, {
+ 'fields': ('calendar',)
+ }),
+ ('Pages', {
+ 'fields': ('index_page', 'event_detail_page')
+ }),
+ ('General Settings', {
+ 'fields': ('tag_permalink_base', 'owner_permalink_base', 'location_permalink_base', 'events_per_page')
+ }),
+ ('Event List Pages', {
+ 'fields': ('timespan_page', 'tag_page', 'location_page', 'owner_page'),
+ 'classes': COLLAPSE_CLASSES
+ }),
+ ('Archive Pages', {
+ 'fields': ('location_archive_page', 'tag_archive_page', 'owner_archive_page'),
+ 'classes': COLLAPSE_CLASSES
+ }),
+ ('Feed Settings', {
+ 'fields': ( 'feeds_enabled', 'feed_suffix', 'feed_type', 'item_title_template', 'item_description_template',),
+ 'classes': COLLAPSE_CLASSES
+ })
+ )
+ raw_id_fields = ('index_page', 'event_detail_page', 'timespan_page', 'tag_page', 'location_page', 'owner_page', 'location_archive_page', 'tag_archive_page', 'owner_archive_page', 'item_title_template', 'item_description_template',)
+ related_lookup_fields = {'fk': raw_id_fields}
+
+
+admin.site.register(Location, LocationAdmin)
+admin.site.register(Event, EventAdmin)
+admin.site.register(Calendar, CalendarAdmin)
+admin.site.register(CalendarView, CalendarViewAdmin)
\ No newline at end of file
--- /dev/null
+from django.http import HttpResponse
+from django.utils.feedgenerator import SyndicationFeed
+import vobject
+
+
+# Map the keys in the ICalendarFeed internal dictionary to the names of iCalendar attributes.
+FEED_ICAL_MAP = {
+ 'title': 'x-wr-calname',
+ 'description': 'x-wr-caldesc',
+ #'link': ???,
+ #'language': ???,
+ #author_email
+ #author_name
+ #author_link
+ #subtitle
+ #categories
+ #feed_url
+ #feed_copyright
+ 'id': 'prodid',
+ 'ttl': 'x-published-ttl'
+}
+
+
+ITEM_ICAL_MAP = {
+ 'title': 'summary',
+ 'description': 'description',
+ 'link': 'url',
+ # author_email, author_name, and author_link need special handling. Consider them the
+ # 'organizer' of the event <http://tools.ietf.org/html/rfc5545#section-3.8.4.3> and
+ # construct something based on that.
+ 'pubdate': 'created',
+ 'last_modified': 'last-modified',
+ #'comments' require special handling as well <http://tools.ietf.org/html/rfc5545#section-3.8.1.4>
+ 'unique_id': 'uid',
+ 'enclosure': 'attach', # does this need special handling?
+ 'categories': 'categories', # does this need special handling?
+ # ttl is ignored.
+ 'start': 'dtstart',
+ 'end': 'dtend',
+}
+
+
+class ICalendarFeed(SyndicationFeed):
+ mime_type = 'text/calendar'
+
+ def add_item(self, *args, **kwargs):
+ for kwarg in ['start', 'end', 'last_modified', 'location']:
+ kwargs.setdefault(kwarg, None)
+ super(ICalendarFeed, self).add_item(*args, **kwargs)
+
+ def write(self, outfile, encoding):
+ # TODO: Use encoding... how? Just convert all values when setting them should work...
+ cal = vobject.iCalendar()
+
+ # IE/Outlook needs this. See
+ # <http://blog.thescoop.org/archives/2007/07/31/django-ical-and-vobject/>
+ cal.add('method').value = 'PUBLISH'
+
+ for key, val in self.feed.items():
+ if key in FEED_ICAL_MAP and val:
+ cal.add(FEED_ICAL_MAP[key]).value = val
+
+ for item in self.items:
+ # TODO: handle multiple types of events.
+ event = cal.add('vevent')
+ for key, val in item.items():
+ #TODO: handle the non-standard items like comments and author.
+ if key in ITEM_ICAL_MAP and val:
+ event.add(ITEM_ICAL_MAP[key]).value = val
+
+ cal.serialize(outfile)
+
+ # Some special handling for HttpResponses. See link above.
+ if isinstance(outfile, HttpResponse):
+ filename = self.feed.get('filename', 'filename.ics')
+ outfile['Filename'] = filename
+ outfile['Content-Disposition'] = 'attachment; filename=%s' % filename
\ No newline at end of file
--- /dev/null
+# encoding: utf-8
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+
+ # Adding model 'Location'
+ db.create_table('julian_location', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=255, db_index=True)),
+ ))
+ db.send_create_signal('julian', ['Location'])
+
+ # Adding model 'Event'
+ db.create_table('julian_event', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('start_date', self.gf('django.db.models.fields.DateField')()),
+ ('start_time', self.gf('django.db.models.fields.TimeField')(null=True, blank=True)),
+ ('end_date', self.gf('django.db.models.fields.DateField')()),
+ ('end_time', self.gf('django.db.models.fields.TimeField')(null=True, blank=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255, db_index=True)),
+ ('location_content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'], null=True, blank=True)),
+ ('location_pk', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ('description', self.gf('philo.models.fields.TemplateField')()),
+ ('parent_event', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['julian.Event'], null=True, blank=True)),
+ ('owner', self.gf('django.db.models.fields.related.ForeignKey')(related_name='owned_events', to=orm['auth.User'])),
+ ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ('last_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
+ ('site', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+ ))
+ db.send_create_signal('julian', ['Event'])
+
+ # Adding unique constraint on 'Event', fields ['site', 'created']
+ db.create_unique('julian_event', ['site_id', 'created'])
+
+ # Adding M2M table for field tags on 'Event'
+ db.create_table('julian_event_tags', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('event', models.ForeignKey(orm['julian.event'], null=False)),
+ ('tag', models.ForeignKey(orm['philo.tag'], null=False))
+ ))
+ db.create_unique('julian_event_tags', ['event_id', 'tag_id'])
+
+ # Adding model 'Calendar'
+ db.create_table('julian_calendar', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=100, db_index=True)),
+ ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ('site', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+ ('language', self.gf('django.db.models.fields.CharField')(default='en', max_length=5)),
+ ))
+ db.send_create_signal('julian', ['Calendar'])
+
+ # Adding unique constraint on 'Calendar', fields ['name', 'site', 'language']
+ db.create_unique('julian_calendar', ['name', 'site_id', 'language'])
+
+ # Adding M2M table for field events on 'Calendar'
+ db.create_table('julian_calendar_events', (
+ ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
+ ('calendar', models.ForeignKey(orm['julian.calendar'], null=False)),
+ ('event', models.ForeignKey(orm['julian.event'], null=False))
+ ))
+ db.create_unique('julian_calendar_events', ['calendar_id', 'event_id'])
+
+ # Adding model 'CalendarView'
+ db.create_table('julian_calendarview', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('feed_type', self.gf('django.db.models.fields.CharField')(default='text/calendar', max_length=50)),
+ ('feed_suffix', self.gf('django.db.models.fields.CharField')(default='feed', max_length=255)),
+ ('feeds_enabled', self.gf('django.db.models.fields.BooleanField')(default=True)),
+ ('feed_length', self.gf('django.db.models.fields.PositiveIntegerField')(default=15, null=True, blank=True)),
+ ('item_title_template', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='julian_calendarview_title_related', null=True, to=orm['philo.Template'])),
+ ('item_description_template', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='julian_calendarview_description_related', null=True, to=orm['philo.Template'])),
+ ('calendar', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['julian.Calendar'])),
+ ('index_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_index_related', to=orm['philo.Page'])),
+ ('event_detail_page', self.gf('django.db.models.fields.related.ForeignKey')(related_name='calendar_detail_related', to=orm['philo.Page'])),
+ ('timespan_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_timespan_related', null=True, to=orm['philo.Page'])),
+ ('tag_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_tag_related', null=True, to=orm['philo.Page'])),
+ ('location_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_location_related', null=True, to=orm['philo.Page'])),
+ ('owner_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_owner_related', null=True, to=orm['philo.Page'])),
+ ('tag_archive_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_tag_archive_related', null=True, to=orm['philo.Page'])),
+ ('location_archive_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_location_archive_related', null=True, to=orm['philo.Page'])),
+ ('owner_archive_page', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='calendar_owner_archive_related', null=True, to=orm['philo.Page'])),
+ ('tag_permalink_base', self.gf('django.db.models.fields.CharField')(default='tags', max_length=30)),
+ ('owner_permalink_base', self.gf('django.db.models.fields.CharField')(default='owners', max_length=30)),
+ ('location_permalink_base', self.gf('django.db.models.fields.CharField')(default='locations', max_length=30)),
+ ('events_per_page', self.gf('django.db.models.fields.PositiveIntegerField')(null=True, blank=True)),
+ ))
+ db.send_create_signal('julian', ['CalendarView'])
+
+
+ def backwards(self, orm):
+
+ # Removing unique constraint on 'Calendar', fields ['name', 'site', 'language']
+ db.delete_unique('julian_calendar', ['name', 'site_id', 'language'])
+
+ # Removing unique constraint on 'Event', fields ['site', 'created']
+ db.delete_unique('julian_event', ['site_id', 'created'])
+
+ # Deleting model 'Location'
+ db.delete_table('julian_location')
+
+ # Deleting model 'Event'
+ db.delete_table('julian_event')
+
+ # Removing M2M table for field tags on 'Event'
+ db.delete_table('julian_event_tags')
+
+ # Deleting model 'Calendar'
+ db.delete_table('julian_calendar')
+
+ # Removing M2M table for field events on 'Calendar'
+ db.delete_table('julian_calendar_events')
+
+ # Deleting model 'CalendarView'
+ db.delete_table('julian_calendarview')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+ 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ 'julian.calendar': {
+ 'Meta': {'unique_together': "(('name', 'site', 'language'),)", 'object_name': 'Calendar'},
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'events': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'calendars'", 'blank': 'True', 'to': "orm['julian.Event']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '5'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '100', 'db_index': 'True'})
+ },
+ 'julian.calendarview': {
+ 'Meta': {'object_name': 'CalendarView'},
+ 'calendar': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Calendar']"}),
+ 'event_detail_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_detail_related'", 'to': "orm['philo.Page']"}),
+ 'events_per_page': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
+ 'feed_length': ('django.db.models.fields.PositiveIntegerField', [], {'default': '15', 'null': 'True', 'blank': 'True'}),
+ 'feed_suffix': ('django.db.models.fields.CharField', [], {'default': "'feed'", 'max_length': '255'}),
+ 'feed_type': ('django.db.models.fields.CharField', [], {'default': "'text/calendar'", 'max_length': '50'}),
+ 'feeds_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'index_page': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'calendar_index_related'", 'to': "orm['philo.Page']"}),
+ 'item_description_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_calendarview_description_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'item_title_template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'julian_calendarview_title_related'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'location_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_location_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'location_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_location_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'location_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'locations'", 'max_length': '30'}),
+ 'owner_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_owner_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'owner_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_owner_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'owner_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'owners'", 'max_length': '30'}),
+ 'tag_archive_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_tag_archive_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'tag_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_tag_related'", 'null': 'True', 'to': "orm['philo.Page']"}),
+ 'tag_permalink_base': ('django.db.models.fields.CharField', [], {'default': "'tags'", 'max_length': '30'}),
+ 'timespan_page': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'calendar_timespan_related'", 'null': 'True', 'to': "orm['philo.Page']"})
+ },
+ 'julian.event': {
+ 'Meta': {'unique_together': "(('site', 'created'),)", 'object_name': 'Event'},
+ 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'description': ('philo.models.fields.TemplateField', [], {}),
+ 'end_date': ('django.db.models.fields.DateField', [], {}),
+ 'end_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'last_modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+ 'location_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'owned_events'", 'to': "orm['auth.User']"}),
+ 'parent_event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['julian.Event']", 'null': 'True', 'blank': 'True'}),
+ 'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'start_date': ('django.db.models.fields.DateField', [], {}),
+ 'start_time': ('django.db.models.fields.TimeField', [], {'null': 'True', 'blank': 'True'}),
+ 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'events'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['philo.Tag']"})
+ },
+ 'julian.location': {
+ 'Meta': {'object_name': 'Location'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'oberlin.locationcoordinates': {
+ 'Meta': {'unique_together': "(('location_ct', 'location_pk'),)", 'object_name': 'LocationCoordinates'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'latitude': ('django.db.models.fields.FloatField', [], {}),
+ 'location_ct': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'location_pk': ('django.db.models.fields.TextField', [], {}),
+ 'longitude': ('django.db.models.fields.FloatField', [], {})
+ },
+ 'philo.attribute': {
+ 'Meta': {'unique_together': "(('key', 'entity_content_type', 'entity_object_id'), ('value_content_type', 'value_object_id'))", 'object_name': 'Attribute'},
+ 'entity_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_entity_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'entity_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'value_content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attribute_value_set'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
+ 'value_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+ },
+ 'philo.node': {
+ 'Meta': {'object_name': 'Node'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Node']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'view_content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'node_view_set'", 'to': "orm['contenttypes.ContentType']"}),
+ 'view_object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
+ },
+ 'philo.page': {
+ 'Meta': {'object_name': 'Page'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'pages'", 'to': "orm['philo.Template']"}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'philo.tag': {
+ 'Meta': {'ordering': "('name',)", 'object_name': 'Tag'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'})
+ },
+ 'philo.template': {
+ 'Meta': {'object_name': 'Template'},
+ 'code': ('philo.models.fields.TemplateField', [], {}),
+ 'documentation': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'lft': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'mimetype': ('django.db.models.fields.CharField', [], {'default': "'text/html'", 'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
+ 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['philo.Template']"}),
+ 'rght': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'db_index': 'True'}),
+ 'tree_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'root_node': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'sites'", 'null': 'True', 'to': "orm['philo.Node']"})
+ }
+ }
+
+ complete_apps = ['julian']
--- /dev/null
+from django.conf import settings
+from django.conf.urls.defaults import url, patterns, include
+from django.contrib.auth.models import User
+from django.contrib.contenttypes.generic import GenericForeignKey
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.sites.models import Site
+from django.core.exceptions import ValidationError, ObjectDoesNotExist
+from django.core.validators import RegexValidator
+from django.db import models
+from django.db.models.query import QuerySet
+from django.http import HttpResponse, Http404
+from django.utils.encoding import force_unicode
+from philo.contrib.julian.feedgenerator import ICalendarFeed
+from philo.contrib.penfield.models import FeedView, FEEDS
+from philo.exceptions import ViewCanNotProvideSubpath
+from philo.models import Tag, Entity, Page, TemplateField
+from philo.utils import ContentTypeRegistryLimiter
+import datetime, calendar
+
+
+__all__ = ('register_location_model', 'unregister_location_model', 'Location', 'TimedModel', 'Event', 'Calendar', 'CalendarView',)
+
+
+ICALENDAR = ICalendarFeed.mime_type
+FEEDS[ICALENDAR] = ICalendarFeed
+try:
+ DEFAULT_SITE = Site.objects.get_current()
+except:
+ DEFAULT_SITE = None
+_languages = dict(settings.LANGUAGES)
+try:
+ _languages[settings.LANGUAGE_CODE]
+ DEFAULT_LANGUAGE = settings.LANGUAGE_CODE
+except KeyError:
+ try:
+ lang = settings.LANGUAGE_CODE.split('-')[0]
+ _languages[lang]
+ DEFAULT_LANGUAGE = lang
+ except KeyError:
+ DEFAULT_LANGUAGE = None
+
+
+location_content_type_limiter = ContentTypeRegistryLimiter()
+
+
+def register_location_model(model):
+ location_content_type_limiter.register_class(model)
+
+
+def unregister_location_model(model):
+ location_content_type_limiter.unregister_class(model)
+
+
+class Location(Entity):
+ name = models.CharField(max_length=255)
+ slug = models.SlugField(max_length=255, unique=True)
+
+ def __unicode__(self):
+ return self.name
+
+
+register_location_model(Location)
+
+
+class TimedModel(models.Model):
+ start_date = models.DateField(help_text="YYYY-MM-DD")
+ start_time = models.TimeField(blank=True, null=True, help_text="HH:MM:SS - 24 hour clock")
+ end_date = models.DateField()
+ end_time = models.TimeField(blank=True, null=True)
+
+ def is_all_day(self):
+ return self.start_time is None and self.end_time is None
+
+ def clean(self):
+ if bool(self.start_time) != bool(self.end_time):
+ raise ValidationError("A %s must have either a start time and an end time or neither.")
+
+ if self.start_date > self.end_date or self.start_date == self.end_date and self.start_time > self.end_time:
+ raise ValidationError("A %s cannot end before it starts." % self.__class__.__name__)
+
+ def get_start(self):
+ return datetime.datetime.combine(self.start_date, self.start_time) if self.start_time else self.start_date
+
+ def get_end(self):
+ return datetime.datetime.combine(self.end_date, self.end_time) if self.end_time else self.end_date
+
+ class Meta:
+ abstract = True
+
+
+class EventManager(models.Manager):
+ def get_query_set(self):
+ return EventQuerySet(self.model)
+
+class EventQuerySet(QuerySet):
+ def upcoming(self):
+ return self.filter(start_date__gte=datetime.date.today())
+ def current(self):
+ return self.filter(start_date__lte=datetime.date.today(), end_date__gte=datetime.date.today())
+ def single_day(self):
+ return self.filter(start_date__exact=models.F('end_date'))
+ def multiday(self):
+ return self.exclude(start_date__exact=models.F('end_date'))
+
+class Event(Entity, TimedModel):
+ name = models.CharField(max_length=255)
+ slug = models.SlugField(max_length=255, unique_for_date='start_date')
+
+ location_content_type = models.ForeignKey(ContentType, limit_choices_to=location_content_type_limiter, blank=True, null=True)
+ location_pk = models.TextField(blank=True)
+ location = GenericForeignKey('location_content_type', 'location_pk')
+
+ description = TemplateField()
+
+ tags = models.ManyToManyField(Tag, related_name='events', blank=True, null=True)
+
+ parent_event = models.ForeignKey('self', blank=True, null=True)
+
+ # TODO: "User module"
+ owner = models.ForeignKey(User, related_name='owned_events')
+
+ created = models.DateTimeField(auto_now_add=True)
+ last_modified = models.DateTimeField(auto_now=True)
+
+ site = models.ForeignKey(Site, default=DEFAULT_SITE)
+
+ @property
+ def uuid(self):
+ return "%s@%s" % (self.created.isoformat(), getattr(self.site, 'domain', 'None'))
+
+ objects = EventManager()
+
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ unique_together = ('site', 'created')
+
+
+class Calendar(Entity):
+ name = models.CharField(max_length=100)
+ slug = models.SlugField(max_length=100)
+ description = models.TextField(blank=True)
+ events = models.ManyToManyField(Event, related_name='calendars', blank=True)
+
+ site = models.ForeignKey(Site, default=DEFAULT_SITE)
+ language = models.CharField(max_length=5, choices=settings.LANGUAGES, default=DEFAULT_LANGUAGE)
+
+ def __unicode__(self):
+ return self.name
+
+ @property
+ def fpi(self):
+ # See http://xml.coverpages.org/tauber-fpi.html or ISO 9070:1991 for format information.
+ return "-//%s//%s//%s" % (self.site.name, self.name, self.language.split('-')[0].upper())
+
+ class Meta:
+ unique_together = ('name', 'site', 'language')
+
+
+class CalendarView(FeedView):
+ calendar = models.ForeignKey(Calendar)
+ index_page = models.ForeignKey(Page, related_name="calendar_index_related")
+ event_detail_page = models.ForeignKey(Page, related_name="calendar_detail_related")
+
+ timespan_page = models.ForeignKey(Page, related_name="calendar_timespan_related", blank=True, null=True)
+ tag_page = models.ForeignKey(Page, related_name="calendar_tag_related", blank=True, null=True)
+ location_page = models.ForeignKey(Page, related_name="calendar_location_related", blank=True, null=True)
+ owner_page = models.ForeignKey(Page, related_name="calendar_owner_related", blank=True, null=True)
+
+ tag_archive_page = models.ForeignKey(Page, related_name="calendar_tag_archive_related", blank=True, null=True)
+ location_archive_page = models.ForeignKey(Page, related_name="calendar_location_archive_related", blank=True, null=True)
+ owner_archive_page = models.ForeignKey(Page, related_name="calendar_owner_archive_related", blank=True, null=True)
+
+ tag_permalink_base = models.CharField(max_length=30, default='tags')
+ owner_permalink_base = models.CharField(max_length=30, default='owners')
+ location_permalink_base = models.CharField(max_length=30, default='locations')
+ events_per_page = models.PositiveIntegerField(blank=True, null=True)
+
+ item_context_var = "events"
+ object_attr = "calendar"
+
+ def get_reverse_params(self, obj):
+ if isinstance(obj, User):
+ return 'events_for_user', [], {'username': obj.username}
+ elif isinstance(obj, Event):
+ return 'event_detail', [], {
+ 'year': str(obj.start_date.year).zfill(4),
+ 'month': str(obj.start_date.month).zfill(2),
+ 'day': str(obj.start_date.day).zfill(2),
+ 'slug': obj.slug
+ }
+ elif isinstance(obj, Tag) or isinstance(obj, models.query.QuerySet) and obj.model == Tag:
+ if isinstance(obj, Tag):
+ obj = [obj]
+ return 'entries_by_tag', [], {'tag_slugs': '/'.join(obj)}
+ raise ViewCanNotProvideSubpath
+
+ def timespan_patterns(self, pattern, timespan_name):
+ return self.feed_patterns(pattern, 'get_events_by_timespan', 'timespan_page', "events_by_%s" % timespan_name)
+
+ @property
+ def urlpatterns(self):
+ # Perhaps timespans should be done with GET parameters? Or two /-separated
+ # date slugs? (e.g. 2010-02-1/2010-02-2) or a start and duration?
+ # (e.g. 2010-02-01/week/ or ?d=2010-02-01&l=week)
+ urlpatterns = self.feed_patterns(r'^', 'get_all_events', 'index_page', 'index') + \
+ self.timespan_patterns(r'^(?P<year>\d{4})', 'year') + \
+ self.timespan_patterns(r'^(?P<year>\d{4})/(?P<month>\d{2})', 'month') + \
+ self.timespan_patterns(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})', 'day') + \
+ self.feed_patterns(r'^%s/(?P<username>[^/]+)' % self.owner_permalink_base, 'get_events_by_owner', 'owner_page', 'events_by_user') + \
+ self.feed_patterns(r'^%s/(?P<app_label>\w+)/(?P<model>\w+)/(?P<pk>[^/]+)' % self.location_permalink_base, 'get_events_by_location', 'location_page', 'events_by_location') + \
+ self.feed_patterns(r'^%s/(?P<tag_slugs>[-\w]+[-+/\w]*)' % self.tag_permalink_base, 'get_events_by_tag', 'tag_page', 'events_by_tag') + \
+ patterns('',
+ url(r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[\w-]+)$', self.event_detail_view, name="event_detail"),
+ )
+
+ # Some sort of shortcut for a location would be useful. This could be on a per-calendar
+ # or per-calendar-view basis.
+ #url(r'^%s/(?P<slug>[\w-]+)' % self.location_permalink_base, ...)
+
+ if self.tag_archive_page:
+ urlpatterns += patterns('',
+ url(r'^%s$' % self.tag_permalink_base, self.tag_archive_view, name='tag_archive')
+ )
+
+ if self.owner_archive_page:
+ urlpatterns += patterns('',
+ url(r'^%s$' % self.owner_permalink_base, self.owner_archive_view, name='owner_archive')
+ )
+
+ if self.location_archive_page:
+ urlpatterns += patterns('',
+ url(r'^%s$' % self.location_permalink_base, self.location_archive_view, name='location_archive')
+ )
+ return urlpatterns
+
+ # Basic QuerySet fetchers.
+ def get_event_queryset(self):
+ return self.calendar.events.all()
+
+ def get_timespan_queryset(self, year, month=None, day=None):
+ qs = self.get_event_queryset()
+ # See python documentation for the min/max values.
+ if year and month and day:
+ year, month, day = int(year), int(month), int(day)
+ start_datetime = datetime.datetime(year, month, day, 0, 0)
+ end_datetime = datetime.datetime(year, month, day, 23, 59)
+ elif year and month:
+ year, month = int(year), int(month)
+ start_datetime = datetime.datetime(year, month, 1, 0, 0)
+ end_datetime = datetime.datetime(year, month, calendar.monthrange(year, month)[1], 23, 59)
+ else:
+ year = int(year)
+ start_datetime = datetime.datetime(year, 1, 1, 0, 0)
+ end_datetime = datetime.datetime(year, 12, 31, 23, 59)
+
+ return qs.exclude(end_date__lt=start_datetime, end_time__lt=start_datetime).exclude(start_date__gt=end_datetime, start_time__gt=end_datetime, start_time__isnull=False).exclude(start_time__isnull=True, start_date__gt=end_datetime)
+
+ def get_tag_queryset(self):
+ return Tag.objects.filter(events__calendars=self.calendar).distinct()
+
+ def get_location_querysets(self):
+ # Potential bottleneck?
+ location_map = {}
+ locations = Event.objects.values_list('location_content_type', 'location_pk')
+
+ for ct, pk in locations:
+ location_map.setdefault(ct, []).append(pk)
+
+ location_cts = ContentType.objects.in_bulk(location_map.keys())
+ location_querysets = {}
+
+ for ct_pk, pks in location_map.items():
+ ct = location_cts[ct_pk]
+ location_querysets[ct] = ct.model_class()._default_manager.filter(pk__in=pks)
+
+ return location_querysets
+
+ def get_owner_queryset(self):
+ return User.objects.filter(owned_events__calendars=self.calendar).distinct()
+
+ # Event QuerySet parsers for a request/args/kwargs
+ def get_all_events(self, request, extra_context=None):
+ return self.get_event_queryset(), extra_context
+
+ def get_events_by_timespan(self, request, year, month=None, day=None, extra_context=None):
+ context = extra_context or {}
+ context.update({
+ 'year': year,
+ 'month': month,
+ 'day': day
+ })
+ return self.get_timespan_queryset(year, month, day), context
+
+ def get_events_by_owner(self, request, username, extra_context=None):
+ try:
+ owner = self.get_owner_queryset().get(username=username)
+ except User.DoesNotExist:
+ raise Http404
+
+ qs = self.get_event_queryset().filter(owner=owner)
+ context = extra_context or {}
+ context.update({
+ 'owner': owner
+ })
+ return qs, context
+
+ def get_events_by_tag(self, request, tag_slugs, extra_context=None):
+ tag_slugs = tag_slugs.replace('+', '/').split('/')
+ tags = self.get_tag_queryset().filter(slug__in=tag_slugs)
+
+ if not tags:
+ raise Http404
+
+ # Raise a 404 on an incorrect slug.
+ found_slugs = [tag.slug for tag in tags]
+ for slug in tag_slugs:
+ if slug and slug not in found_slugs:
+ raise Http404
+
+ events = self.get_event_queryset()
+ for tag in tags:
+ events = events.filter(tags=tag)
+
+ context = extra_context or {}
+ context.update({'tags': tags})
+
+ return events, context
+
+ def get_events_by_location(self, request, app_label, model, pk, extra_context=None):
+ try:
+ ct = ContentType.objects.get(app_label=app_label, model=model)
+ location = ct.model_class()._default_manager.get(pk=pk)
+ except ObjectDoesNotExist:
+ raise Http404
+
+ events = self.get_event_queryset().filter(location_content_type=ct, location_pk=location.pk)
+
+ context = extra_context or {}
+ context.update({
+ 'location': location
+ })
+ return events, context
+
+ # Detail View.
+ def event_detail_view(self, request, year, month, day, slug, extra_context=None):
+ try:
+ event = Event.objects.select_related('parent_event').get(start_date__year=year, start_date__month=month, start_date__day=day, slug=slug)
+ except Event.DoesNotExist:
+ raise Http404
+
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'event': event
+ })
+ return self.event_detail_page.render_to_response(request, extra_context=context)
+
+ # Archive Views.
+ def tag_archive_view(self, request, extra_context=None):
+ tags = self.get_tag_queryset()
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'tags': tags
+ })
+ return self.tag_archive_page.render_to_response(request, extra_context=context)
+
+ def location_archive_view(self, request, extra_context=None):
+ # What datastructure should locations be?
+ locations = self.get_location_querysets()
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'locations': locations
+ })
+ return self.location_archive_page.render_to_response(request, extra_context=context)
+
+ def owner_archive_view(self, request, extra_context=None):
+ owners = self.get_owner_queryset()
+ context = self.get_context()
+ context.update(extra_context or {})
+ context.update({
+ 'owners': owners
+ })
+ return self.owner_archive_page.render_to_response(request, extra_context=context)
+
+ # Process page items
+ def process_page_items(self, request, items):
+ if self.events_per_page:
+ page_num = request.GET.get('page', 1)
+ paginator, paginated_page, items = paginate(items, self.events_per_page, page_num)
+ item_context = {
+ 'paginator': paginator,
+ 'paginated_page': paginated_page,
+ self.item_context_var: items
+ }
+ else:
+ item_context = {
+ self.item_context_var: items
+ }
+ return items, item_context
+
+ # Feed information hooks
+ def title(self, obj):
+ return obj.name
+
+ def link(self, obj):
+ # Link is ignored anyway...
+ return ""
+
+ def feed_guid(self, obj):
+ return obj.fpi
+
+ def description(self, obj):
+ return obj.description
+
+ def feed_extra_kwargs(self, obj):
+ return {'filename': "%s.ics" % obj.slug}
+
+ def item_title(self, item):
+ return item.name
+
+ def item_description(self, item):
+ return item.description
+
+ def item_link(self, item):
+ return self.reverse(item)
+
+ def item_guid(self, item):
+ return item.uuid
+
+ def item_author_name(self, item):
+ if item.owner:
+ return item.owner.get_full_name()
+
+ def item_author_email(self, item):
+ return getattr(item.owner, 'email', None) or None
+
+ def item_pubdate(self, item):
+ return item.created
+
+ def item_categories(self, item):
+ return [tag.name for tag in item.tags.all()]
+
+ def item_extra_kwargs(self, item):
+ return {
+ 'start': item.get_start(),
+ 'end': item.get_end(),
+ 'last_modified': item.last_modified,
+ # Is forcing unicode enough, or should we look for a "custom method"?
+ 'location': force_unicode(item.location),
+ }
+
+ def __unicode__(self):
+ return u"%s for %s" % (self.__class__.__name__, self.calendar)
+
+field = CalendarView._meta.get_field('feed_type')
+field._choices += ((ICALENDAR, 'iCalendar'),)
+field.default = ICALENDAR
\ No newline at end of file
'classes': COLLAPSE_CLASSES
}),
('Feed Settings', {
- 'fields': ( 'feeds_enabled', 'feed_suffix', 'feed_type', 'item_title_template', 'item_description_template',),
+ 'fields': ( 'feeds_enabled', 'feed_suffix', 'feed_type', 'feed_length', 'item_title_template', 'item_description_template',),
'classes': COLLAPSE_CLASSES
})
)
--- /dev/null
+from .models import Blog, BlogEntry, BlogView, NewsletterArticle, NewsletterIssue, Newsletter, NewsletterView
+from philo.contrib.gilbert import site
+from philo.contrib.gilbert.plugins.models import ModelAdmin
+
+
+class BlogAdmin(ModelAdmin):
+ search_fields = ('title',)
+
+
+class BlogEntryAdmin(ModelAdmin):
+ search_fields = ('title', 'content',)
+ data_columns = ('title', 'author', 'blog', 'date',)
+
+
+site.register_model(Blog, BlogAdmin, icon_name='blog')
+site.register_model(BlogEntry, BlogEntryAdmin, icon_name='document-snippet')
+site.register_model(BlogView, icon_name='application-blog')
+site.register_model(NewsletterArticle, icon_name='document-snippet')
+site.register_model(NewsletterIssue, icon_name='newspaper')
+site.register_model(Newsletter, icon_name='newspapers')
+site.register_model(NewsletterView, icon_name='application')
\ No newline at end of file
-from django import template
+from django import template, VERSION as django_version
from django.conf import settings
from django.utils.safestring import mark_safe
from philo.contrib.shipherd.models import Navigation
class RecurseNavigationNode(template.Node):
- def __init__(self, template_nodes, instance_var, key):
+ def __init__(self, template_nodes, instance_var, key_var):
self.template_nodes = template_nodes
self.instance_var = instance_var
- self.key = key
+ self.key_var = key_var
def render(self, context):
try:
return ''
instance = self.instance_var.resolve(context)
+ key = self.key_var.resolve(context)
+
+ # Fall back on old behavior if the key doesn't seem to be a variable.
+ if not key:
+ token = self.key_var.token
+ if token[0] not in ["'", '"'] and '.' not in token:
+ key = token
+ else:
+ return settings.TEMPLATE_STRING_IF_INVALID
try:
- items = instance.navigation[self.key]
+ items = instance.navigation[key]
except:
return settings.TEMPLATE_STRING_IF_INVALID
raise template.TemplateSyntaxError(_('%s tag requires two arguments: a node and a navigation section name') % bits[0])
instance_var = parser.compile_filter(bits[1])
- key = bits[2]
-
- template_nodes = parser.parse(('recurse', 'endrecursenavigation',))
-
- token = parser.next_token()
- if token.contents == 'recurse':
- template_nodes.append(RecurseNavigationMarker())
- template_nodes.extend(parser.parse(('endrecursenavigation')))
- parser.delete_first_token()
+ key_var = parser.compile_filter(bits[2])
- return RecurseNavigationNode(template_nodes, instance_var, key)
+ template_nodes = parser.parse(('endrecursenavigation',))
+ token = parser.delete_first_token()
+ return RecurseNavigationNode(template_nodes, instance_var, key_var)
@register.filter
try:
return Navigation.objects.filter(node__in=node.get_ancestors(include_self=True), key=key).order_by('-node__level')[0].node
except:
- if settings.TEMPLATE_DEBUG:
- raise
return node
\ No newline at end of file
--- /dev/null
+from philo.contrib.sobol.search import *
\ No newline at end of file
--- /dev/null
+from django.conf import settings
+from django.conf.urls.defaults import patterns, url
+from django.contrib import admin
+from django.core.urlresolvers import reverse
+from django.db.models import Count
+from django.http import HttpResponseRedirect, Http404
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.utils.translation import ugettext_lazy as _
+from philo.admin import EntityAdmin
+from philo.contrib.sobol.models import Search, ResultURL, SearchView
+from functools import update_wrapper
+
+
+class ResultURLInline(admin.TabularInline):
+ model = ResultURL
+ readonly_fields = ('url',)
+ can_delete = False
+ extra = 0
+ max_num = 0
+
+
+class SearchAdmin(admin.ModelAdmin):
+ readonly_fields = ('string',)
+ inlines = [ResultURLInline]
+ list_display = ['string', 'unique_urls', 'total_clicks']
+ search_fields = ['string', 'result_urls__url']
+ actions = ['results_action']
+ if 'grappelli' in settings.INSTALLED_APPS:
+ results_template = 'admin/sobol/search/grappelli_results.html'
+ else:
+ results_template = 'admin/sobol/search/results.html'
+
+ def get_urls(self):
+ urlpatterns = super(SearchAdmin, self).get_urls()
+
+ def wrap(view):
+ def wrapper(*args, **kwargs):
+ return self.admin_site.admin_view(view)(*args, **kwargs)
+ return update_wrapper(wrapper, view)
+
+ info = self.model._meta.app_label, self.model._meta.module_name
+
+ urlpatterns = patterns('',
+ url(r'^results/$', wrap(self.results_view), name="%s_%s_selected_results" % info),
+ url(r'^(.+)/results/$', wrap(self.results_view), name="%s_%s_results" % info)
+ ) + urlpatterns
+ return urlpatterns
+
+ def unique_urls(self, obj):
+ return obj.unique_urls
+ unique_urls.admin_order_field = 'unique_urls'
+
+ def total_clicks(self, obj):
+ return obj.total_clicks
+ total_clicks.admin_order_field = 'total_clicks'
+
+ def queryset(self, request):
+ qs = super(SearchAdmin, self).queryset(request)
+ return qs.annotate(total_clicks=Count('result_urls__clicks', distinct=True), unique_urls=Count('result_urls', distinct=True))
+
+ def results_action(self, request, queryset):
+ info = self.model._meta.app_label, self.model._meta.module_name
+ if len(queryset) == 1:
+ return HttpResponseRedirect(reverse("admin:%s_%s_results" % info, args=(queryset[0].pk,)))
+ else:
+ url = reverse("admin:%s_%s_selected_results" % info)
+ return HttpResponseRedirect("%s?ids=%s" % (url, ','.join([str(item.pk) for item in queryset])))
+ results_action.short_description = "View results for selected %(verbose_name_plural)s"
+
+ def results_view(self, request, object_id=None, extra_context=None):
+ if object_id is not None:
+ object_ids = [object_id]
+ else:
+ object_ids = request.GET.get('ids').split(',')
+
+ if object_ids is None:
+ raise Http404
+
+ qs = self.queryset(request).filter(pk__in=object_ids)
+ opts = self.model._meta
+
+ if len(object_ids) == 1:
+ title = _(u"Search results for %s" % qs[0])
+ else:
+ title = _(u"Search results for multiple objects")
+
+ context = {
+ 'title': title,
+ 'queryset': qs,
+ 'opts': opts,
+ 'root_path': self.admin_site.root_path,
+ 'app_label': opts.app_label
+ }
+ return render_to_response(self.results_template, context, context_instance=RequestContext(request))
+
+
+class SearchViewAdmin(EntityAdmin):
+ raw_id_fields = ('results_page',)
+ related_lookup_fields = {'fk': raw_id_fields}
+
+
+admin.site.register(Search, SearchAdmin)
+admin.site.register(SearchView, SearchViewAdmin)
\ No newline at end of file
--- /dev/null
+from django import forms
+from philo.contrib.sobol.utils import SEARCH_ARG_GET_KEY
+
+
+class BaseSearchForm(forms.BaseForm):
+ base_fields = {
+ SEARCH_ARG_GET_KEY: forms.CharField()
+ }
+
+
+class SearchForm(forms.Form, BaseSearchForm):
+ pass
\ No newline at end of file
--- /dev/null
+from django.conf.urls.defaults import patterns, url
+from django.contrib import messages
+from django.core.exceptions import ValidationError
+from django.db import models
+from django.http import HttpResponseRedirect, Http404, HttpResponse
+from django.utils import simplejson as json
+from django.utils.datastructures import SortedDict
+from philo.contrib.sobol import registry
+from philo.contrib.sobol.forms import SearchForm
+from philo.contrib.sobol.utils import HASH_REDIRECT_GET_KEY, URL_REDIRECT_GET_KEY, SEARCH_ARG_GET_KEY, check_redirect_hash
+from philo.exceptions import ViewCanNotProvideSubpath
+from philo.models import MultiView, Page
+from philo.models.fields import SlugMultipleChoiceField
+from philo.validators import RedirectValidator
+import datetime
+try:
+ import eventlet
+except:
+ eventlet = False
+
+
+class Search(models.Model):
+ string = models.TextField()
+
+ def __unicode__(self):
+ return self.string
+
+ def get_weighted_results(self, threshhold=None):
+ "Returns this search's results ordered by decreasing weight."
+ if not hasattr(self, '_weighted_results'):
+ result_qs = self.result_urls.all()
+
+ if threshhold is not None:
+ result_qs = result_qs.filter(counts__datetime__gte=threshhold)
+
+ results = [result for result in result_qs]
+
+ results.sort(cmp=lambda x,y: cmp(y.weight, x.weight))
+
+ self._weighted_results = results
+
+ return self._weighted_results
+
+ def get_favored_results(self, error=5, threshhold=None):
+ """
+ Calculate the set of most-favored results. A higher error
+ will cause this method to be more reticent about adding new
+ items.
+
+ The thought is to see whether there are any results which
+ vastly outstrip the other options. As such, evenly-weighted
+ results should be grouped together and either added or
+ excluded as a group.
+ """
+ if not hasattr(self, '_favored_results'):
+ results = self.get_weighted_results(threshhold)
+
+ grouped_results = SortedDict()
+
+ for result in results:
+ grouped_results.setdefault(result.weight, []).append(result)
+
+ self._favored_results = []
+
+ for value, subresults in grouped_results.items():
+ cost = error * sum([(value - result.weight)**2 for result in self._favored_results])
+ if value > cost:
+ self._favored_results += subresults
+ else:
+ break
+ return self._favored_results
+
+ class Meta:
+ ordering = ['string']
+ verbose_name_plural = 'searches'
+
+
+class ResultURL(models.Model):
+ search = models.ForeignKey(Search, related_name='result_urls')
+ url = models.TextField(validators=[RedirectValidator()])
+
+ def __unicode__(self):
+ return self.url
+
+ def get_weight(self, threshhold=None):
+ if not hasattr(self, '_weight'):
+ clicks = self.clicks.all()
+
+ if threshhold is not None:
+ clicks = clicks.filter(datetime__gte=threshhold)
+
+ self._weight = sum([click.weight for click in clicks])
+
+ return self._weight
+ weight = property(get_weight)
+
+ class Meta:
+ ordering = ['url']
+
+
+class Click(models.Model):
+ result = models.ForeignKey(ResultURL, related_name='clicks')
+ datetime = models.DateTimeField()
+
+ def __unicode__(self):
+ return self.datetime.strftime('%B %d, %Y %H:%M:%S')
+
+ def get_weight(self, default=1, weighted=lambda value, days: value/days**2):
+ if not hasattr(self, '_weight'):
+ days = (datetime.datetime.now() - self.datetime).days
+ if days < 0:
+ raise ValueError("Click dates must be in the past.")
+ default = float(default)
+ if days == 0:
+ self._weight = float(default)
+ else:
+ self._weight = weighted(default, days)
+ return self._weight
+ weight = property(get_weight)
+
+ def clean(self):
+ if self.datetime > datetime.datetime.now():
+ raise ValidationError("Click dates must be in the past.")
+
+ class Meta:
+ ordering = ['datetime']
+ get_latest_by = 'datetime'
+
+
+class SearchView(MultiView):
+ results_page = models.ForeignKey(Page, related_name='search_results_related')
+ searches = SlugMultipleChoiceField(choices=registry.iterchoices())
+ enable_ajax_api = models.BooleanField("Enable AJAX API", default=True, help_text="Search results will be available <i>only</i> by AJAX, not as template variables.")
+ placeholder_text = models.CharField(max_length=75, default="Search")
+
+ search_form = SearchForm
+
+ def __unicode__(self):
+ return u"%s (%s)" % (self.placeholder_text, u", ".join([display for slug, display in registry.iterchoices() if slug in self.searches]))
+
+ def get_reverse_params(self, obj):
+ raise ViewCanNotProvideSubpath
+
+ @property
+ def urlpatterns(self):
+ urlpatterns = patterns('',
+ url(r'^$', self.results_view, name='results'),
+ )
+ if self.enable_ajax_api:
+ urlpatterns += patterns('',
+ url(r'^(?P<slug>[\w-]+)$', self.ajax_api_view, name='ajax_api_view')
+ )
+ return urlpatterns
+
+ def get_search_instance(self, slug, search_string):
+ return registry[slug](search_string.lower())
+
+ def results_view(self, request, extra_context=None):
+ results = None
+
+ context = self.get_context()
+ context.update(extra_context or {})
+
+ if SEARCH_ARG_GET_KEY in request.GET:
+ form = self.search_form(request.GET)
+
+ if form.is_valid():
+ search_string = request.GET[SEARCH_ARG_GET_KEY].lower()
+ url = request.GET.get(URL_REDIRECT_GET_KEY)
+ hash = request.GET.get(HASH_REDIRECT_GET_KEY)
+
+ if url and hash:
+ if check_redirect_hash(hash, search_string, url):
+ # Create the necessary models
+ search = Search.objects.get_or_create(string=search_string)[0]
+ result_url = search.result_urls.get_or_create(url=url)[0]
+ result_url.clicks.create(datetime=datetime.datetime.now())
+ return HttpResponseRedirect(url)
+ else:
+ messages.add_message(request, messages.INFO, "The link you followed had been tampered with. Here are all the results for your search term instead!")
+ # TODO: Should search_string be escaped here?
+ return HttpResponseRedirect("%s?%s=%s" % (request.path, SEARCH_ARG_GET_KEY, search_string))
+ if not self.enable_ajax_api:
+ search_instances = []
+ if eventlet:
+ pool = eventlet.GreenPool()
+ for slug in self.searches:
+ search_instance = self.get_search_instance(slug, search_string)
+ search_instances.append(search_instance)
+ if eventlet:
+ pool.spawn_n(self.make_result_cache, search_instance)
+ else:
+ self.make_result_cache(search_instance)
+ if eventlet:
+ pool.waitall()
+ context.update({
+ 'searches': search_instances
+ })
+ else:
+ context.update({
+ 'searches': [{'verbose_name': verbose_name, 'slug': slug, 'url': self.reverse('ajax_api_view', kwargs={'slug': slug}, node=request.node), 'result_template': registry[slug].result_template} for slug, verbose_name in registry.iterchoices() if slug in self.searches]
+ })
+ else:
+ form = SearchForm()
+
+ context.update({
+ 'form': form
+ })
+ return self.results_page.render_to_response(request, extra_context=context)
+
+ def make_result_cache(self, search_instance):
+ search_instance.results
+
+ def ajax_api_view(self, request, slug, extra_context=None):
+ search_string = request.GET.get(SEARCH_ARG_GET_KEY)
+
+ if not request.is_ajax() or not self.enable_ajax_api or slug not in self.searches or search_string is None:
+ raise Http404
+
+ search_instance = self.get_search_instance(slug, search_string)
+ response = HttpResponse(json.dumps({
+ 'results': [result.get_context() for result in search_instance.results],
+ }))
+ return response
\ No newline at end of file
--- /dev/null
+#encoding: utf-8
+
+from django.conf import settings
+from django.contrib.sites.models import Site
+from django.core.cache import cache
+from django.db.models.options import get_verbose_name as convert_camelcase
+from django.utils import simplejson as json
+from django.utils.http import urlquote_plus
+from django.utils.safestring import mark_safe
+from django.utils.text import capfirst
+from django.template import loader, Context, Template
+import datetime
+from philo.contrib.sobol.utils import make_tracking_querydict
+
+try:
+ from eventlet.green import urllib2
+except:
+ import urllib2
+
+
+__all__ = (
+ 'Result', 'BaseSearch', 'DatabaseSearch', 'URLSearch', 'JSONSearch', 'GoogleSearch', 'registry'
+)
+
+
+SEARCH_CACHE_KEY = 'philo_sobol_search_results'
+DEFAULT_RESULT_TEMPLATE_STRING = "{% if url %}<a href='{{ url }}'>{% endif %}{{ title }}{% if url %}</a>{% endif %}"
+DEFAULT_RESULT_TEMPLATE = Template(DEFAULT_RESULT_TEMPLATE_STRING)
+
+# Determines the timeout on the entire result cache.
+MAX_CACHE_TIMEOUT = 60*24*7
+
+
+class RegistrationError(Exception):
+ pass
+
+
+class SearchRegistry(object):
+ # Holds a registry of search types by slug.
+ def __init__(self):
+ self._registry = {}
+
+ def register(self, search, slug=None):
+ slug = slug or search.slug
+ if slug in self._registry:
+ registered = self._registry[slug]
+ if registered.__module__ != search.__module__:
+ raise RegistrationError("A different search is already registered as `%s`" % slug)
+ else:
+ self._registry[slug] = search
+
+ def unregister(self, search, slug=None):
+ if slug is not None:
+ if slug in self._registry and self._registry[slug] == search:
+ del self._registry[slug]
+ raise RegistrationError("`%s` is not registered as `%s`" % (search, slug))
+ else:
+ for slug, search in self._registry.items():
+ if search == search:
+ del self._registry[slug]
+
+ def items(self):
+ return self._registry.items()
+
+ def iteritems(self):
+ return self._registry.iteritems()
+
+ def iterchoices(self):
+ for slug, search in self.iteritems():
+ yield slug, search.verbose_name
+
+ def __getitem__(self, key):
+ return self._registry[key]
+
+ def __iter__(self):
+ return self._registry.__iter__()
+
+
+registry = SearchRegistry()
+
+
+class Result(object):
+ """
+ A result is instantiated with a configuration dictionary, a search,
+ and a template name. The configuration dictionary is expected to
+ define a `title` and optionally a `url`. Any other variables may be
+ defined; they will be made available through the result object in
+ the template, if one is defined.
+ """
+ def __init__(self, search, result):
+ self.search = search
+ self.result = result
+
+ def get_title(self):
+ return self.search.get_result_title(self.result)
+
+ def get_url(self):
+ qd = self.search.get_result_querydict(self.result)
+ if qd is None:
+ return ""
+ return "?%s" % qd.urlencode()
+
+ def get_template(self):
+ return self.search.get_result_template(self.result)
+
+ def get_extra_context(self):
+ return self.search.get_result_extra_context(self.result)
+
+ def get_context(self):
+ context = self.get_extra_context()
+ context.update({
+ 'title': self.get_title(),
+ 'url': self.get_url()
+ })
+ return context
+
+ def render(self):
+ t = self.get_template()
+ c = Context(self.get_context())
+ return t.render(c)
+
+ def __unicode__(self):
+ return self.render()
+
+
+class BaseSearchMetaclass(type):
+ def __new__(cls, name, bases, attrs):
+ if 'verbose_name' not in attrs:
+ attrs['verbose_name'] = capfirst(convert_camelcase(name))
+ if 'slug' not in attrs:
+ attrs['slug'] = name.lower()
+ return super(BaseSearchMetaclass, cls).__new__(cls, name, bases, attrs)
+
+
+class BaseSearch(object):
+ """
+ Defines a generic search interface. Accessing self.results will
+ attempt to retrieve cached results and, if that fails, will
+ initiate a new search and store the results in the cache.
+ """
+ __metaclass__ = BaseSearchMetaclass
+ result_limit = 10
+ _cache_timeout = 60*48
+
+ def __init__(self, search_arg):
+ self.search_arg = search_arg
+
+ def _get_cached_results(self):
+ """Return the cached results if the results haven't timed out. Otherwise return None."""
+ result_cache = cache.get(SEARCH_CACHE_KEY)
+ if result_cache and self.__class__ in result_cache and self.search_arg.lower() in result_cache[self.__class__]:
+ cached = result_cache[self.__class__][self.search_arg.lower()]
+ if cached['timeout'] >= datetime.datetime.now():
+ return cached['results']
+ return None
+
+ def _set_cached_results(self, results, timeout):
+ """Sets the results to the cache for <timeout> minutes."""
+ result_cache = cache.get(SEARCH_CACHE_KEY) or {}
+ cached = result_cache.setdefault(self.__class__, {}).setdefault(self.search_arg.lower(), {})
+ cached.update({
+ 'results': results,
+ 'timeout': datetime.datetime.now() + datetime.timedelta(minutes=timeout)
+ })
+ cache.set(SEARCH_CACHE_KEY, result_cache, MAX_CACHE_TIMEOUT)
+
+ @property
+ def results(self):
+ if not hasattr(self, '_results'):
+ results = self._get_cached_results()
+ if results is None:
+ try:
+ # Cache one extra result so we can see if there are
+ # more results to be had.
+ limit = self.result_limit
+ if limit is not None:
+ limit += 1
+ results = self.get_results(limit)
+ except:
+ if settings.DEBUG:
+ raise
+ # On exceptions, don't set any cache; just return.
+ return []
+
+ self._set_cached_results(results, self._cache_timeout)
+ self._results = results
+
+ return self._results
+
+ def get_results(self, limit=None, result_class=Result):
+ """
+ Calls self.search() and parses the return value into Result objects.
+ """
+ results = self.search(limit)
+ return [result_class(self, result) for result in results]
+
+ def search(self, limit=None):
+ """
+ Returns an iterable of up to <limit> results. The
+ get_result_title, get_result_url, get_result_template, and
+ get_result_extra_context methods will be used to interpret the
+ individual items that this function returns, so the result can
+ be an object with attributes as easily as a dictionary
+ with keys. The only restriction is that the objects be
+ pickleable so that they can be used with django's cache system.
+ """
+ raise NotImplementedError
+
+ def get_result_title(self, result):
+ raise NotImplementedError
+
+ def get_result_url(self, result):
+ "Subclasses override this to provide the actual URL for the result."
+ raise NotImplementedError
+
+ def get_result_querydict(self, result):
+ url = self.get_result_url(result)
+ if url is None:
+ return None
+ return make_tracking_querydict(self.search_arg, url)
+
+ def get_result_template(self, result):
+ if hasattr(self, 'result_template'):
+ return loader.get_template(self.result_template)
+ if not hasattr(self, '_result_template'):
+ self._result_template = DEFAULT_RESULT_TEMPLATE
+ return self._result_template
+
+ def get_result_extra_context(self, result):
+ return {}
+
+ def has_more_results(self):
+ """Useful to determine whether to display a `view more results` link."""
+ return len(self.results) > self.result_limit
+
+ @property
+ def more_results_url(self):
+ """
+ Returns the actual url for more results. This will be encoded
+ into a querystring for tracking purposes.
+ """
+ raise NotImplementedError
+
+ @property
+ def more_results_querydict(self):
+ return make_tracking_querydict(self.search_arg, self.more_results_url)
+
+ def __unicode__(self):
+ return ' '.join(self.__class__.verbose_name.rsplit(' ', 1)[:-1]) + ' results'
+
+
+class DatabaseSearch(BaseSearch):
+ model = None
+
+ def search(self, limit=None):
+ if not hasattr(self, '_qs'):
+ self._qs = self.get_queryset()
+ if limit is not None:
+ self._qs = self._qs[:limit]
+
+ return self._qs
+
+ def get_queryset(self):
+ return self.model._default_manager.all()
+
+
+class URLSearch(BaseSearch):
+ """
+ Defines a generic interface for searches that require accessing a
+ certain url to get search results.
+ """
+ search_url = ''
+ query_format_str = "%s"
+
+ @property
+ def url(self):
+ "The URL where the search gets its results."
+ return self.search_url + self.query_format_str % urlquote_plus(self.search_arg)
+
+ @property
+ def more_results_url(self):
+ "The URL where the users would go to get more results."
+ return self.url
+
+ def parse_response(self, response, limit=None):
+ raise NotImplementedError
+
+ def search(self, limit=None):
+ return self.parse_response(urllib2.urlopen(self.url), limit=limit)
+
+
+class JSONSearch(URLSearch):
+ """
+ Makes a GET request and parses the results as JSON. The default
+ behavior assumes that the return value is a list of results.
+ """
+ def parse_response(self, response, limit=None):
+ return json.loads(response.read())[:limit]
+
+
+class GoogleSearch(JSONSearch):
+ search_url = "http://ajax.googleapis.com/ajax/services/search/web"
+ # TODO: Change this template to reflect the app's actual name.
+ result_template = 'search/googlesearch.html'
+ _cache_timeout = 60
+ verbose_name = "Google search (current site)"
+
+ @property
+ def query_format_str(self):
+ default_args = self.default_args
+ if default_args:
+ default_args += " "
+ return "?v=1.0&q=%s%%s" % urlquote_plus(default_args).replace('%', '%%')
+
+ @property
+ def default_args(self):
+ return "site:%s" % Site.objects.get_current().domain
+
+ def parse_response(self, response, limit=None):
+ responseData = json.loads(response.read())['responseData']
+ results, cursor = responseData['results'], responseData['cursor']
+
+ if results:
+ self._more_results_url = cursor['moreResultsUrl']
+ self._estimated_result_count = cursor['estimatedResultCount']
+
+ return results[:limit]
+
+ @property
+ def url(self):
+ # Google requires that an ajax request have a proper Referer header.
+ return urllib2.Request(
+ super(GoogleSearch, self).url,
+ None,
+ {'Referer': "http://%s" % Site.objects.get_current().domain}
+ )
+
+ @property
+ def has_more_results(self):
+ if self.results and len(self.results) < self._estimated_result_count:
+ return True
+ return False
+
+ @property
+ def more_results_url(self):
+ return self._more_results_url
+
+ def get_result_title(self, result):
+ return result['titleNoFormatting']
+
+ def get_result_url(self, result):
+ return result['unescapedUrl']
+
+ def get_result_extra_context(self, result):
+ return result
+
+
+registry.register(GoogleSearch)
+
+
+try:
+ from BeautifulSoup import BeautifulSoup, SoupStrainer, BeautifulStoneSoup
+except:
+ pass
+else:
+ __all__ += ('ScrapeSearch', 'XMLSearch',)
+ class ScrapeSearch(URLSearch):
+ _strainer_args = []
+ _strainer_kwargs = {}
+
+ @property
+ def strainer(self):
+ if not hasattr(self, '_strainer'):
+ self._strainer = SoupStrainer(*self._strainer_args, **self._strainer_kwargs)
+ return self._strainer
+
+ def parse_response(self, response, limit=None):
+ strainer = self.strainer
+ soup = BeautifulSoup(response, parseOnlyThese=strainer)
+ return self.parse_results(soup.findAll(recursive=False, limit=limit))
+
+ def parse_results(self, results):
+ """
+ Provides a hook for parsing the results of straining. This
+ has no default behavior because the results absolutely
+ must be parsed to properly extract the information.
+ For more information, see http://www.crummy.com/software/BeautifulSoup/documentation.html#Improving%20Memory%20Usage%20with%20extract
+ """
+ raise NotImplementedError
+
+
+ class XMLSearch(ScrapeSearch):
+ _self_closing_tags = []
+
+ def parse_response(self, response, limit=None):
+ strainer = self.strainer
+ soup = BeautifulStoneSoup(response, selfClosingTags=self._self_closing_tags, parseOnlyThese=strainer)
+ return self.parse_results(soup.findAll(recursive=False, limit=limit))
\ No newline at end of file
--- /dev/null
+{% extends "admin/base_site.html" %}
+
+<!-- LOADING -->
+{% load i18n %}
+
+<!-- EXTRASTYLES -->
+{% block extrastyle %}<style type="text/css">.favored{font-weight:bold;}</style>{% endblock %}
+
+<!-- BREADCRUMBS -->
+{% block breadcrumbs %}
+ <div id="breadcrumbs">
+ {% if queryset|length > 1 %}
+ <a href="../../">{% trans "Home" %}</a> ›
+ <a href="../">{{ app_label|capfirst }}</a> ›
+ <a href="./">{{ opts.verbose_name_plural|capfirst }}</a> ›
+ {% trans 'Search results for multiple objects' %}
+ {% else %}
+ <a href="../../../../">{% trans "Home" %}</a> ›
+ <a href="../../../">{{ app_label|capfirst }}</a> ›
+ <a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> ›
+ <a href="../">{{ queryset|first|truncatewords:"18" }}</a> ›
+ {% trans 'Results' %}
+ {% endif %}
+ </div>
+{% endblock %}
+
+<!-- CONTENT -->
+{% block content %}
+ <div class="container-grid delete-confirmation">
+ {% for search in queryset %}
+ <div class="group tabular">
+ <h2>{{ search_string }}</h2>
+ <div class="module table">
+ <div class="module thead">
+ <div class="tr">
+ <div class="th">Weight</div>
+ <div class="th">URL</div>
+ </div>
+ </div>
+ <div class="module tbody">
+ {% for result in search.get_weighted_results %}
+ <div class="tr{% if result in search.get_favored_results %} favored{% endif %}">
+ <div class="td">{{ result.weight }}</div>
+ <div class="td">{{ result.url }}</div>
+ </div>
+ {% endfor %}
+ </div>
+ </div>
+ </div>
+ {% endfor %}
+ </div>
+{% endblock %}
\ No newline at end of file
--- /dev/null
+{% extends "admin/base_site.html" %}
+{% load i18n %}
+
+{% block extrastyle %}<style type="text/css">.favored{font-weight:bold;}</style>{% endblock %}
+
+{% block breadcrumbs %}
+<div class="breadcrumbs">
+ {% if queryset|length > 1 %}
+ <a href="../../">{% trans "Home" %}</a> ›
+ <a href="../">{{ app_label|capfirst }}</a> ›
+ <a href="./">{{ opts.verbose_name_plural|capfirst }}</a> ›
+ {% trans 'Search results for multiple objects' %}
+ {% else %}
+ <a href="../../../../">{% trans "Home" %}</a> ›
+ <a href="../../../">{{ app_label|capfirst }}</a> ›
+ <a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> ›
+ <a href="../">{{ queryset|first|truncatewords:"18" }}</a> ›
+ {% trans 'Results' %}
+ {% endif %}
+</div>
+{% endblock %}
+
+
+{% block content %}
+ {% for search in queryset %}
+ <fieldset class="module">
+ <h2>{{ search.string }}</h2>
+ <table>
+ <thead>
+ <tr>
+ <th>Weight</th>
+ <th>URL</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for result in search.get_weighted_results %}
+ <tr{% if result in search.favored_results %} class="favored"{% endif %}>
+ <td>{{ result.weight }}</td>
+ <td>{{ result.url }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </fieldset>
+ {% endfor %}
+{% endblock %}
\ No newline at end of file
--- /dev/null
+<article>
+ <h1><a href="{{ url }}">{{ title|safe }}</a></h1>
+ <p>{{ content|safe }}</p>
+</article>
\ No newline at end of file
--- /dev/null
+from django.conf import settings
+from django.http import QueryDict
+from django.utils.encoding import smart_str
+from django.utils.http import urlquote_plus, urlquote
+from hashlib import sha1
+
+
+SEARCH_ARG_GET_KEY = 'q'
+URL_REDIRECT_GET_KEY = 'url'
+HASH_REDIRECT_GET_KEY = 's'
+
+
+def make_redirect_hash(search_arg, url):
+ return sha1(smart_str(search_arg + url + settings.SECRET_KEY)).hexdigest()[::2]
+
+
+def check_redirect_hash(hash, search_arg, url):
+ return hash == make_redirect_hash(search_arg, url)
+
+
+def make_tracking_querydict(search_arg, url):
+ """
+ Returns a QueryDict instance containing the information necessary
+ for tracking clicks of this url.
+
+ NOTE: will this kind of initialization handle quoting correctly?
+ """
+ return QueryDict("%s=%s&%s=%s&%s=%s" % (
+ SEARCH_ARG_GET_KEY, urlquote_plus(search_arg),
+ URL_REDIRECT_GET_KEY, urlquote(url),
+ HASH_REDIRECT_GET_KEY, make_redirect_hash(search_arg, url))
+ )
\ No newline at end of file
from django.conf import settings
from django.utils.http import int_to_base36, base36_to_int
from django.contrib.auth.tokens import PasswordResetTokenGenerator
+from hashlib import sha1
REGISTRATION_TIMEOUT_DAYS = getattr(settings, 'WALDO_REGISTRATION_TIMEOUT_DAYS', 1)
# By hashing on the internal state of the user and using state that is
# sure to change, we produce a hash that will be invalid as soon as it
# is used.
- from django.utils.hashcompat import sha_constructor
- hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + unicode(user.is_active) + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + unicode(timestamp)).hexdigest()[::2]
+ hash = sha1(settings.SECRET_KEY + unicode(user.id) + unicode(user.is_active) + user.last_login.strftime('%Y-%m-%d %H:%M:%S') + unicode(timestamp)).hexdigest()[::2]
return '%s-%s' % (ts_b36, hash)
def _make_token_with_timestamp(self, user, email, timestamp):
ts_b36 = int_to_base36(timestamp)
- from django.utils.hashcompat import sha_constructor
- hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + user.email + email + unicode(timestamp)).hexdigest()[::2]
+ hash = sha1(settings.SECRET_KEY + unicode(user.id) + user.email + email + unicode(timestamp)).hexdigest()[::2]
return '%s-%s' % (ts_b36, hash)
-from django.forms.models import ModelFormMetaclass, ModelForm
+from django.forms.models import ModelFormMetaclass, ModelForm, ModelFormOptions
from django.utils.datastructures import SortedDict
from philo.utils import fattr
__all__ = ('EntityForm',)
-def proxy_fields_for_entity_model(entity_model, fields=None, exclude=None, widgets=None, formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
+def proxy_fields_for_entity_model(entity_model, fields=None, exclude=None, widgets=None, formfield_callback=None):
field_list = []
ignored = []
opts = entity_model._entity_meta
kwargs = {'widget': widgets[f.name]}
else:
kwargs = {}
- formfield = formfield_callback(f, **kwargs)
+
+ if formfield_callback is None:
+ formfield = f.formfield(**kwargs)
+ elif not callable(formfield_callback):
+ raise TypeError('formfield_callback must be a function or callable')
+ else:
+ formfield = formfield_callback(f, **kwargs)
+
if formfield:
field_list.append((f.name, formfield))
else:
return field_dict
-# BEGIN HACK - This will not be required after http://code.djangoproject.com/ticket/14082 has been resolved
-
-class EntityFormBase(ModelForm):
- pass
+# HACK until http://code.djangoproject.com/ticket/14082 is resolved.
+_old = ModelFormMetaclass.__new__
+def _new(cls, name, bases, attrs):
+ if cls == ModelFormMetaclass:
+ m = attrs.get('__metaclass__', None)
+ if m is None:
+ parents = [b for b in bases if issubclass(b, ModelForm)]
+ for c in parents:
+ if c.__metaclass__ != ModelFormMetaclass:
+ m = c.__metaclass__
+ break
+
+ if m is not None:
+ return m(name, bases, attrs)
+
+ return _old(cls, name, bases, attrs)
+ModelFormMetaclass.__new__ = staticmethod(_new)
+# END HACK
-_old_metaclass_new = ModelFormMetaclass.__new__
-def _new_metaclass_new(cls, name, bases, attrs):
- formfield_callback = attrs.get('formfield_callback', None)
- if formfield_callback is None:
- formfield_callback = lambda f, **kwargs: f.formfield(**kwargs)
- new_class = _old_metaclass_new(cls, name, bases, attrs)
- opts = new_class._meta
- if issubclass(new_class, EntityFormBase) and opts.model:
- # "override" proxy fields with declared fields by excluding them if there's a name conflict.
- exclude = (list(opts.exclude or []) + new_class.declared_fields.keys()) or None
- proxy_fields = proxy_fields_for_entity_model(opts.model, opts.fields, exclude, opts.widgets, formfield_callback) # don't pass in formfield_callback
+class EntityFormMetaclass(ModelFormMetaclass):
+ def __new__(cls, name, bases, attrs):
+ try:
+ parents = [b for b in bases if issubclass(b, EntityForm)]
+ except NameError:
+ # We are defining EntityForm itself
+ parents = None
+ sup = super(EntityFormMetaclass, cls)
+
+ if not parents:
+ # Then there's no business trying to use proxy fields.
+ return sup.__new__(cls, name, bases, attrs)
+
+ # Fake a declaration of all proxy fields so they'll be handled correctly.
+ opts = ModelFormOptions(attrs.get('Meta', None))
+
+ if opts.model:
+ formfield_callback = attrs.get('formfield_callback', None)
+ proxy_fields = proxy_fields_for_entity_model(opts.model, opts.fields, opts.exclude, opts.widgets, formfield_callback)
+ else:
+ proxy_fields = {}
+
+ new_attrs = proxy_fields.copy()
+ new_attrs.update(attrs)
+
+ new_class = sup.__new__(cls, name, bases, new_attrs)
new_class.proxy_fields = proxy_fields
- new_class.base_fields.update(proxy_fields)
- return new_class
+ return new_class
-ModelFormMetaclass.__new__ = staticmethod(_new_metaclass_new)
-# END HACK
-
-
-class EntityForm(EntityFormBase): # Would inherit from ModelForm directly if it weren't for the above HACK
+class EntityForm(ModelForm):
+ __metaclass__ = EntityFormMetaclass
+
def __init__(self, *args, **kwargs):
initial = kwargs.pop('initial', None)
instance = kwargs.get('instance', None)
node, subpath = Node.objects.get_with_path(path, root=getattr(current_site, 'root_node', None), absolute_result=False)
except Node.DoesNotExist:
node = None
-
- if node:
+ else:
if subpath is None:
subpath = ""
subpath = "/" + subpath
- if trailing_slash and subpath[-1] != "/":
- subpath += "/"
-
- node.subpath = subpath
+ if not node.handles_subpath(subpath):
+ node = None
+ else:
+ if trailing_slash and subpath[-1] != "/":
+ subpath += "/"
+
+ node.subpath = subpath
request._found_node = node
request.__class__.node = LazyNode()
def process_view(self, request, view_func, view_args, view_kwargs):
- request._cached_node_path = view_kwargs.get('path', '/')
+ try:
+ request._cached_node_path = view_kwargs['path']
+ except KeyError:
+ pass
def process_exception(self, request, exception):
if settings.DEBUG or not hasattr(request, 'node') or not request.node:
abstract = True
+#: An instance of :class:`ContentTypeRegistryLimiter` which is used to track the content types which can be related to by ForeignKeyValues and ManyToManyValues.
value_content_type_limiter = ContentTypeRegistryLimiter()
def register_value_model(model):
+ """Registers a model as a valid content type for a :class:`ForeignKeyValue` or :class:`ManyToManyValue` through the :data:`value_content_type_limiter`."""
value_content_type_limiter.register_class(model)
def unregister_value_model(model):
+ """Registers a model as a valid content type for a :class:`ForeignKeyValue` or :class:`ManyToManyValue` through the :data:`value_content_type_limiter`."""
value_content_type_limiter.unregister_class(model)
class AttributeValue(models.Model):
+ """
+ This is an abstract base class for models that can be used as values for :class:`Attribute`\ s.
+
+ AttributeValue subclasses are expected to supply access to a clean version of their value through an attribute called "value".
+
+ """
+
+ #: :class:`GenericRelation` to :class:`Attribute`
attribute_set = generic.GenericRelation('Attribute', content_type_field='value_content_type', object_id_field='value_object_id')
def set_value(self, value):
+ """Given a ``value``, sets the appropriate fields so that it can be correctly stored in the database."""
raise NotImplementedError
def value_formfields(self, **kwargs):
- """Define any formfields that would be used to construct an instance of this value."""
+ """
+ Returns any formfields that would be used to construct an instance of this value.
+
+ :returns: A dictionary mapping field names to formfields.
+
+ """
+
raise NotImplementedError
def construct_instance(self, **kwargs):
- """Apply cleaned data from the formfields generated by valid_formfields to oneself."""
+ """Applies cleaned data from the formfields generated by valid_formfields to oneself."""
raise NotImplementedError
def __unicode__(self):
abstract = True
+#: An instance of :class:`ContentTypeSubclassLimiter` which is used to track the content types which are considered valid value models for an :class:`Attribute`.
attribute_value_limiter = ContentTypeSubclassLimiter(AttributeValue)
class JSONValue(AttributeValue):
+ """Stores a python object as a json string."""
value = JSONField(verbose_name='Value (JSON)', help_text='This value must be valid JSON.', default='null', db_index=True)
def __unicode__(self):
class ForeignKeyValue(AttributeValue):
+ """Stores a generic relationship to an instance of any value content type (as defined by the :data:`value_content_type_limiter`)."""
content_type = models.ForeignKey(ContentType, limit_choices_to=value_content_type_limiter, verbose_name='Value type', null=True, blank=True)
object_id = models.PositiveIntegerField(verbose_name='Value ID', null=True, blank=True, db_index=True)
value = generic.GenericForeignKey()
class ManyToManyValue(AttributeValue):
+ """Stores a generic relationship to many instances of any value content type (as defined by the :data:`value_content_type_limiter`)."""
content_type = models.ForeignKey(ContentType, limit_choices_to=value_content_type_limiter, verbose_name='Value type', null=True, blank=True)
values = models.ManyToManyField(ForeignKeyValue, blank=True, null=True)
class Attribute(models.Model):
+ """Represents an arbitrary key/value pair on an arbitrary :class:`Model` where the key consists of word characters and the value is a subclass of :class:`AttributeValue`."""
entity_content_type = models.ForeignKey(ContentType, related_name='attribute_entity_set', verbose_name='Entity type')
entity_object_id = models.PositiveIntegerField(verbose_name='Entity ID', db_index=True)
+
+ #: :class:`GenericForeignKey` to anything (generally an instance of an Entity subclass).
entity = generic.GenericForeignKey('entity_content_type', 'entity_object_id')
value_content_type = models.ForeignKey(ContentType, related_name='attribute_value_set', limit_choices_to=attribute_value_limiter, verbose_name='Value type', null=True, blank=True)
value_object_id = models.PositiveIntegerField(verbose_name='Value ID', null=True, blank=True, db_index=True)
+
+ #: :class:`GenericForeignKey` to an instance of a subclass of :class:`AttributeValue` as determined by the :data:`attribute_value_limiter`.
value = generic.GenericForeignKey('value_content_type', 'value_object_id')
+ #: :class:`CharField` containing a key (up to 255 characters) consisting of alphanumeric characters and underscores.
key = models.CharField(max_length=255, validators=[RegexValidator("\w+")], help_text="Must contain one or more alphanumeric characters or underscores.", db_index=True)
def __unicode__(self):
class EntityBase(models.base.ModelBase):
def __new__(cls, name, bases, attrs):
+ entity_meta = attrs.pop('EntityMeta', None)
new = super(EntityBase, cls).__new__(cls, name, bases, attrs)
- entity_options = attrs.pop('EntityMeta', None)
- setattr(new, '_entity_meta', EntityOptions(entity_options))
+ new.add_to_class('_entity_meta', EntityOptions(entity_meta))
entity_class_prepared.send(sender=new)
return new
class Entity(models.Model):
+ """An abstract class that simplifies access to related attributes. Most models provided by Philo subclass Entity."""
__metaclass__ = EntityBase
attribute_set = generic.GenericRelation(Attribute, content_type_field='entity_content_type', object_id_field='entity_object_id')
@property
def attributes(self):
+ """
+ Property that returns a dictionary-like object which can be used to retrieve related :class:`Attribute`\ s' values directly.
+
+ Example::
+
+ >>> attr = entity.attribute_set.get(key='spam')
+ >>> attr.value.value
+ u'eggs'
+ >>> entity.attributes['spam']
+ u'eggs'
+
+ """
+
return QuerySetMapper(self.attribute_set.all())
class Meta:
def get_with_path(self, path, root=None, absolute_result=True, pathsep='/', field='slug'):
"""
- Returns the object with the path, unless absolute_result is set to False, in which
- case it returns a tuple containing the deepest object found along the path, and the
- remainder of the path after that object as a string (or None if there is no remaining
- path). Raises a DoesNotExist exception if no object is found with the given path.
-
- If the path you're searching for is known to exist, it is always faster to use
- absolute_result=True - unless the path depth is over ~40, in which case the high cost
- of the absolute query makes a binary search (i.e. non-absolute) faster.
+ If ``absolute_result`` is ``True``, returns the object at ``path`` (starting at ``root``) or raises a :exception:`DoesNotExist` exception. Otherwise, returns a tuple containing the deepest object found along ``path`` (or ``root`` if no deeper object is found) and the remainder of the path after that object as a string (or None if there is no remaining path).
+
+ .. note:: If you are looking for something with an exact path, it is faster to use absolute_result=True, unless the path depth is over ~40, in which case the high cost of the absolute query may make a binary search (i.e. non-absolute) faster.
+
+ .. note:: SQLite allows max of 64 tables in one join. That means the binary search will only work on paths with a max depth of 127 and the absolute fetch will only work to a max depth of (surprise!) 63. Larger depths could be handled, but since the common use case will not have a tree structure that deep, they are not.
+
+ :param path: The path of the object
+ :param root: The object which will be considered the root of the search
+ :param absolute_result: Whether to return an absolute result or do a binary search
+ :param pathsep: The path separator used in ``path``
+ :param field: The field on the model which should be queried for ``path`` segment matching.
+ :returns: An instance if absolute_result is True or (instance, remaining_path) otherwise.
+
"""
- # Note: SQLite allows max of 64 tables in one join. That means the binary search will
- # only work on paths with a max depth of 127 and the absolute fetch will only work
- # to a max depth of (surprise!) 63. Although this could be handled, chances are your
- # tree structure won't be that deep.
+
segments = path.split(pathsep)
# Clean out blank segments. Handles multiple consecutive pathseps.
slug = models.SlugField(max_length=255)
def get_path(self, root=None, pathsep='/', field='slug'):
+ """
+ :param root: Only return the path since this object.
+ :param pathsep: The path separator to use when constructing an instance's path
+ :param field: The field to pull path information from for each ancestor.
+ :returns: A string representation of an object's path.
+
+ """
+
if root == self:
return ''
class TreeEntity(Entity, TreeModel):
+ """An abstract subclass of Entity which represents a tree relationship."""
+
__metaclass__ = TreeEntityBase
@property
def attributes(self):
+ """
+ Property that returns a dictionary-like object which can be used to retrieve related :class:`Attribute`\ s' values directly. If an attribute with a given key is not related to the :class:`Entity`, then the object will check the parent's attributes.
+
+ Example::
+
+ >>> attr = entity.attribute_set.get(key='spam')
+ DoesNotExist: Attribute matching query does not exist.
+ >>> attr = entity.parent.attribute_set.get(key='spam')
+ >>> attr.value.value
+ u'eggs'
+ >>> entity.attributes['spam']
+ u'eggs'
+
+ """
+
if self.parent:
return QuerySetMapper(self.attribute_set.all(), passthrough=self.parent.attributes)
return super(TreeEntity, self).attributes
--- /dev/null
+from django import forms
+from django.core.exceptions import ValidationError
+from django.core.validators import validate_slug
+from django.db import models
+from django.utils import simplejson as json
+from django.utils.text import capfirst
+from django.utils.translation import ugettext_lazy as _
+from philo.forms.fields import JSONFormField
+from philo.validators import TemplateValidator, json_validator
+#from philo.models.fields.entities import *
+
+
+class TemplateField(models.TextField):
+ def __init__(self, allow=None, disallow=None, secure=True, *args, **kwargs):
+ super(TemplateField, self).__init__(*args, **kwargs)
+ self.validators.append(TemplateValidator(allow, disallow, secure))
+
+
+class JSONDescriptor(object):
+ def __init__(self, field):
+ self.field = field
+
+ def __get__(self, instance, owner):
+ if instance is None:
+ raise AttributeError # ?
+
+ if self.field.name not in instance.__dict__:
+ json_string = getattr(instance, self.field.attname)
+ instance.__dict__[self.field.name] = json.loads(json_string)
+
+ return instance.__dict__[self.field.name]
+
+ def __set__(self, instance, value):
+ instance.__dict__[self.field.name] = value
+ setattr(instance, self.field.attname, json.dumps(value))
+
+ def __delete__(self, instance):
+ del(instance.__dict__[self.field.name])
+ setattr(instance, self.field.attname, json.dumps(None))
+
+
+class JSONField(models.TextField):
+ default_validators = [json_validator]
+
+ def get_attname(self):
+ return "%s_json" % self.name
+
+ def contribute_to_class(self, cls, name):
+ super(JSONField, self).contribute_to_class(cls, name)
+ setattr(cls, name, JSONDescriptor(self))
+ models.signals.pre_init.connect(self.fix_init_kwarg, sender=cls)
+
+ def fix_init_kwarg(self, sender, args, kwargs, **signal_kwargs):
+ # Anything passed in as self.name is assumed to come from a serializer and
+ # will be treated as a json string.
+ if self.name in kwargs:
+ value = kwargs.pop(self.name)
+
+ # Hack to handle the xml serializer's handling of "null"
+ if value is None:
+ value = 'null'
+
+ kwargs[self.attname] = value
+
+ def formfield(self, *args, **kwargs):
+ kwargs["form_class"] = JSONFormField
+ return super(JSONField, self).formfield(*args, **kwargs)
+
+
+class SlugMultipleChoiceField(models.Field):
+ __metaclass__ = models.SubfieldBase
+ description = _("Comma-separated slug field")
+
+ def get_internal_type(self):
+ return "TextField"
+
+ def to_python(self, value):
+ if not value:
+ return []
+
+ if isinstance(value, list):
+ return value
+
+ return value.split(',')
+
+ def get_prep_value(self, value):
+ return ','.join(value)
+
+ def formfield(self, **kwargs):
+ # This is necessary because django hard-codes TypedChoiceField for things with choices.
+ defaults = {
+ 'widget': forms.CheckboxSelectMultiple,
+ 'choices': self.get_choices(include_blank=False),
+ 'label': capfirst(self.verbose_name),
+ 'required': not self.blank,
+ 'help_text': self.help_text
+ }
+ if self.has_default():
+ if callable(self.default):
+ defaults['initial'] = self.default
+ defaults['show_hidden_initial'] = True
+ else:
+ defaults['initial'] = self.get_default()
+
+ for k in kwargs.keys():
+ if k not in ('coerce', 'empty_value', 'choices', 'required',
+ 'widget', 'label', 'initial', 'help_text',
+ 'error_messages', 'show_hidden_initial'):
+ del kwargs[k]
+
+ defaults.update(kwargs)
+ form_class = forms.TypedMultipleChoiceField
+ return form_class(**defaults)
+
+ def validate(self, value, model_instance):
+ invalid_values = []
+ for val in value:
+ try:
+ validate_slug(val)
+ except ValidationError:
+ invalid_values.append(val)
+
+ if invalid_values:
+ # should really make a custom message.
+ raise ValidationError(self.error_messages['invalid_choice'] % invalid_values)
+
+
+try:
+ from south.modelsinspector import add_introspection_rules
+except ImportError:
+ pass
+else:
+ add_introspection_rules([], ["^philo\.models\.fields\.SlugMultipleChoiceField"])
+ add_introspection_rules([], ["^philo\.models\.fields\.TemplateField"])
+ add_introspection_rules([], ["^philo\.models\.fields\.JSONField"])
\ No newline at end of file
class LazyContainerFinder(object):
- def __init__(self, nodes):
+ def __init__(self, nodes, extends=False):
self.nodes = nodes
self.initialized = False
self.contentlet_specs = set()
self.contentreference_specs = SortedDict()
self.blocks = {}
self.block_super = False
+ self.extends = extends
def process(self, nodelist):
for node in nodelist:
+ if self.extends:
+ if isinstance(node, BlockNode):
+ self.blocks[node.name] = block = LazyContainerFinder(node.nodelist)
+ block.initialize()
+ self.blocks.update(block.blocks)
+ continue
+
if isinstance(node, ContainerNode):
if not node.references:
self.contentlet_specs.add(node.name)
self.contentreference_specs[node.name] = node.references
continue
- if isinstance(node, BlockNode):
- self.blocks[node.name] = block = LazyContainerFinder(node.nodelist)
- block.initialize()
- self.blocks.update(block.blocks)
- continue
-
- if isinstance(node, ExtendsNode):
- continue
-
if isinstance(node, VariableNode):
if node.filter_expression.var.lookups == (u'block', u'super'):
self.block_super = True
if extends:
if extends.nodelist:
- nodelists.append(LazyContainerFinder(extends.nodelist))
+ nodelists.append(LazyContainerFinder(extends.nodelist, extends=True))
loaded_template = getattr(extends, LOADED_TEMPLATE_ATTR)
nodelists.extend(build_extension_tree(loaded_template.nodelist))
else:
return contentlet_specs, contentreference_specs
def __unicode__(self):
- return self.get_path(pathsep=u' › ', field='name')
+ return self.name
class Meta:
app_label = 'philo'
return self.title
def clean_fields(self, exclude=None):
+ if exclude is None:
+ exclude = []
+
try:
super(Page, self).clean_fields(exclude)
except ValidationError, e:
-{% load i18n adminmedia %}
+{% load i18n adminmedia grp_tags %}
<!-- group -->
<div class="group tabular{% if inline_admin_formset.opts.classes %} {{ inline_admin_formset.opts.classes|join:" " }}{% endif %}"
<script type="text/javascript">
(function($) {
- $(document).ready(function($) {
-
- $("#{{ inline_admin_formset.formset.prefix }}-group").grp_inline({
- prefix: "{{ inline_admin_formset.formset.prefix }}",
- onBeforeAdded: function(inline) {},
- onAfterAdded: function(form) {
- grappelli.reinitDateTimeFields(form);
- grappelli.updateSelectFilter(form);
- form.find("input.vForeignKeyRawIdAdminField").grp_related_fk({lookup_url:"{% url grp_related_lookup %}"});
- form.find("input.vManyToManyRawIdAdminField").grp_related_m2m({lookup_url:"{% url grp_m2m_lookup %}"});
- form.find("input[name*='object_id'][name$='id']").grp_related_generic({lookup_url:"{% url grp_related_lookup %}"});
- },
- });
-
- {% if inline_admin_formset.opts.sortable_field_name %}
- $("#{{ inline_admin_formset.formset.prefix }}-group > div.table").sortable({
- handle: "a.drag-handler",
- items: "div.dynamic-form",
- axis: "y",
- appendTo: 'body',
- forceHelperSize: true,
- containment: '#{{ inline_admin_formset.formset.prefix }}-group > div.table',
- tolerance: 'pointer',
- });
- $("#{{ opts.module_name }}_form").bind("submit", function(){
- var sortable_field_name = "{{ inline_admin_formset.opts.sortable_field_name }}";
- var i = 0;
- $("#{{ inline_admin_formset.formset.prefix }}-group").find("div.dynamic-form").each(function(){
- var fields = $(this).find("div.td :input[value]");
- if (fields.serialize()) {
- $(this).find("input[name$='"+sortable_field_name+"']").val(i);
- i++;
- }
- });
- });
- {% endif %}
-
- });
+ $(document).ready(function($) {
+
+ var prefix = "{{ inline_admin_formset.formset.prefix }}";
+ var related_lookup_fields_fk = {% get_related_lookup_fields_fk inline_admin_formset.opts %};
+ var related_lookup_fields_m2m = {% get_related_lookup_fields_m2m inline_admin_formset.opts %};
+ var related_lookup_fields_generic = {% get_related_lookup_fields_generic inline_admin_formset.opts %};
+ $.each(related_lookup_fields_fk, function() {
+ $("#{{ inline_admin_formset.formset.prefix }}-group > div.table")
+ .find("input[name^='" + prefix + "'][name$='" + this + "']")
+ .grp_related_fk({lookup_url:"{% url grp_related_lookup %}"});
+ });
+ $.each(related_lookup_fields_m2m, function() {
+ $("#{{ inline_admin_formset.formset.prefix }}-group > div.table")
+ .find("input[name^='" + prefix + "'][name$='" + this + "']")
+ .grp_related_m2m({lookup_url:"{% url grp_m2m_lookup %}"});
+ });
+ $.each(related_lookup_fields_generic, function() {
+ var content_type = this[0],
+ object_id = this[1];
+ $("#{{ inline_admin_formset.formset.prefix }}-group > div.table")
+ .find("input[name^='" + prefix + "'][name$='" + this[1] + "']")
+ .each(function() {
+ var i = $(this).attr("id").match(/-\d+-/);
+ if (i) {
+ var ct_id = "#id_" + prefix + i[0] + content_type,
+ obj_id = "#id_" + prefix + i[0] + object_id;
+ $(this).grp_related_generic({content_type:ct_id, object_id:obj_id, lookup_url:"{% url grp_related_lookup %}"});
+ }
+ });
+ });
+
+ $("#{{ inline_admin_formset.formset.prefix }}-group").grp_inline({
+ prefix: "{{ inline_admin_formset.formset.prefix }}",
+ onBeforeAdded: function(inline) {},
+ onAfterAdded: function(form) {
+ grappelli.reinitDateTimeFields(form);
+ grappelli.updateSelectFilter(form);
+ $.each(related_lookup_fields_fk, function() {
+ form.find("input[name^='" + prefix + "'][name$='" + this + "']")
+ .grp_related_fk({lookup_url:"{% url grp_related_lookup %}"});
+ });
+ $.each(related_lookup_fields_m2m, function() {
+ form.find("input[name^='" + prefix + "'][name$='" + this + "']")
+ .grp_related_m2m({lookup_url:"{% url grp_m2m_lookup %}"});
+ });
+ $.each(related_lookup_fields_generic, function() {
+ var content_type = this[0],
+ object_id = this[1];
+ form.find("input[name^='" + prefix + "'][name$='" + this[1] + "']")
+ .each(function() {
+ var i = $(this).attr("id").match(/-\d+-/);
+ if (i) {
+ var ct_id = "#id_" + prefix + i[0] + content_type,
+ obj_id = "#id_" + prefix + i[0] + object_id;
+ $(this).grp_related_generic({content_type:ct_id, object_id:obj_id, lookup_url:"{% url grp_related_lookup %}"});
+ }
+ });
+ });
+ },
+ });
+
+ {% if inline_admin_formset.opts.sortable_field_name %}
+ $("#{{ inline_admin_formset.formset.prefix }}-group > div.table").sortable({
+ handle: "a.drag-handler",
+ items: "div.dynamic-form",
+ axis: "y",
+ appendTo: 'body',
+ forceHelperSize: true,
+ containment: '#{{ inline_admin_formset.formset.prefix }}-group > div.table',
+ tolerance: 'pointer',
+ });
+ $("#{{ opts.module_name }}_form").bind("submit", function(){
+ var sortable_field_name = "{{ inline_admin_formset.opts.sortable_field_name }}";
+ var i = 0;
+ $("#{{ inline_admin_formset.formset.prefix }}-group").find("div.dynamic-form").each(function(){
+ var fields = $(this).find("div.td :input[value]");
+ if (fields.serialize()) {
+ $(this).find("input[name$='"+sortable_field_name+"']").val(i);
+ i++;
+ }
+ });
+ });
+ {% endif %}
+
+ });
})(django.jQuery);
</script>
{% endfor %}{% endspaceless %}
{% endfor %}
{% for form in inline_admin_formset.formset.forms %}
- <div class="row cells-{{ form.fields.keys|length }}{% if not form.fields.keys|length_is:"2" %} cells{% endif %}{% if form.errors %} errors{% endif %} {% for field in form %}{{ field.field.name }} {% endfor %}{% comment %} {% if forloop.last %} empty-form{% endif %}{% endcomment %}">
+ <div class="row cells-{{ form.fields|length }} cells{% if form.errors %} errors{% endif %}{% for field in form %} {{ field.field.name }}{% endfor %}">
{{ form.non_field_errors }}
- <div{% if not form.fields.keys|length_is:"2" %} class="cell"{% endif %}>
- <div class="column span-4"><label class='required' for="{{ form.content.auto_id }}{{ form.content_id.auto_id }}">{{ form.verbose_name|capfirst }}:</label></div>
+ <div>
{% for field in form %}
{% if not field.is_hidden %}
+ {% comment %}This will be true for one field: the content/content reference{% endcomment %}
+ <div class="column span-4"><label class='required' for="{{ form.content.auto_id }}{{ form.content_id.auto_id }}">{{ form.verbose_name|capfirst }}:</label></div>
<div class="column span-flexible">
{{ field }}
{{ field.errors }}
--- /dev/null
+{% extends "admin/change_form.html" %}
+{% load i18n %}
+
+{% block form_top %}
+ {% if not is_popup %}
+ <p>{% trans "First, choose a template. After saving, you'll be able to provide additional content for containers." %}</p>
+ {% else %}
+ <p>{% trans "Choose a template" %}</p>
+ {% endif %}
+{% endblock %}
+
+{% block after_field_sets %}
+<script type="text/javascript">document.getElementById("id_name").focus();</script>
+{% endblock %}
\ No newline at end of file
-from django.test import TestCase
+import sys
+import traceback
+
from django import template
from django.conf import settings
from django.db import connection
from django.template import loader
from django.template.loaders import cached
+from django.test import TestCase
+from django.test.utils import setup_test_template_loader
+
+from philo.contrib.penfield.models import Blog, BlogView, BlogEntry
from philo.exceptions import AncestorDoesNotExist
from philo.models import Node, Page, Template
-from philo.contrib.penfield.models import Blog, BlogView, BlogEntry
-import sys, traceback
class TemplateTestCase(TestCase):
"Tests to make sure that embed behaves with complex includes and extends"
template_tests = self.get_template_tests()
- # Register our custom template loader. Shamelessly cribbed from django core regressiontests.
- def test_template_loader(template_name, template_dirs=None):
- "A custom template loader that loads the unit-test templates."
- try:
- return (template_tests[template_name][0] , "test:%s" % template_name)
- except KeyError:
- raise template.TemplateDoesNotExist, template_name
-
- cache_loader = cached.Loader(('test_template_loader',))
- cache_loader._cached_loaders = (test_template_loader,)
+ # Register our custom template loader. Shamelessly cribbed from django/tests/regressiontests/templates/tests.py:384.
+ cache_loader = setup_test_template_loader(
+ dict([(name, t[0]) for name, t in template_tests.iteritems()]),
+ use_cached_loader=True,
+ )
- old_template_loaders = loader.template_source_loaders
- loader.template_source_loaders = [cache_loader]
+ failures = []
+ tests = template_tests.items()
+ tests.sort()
# Turn TEMPLATE_DEBUG off, because tests assume that.
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
old_invalid = settings.TEMPLATE_STRING_IF_INVALID
expected_invalid_str = 'INVALID'
- failures = []
- tests = template_tests.items()
- tests.sort()
# Run tests
for name, vals in tests:
xx, context, result = vals
urlpatterns = patterns('',
- url(r'^$', node_view, name='philo-root'),
+ url(r'^$', node_view, kwargs={'path': '/'}, name='philo-root'),
url(r'^(?P<path>.*)$', node_view, name='philo-node-by-path')
)
from django.core.exceptions import ValidationError
from django.template import Template, Parser, Lexer, TOKEN_BLOCK, TOKEN_VAR, TemplateSyntaxError
from django.utils import simplejson as json
+from django.utils.html import escape, mark_safe
import re
from philo.utils import LOADED_TEMPLATE_ATTR
raise ValidationError('Tag "%s" is not permitted here.' % command)
+def linebreak_iter(template_source):
+ # Cribbed from django/views/debug.py:18
+ yield 0
+ p = template_source.find('\n')
+ while p >= 0:
+ yield p+1
+ p = template_source.find('\n', p+1)
+ yield len(template_source) + 1
+
+
class TemplateValidator(object):
def __init__(self, allow=None, disallow=None, secure=True):
self.allow = allow
except ValidationError:
raise
except Exception, e:
+ if hasattr(e, 'source') and isinstance(e, TemplateSyntaxError):
+ origin, (start, end) = e.source
+ template_source = origin.reload()
+ upto = 0
+ for num, next in enumerate(linebreak_iter(template_source)):
+ if start >= upto and end <= next:
+ raise ValidationError(mark_safe("Template code invalid: \"%s\" (%s:%d).<br />%s" % (escape(template_source[start:end]), origin.loadname, num, e)))
+ upto = next
raise ValidationError("Template code invalid. Error was: %s: %s" % (e.__class__.__name__, e))
def validate_template(self, template_string):
subpath = request.node.subpath
# Explicitly disallow trailing slashes if we are otherwise at a node's url.
- if request.path and request.path != "/" and request.path[-1] == "/" and subpath == "/":
+ if request._cached_node_path != "/" and request._cached_node_path[-1] == "/" and subpath == "/":
return HttpResponseRedirect(node.get_absolute_url())
if not node.handles_subpath(subpath):
--- /dev/null
+#!/usr/bin/env python
+
+from distutils.core import setup
+import os
+
+
+# Shamelessly cribbed from django's setup.py file.
+def fullsplit(path, result=None):
+ """
+ Split a pathname into components (the opposite of os.path.join) in a
+ platform-neutral way.
+ """
+ if result is None:
+ result = []
+ head, tail = os.path.split(path)
+ if head == '':
+ return [tail] + result
+ if head == path:
+ return result
+ return fullsplit(head, [tail] + result)
+
+# Compile the list of packages available, because distutils doesn't have
+# an easy way to do this. Shamelessly cribbed from django's setup.py file.
+packages, data_files = [], []
+root_dir = os.path.dirname(__file__)
+if root_dir != '':
+ os.chdir(root_dir)
+philo_dir = 'philo'
+
+for dirpath, dirnames, filenames in os.walk(philo_dir):
+ # Ignore dirnames that start with '.'
+ for i, dirname in enumerate(dirnames):
+ if dirname.startswith('.'): del dirnames[i]
+ if '__init__.py' in filenames:
+ packages.append('.'.join(fullsplit(dirpath)))
+ elif filenames:
+ data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]])
+
+
+version = __import__('philo').VERSION
+
+setup(
+ name = 'Philo',
+ version = '%s.%s' % (version[0], version[1]),
+ packages = packages,
+ data_files = data_files,
+)
\ No newline at end of file
+++ /dev/null
-{% extends "admin/change_form.html" %}
-{% load i18n %}
-
-{% block extrahead %}{{ block.super }}
-<!-- This will break if anything ever changes and may not work in all browsers. Sad face. -->
-<script type='text/javascript'>
-(function($){
- $(function(){
- $('#page_form input[type=submit]').click(function(e){
- if (e.target.name == '_addanother') {
- hidden = document.getElementById('page_form')._continue[0]
- hidden.parentNode.removeChild(hidden)
- }
- })
- })
-}(django.jQuery));
-</script>
-{% endblock %}
-
-{% block form_top %}
- <p>{% trans "First, choose a template. After saving, you'll be able to provide additional content for containers." %}</p>
- <input type="hidden" name="_continue" value="1" />
-{% endblock %}
-
-{% block content %}
-{% with 0 as save_on_top %}
-{{ block.super }}
-{% endwith %}
-{% endblock %}
\ No newline at end of file