diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php index 924f2f8f8..0c46c17f2 100644 --- a/modules/backend/ServiceProvider.php +++ b/modules/backend/ServiceProvider.php @@ -27,35 +27,35 @@ class ServiceProvider extends ModuleServiceProvider WidgetManager::instance()->registerFormWidgets(function ($manager) { $manager->registerFormWidget('Backend\FormWidgets\CodeEditor', [ 'label' => 'Code editor', - 'alias' => 'codeeditor' + 'code' => 'codeeditor' ]); $manager->registerFormWidget('Backend\FormWidgets\RichEditor', [ 'label' => 'Rich editor', - 'alias' => 'richeditor' + 'code' => 'richeditor' ]); $manager->registerFormWidget('Backend\FormWidgets\FileUpload', [ 'label' => 'File uploader', - 'alias' => 'fileupload' + 'code' => 'fileupload' ]); $manager->registerFormWidget('Backend\FormWidgets\Relation', [ 'label' => 'Relationship', - 'alias' => 'relation' + 'code' => 'relation' ]); $manager->registerFormWidget('Backend\FormWidgets\DatePicker', [ 'label' => 'Date picker', - 'alias' => 'datepicker' + 'code' => 'datepicker' ]); $manager->registerFormWidget('Backend\FormWidgets\ColorPicker', [ 'label' => 'Color picker', - 'alias' => 'colorpicker' + 'code' => 'colorpicker' ]); $manager->registerFormWidget('Backend\FormWidgets\DataGrid', [ 'label' => 'Data Grid', - 'alias' => 'datagrid' + 'code' => 'datagrid' ]); $manager->registerFormWidget('Backend\FormWidgets\RecordFinder', [ 'label' => 'Record Finder', - 'alias' => 'recordfinder' + 'code' => 'recordfinder' ]); }); diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 897296b49..7b3266f31 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -3872,6 +3872,8 @@ a .icon-flip-vertical:before { .icon-check:before { content: "\f00c"; } +.icon-remove:before, +.icon-close:before, .icon-times:before { content: "\f00d"; } @@ -4201,7 +4203,8 @@ a .icon-flip-vertical:before { .icon-arrows-h:before { content: "\f07e"; } -.icon-bar-chart-o:before { +.icon-bar-chart-o:before, +.icon-bar-chart:before { content: "\f080"; } .icon-twitter-square:before { @@ -5030,7 +5033,6 @@ a .icon-flip-vertical:before { .icon-digg:before { content: "\f1a6"; } -.icon-pied-piper-square:before, .icon-pied-piper:before { content: "\f1a7"; } @@ -5147,6 +5149,7 @@ a .icon-flip-vertical:before { content: "\f1cc"; } .icon-life-bouy:before, +.icon-life-buoy:before, .icon-life-saver:before, .icon-support:before, .icon-life-ring:before { @@ -5214,6 +5217,129 @@ a .icon-flip-vertical:before { .icon-bomb:before { content: "\f1e2"; } +.icon-soccer-ball-o:before, +.icon-futbol-o:before { + content: "\f1e3"; +} +.icon-tty:before { + content: "\f1e4"; +} +.icon-binoculars:before { + content: "\f1e5"; +} +.icon-plug:before { + content: "\f1e6"; +} +.icon-slideshare:before { + content: "\f1e7"; +} +.icon-twitch:before { + content: "\f1e8"; +} +.icon-yelp:before { + content: "\f1e9"; +} +.icon-newspaper-o:before { + content: "\f1ea"; +} +.icon-wifi:before { + content: "\f1eb"; +} +.icon-calculator:before { + content: "\f1ec"; +} +.icon-paypal:before { + content: "\f1ed"; +} +.icon-google-wallet:before { + content: "\f1ee"; +} +.icon-cc-visa:before { + content: "\f1f0"; +} +.icon-cc-mastercard:before { + content: "\f1f1"; +} +.icon-cc-discover:before { + content: "\f1f2"; +} +.icon-cc-amex:before { + content: "\f1f3"; +} +.icon-cc-paypal:before { + content: "\f1f4"; +} +.icon-cc-stripe:before { + content: "\f1f5"; +} +.icon-bell-slash:before { + content: "\f1f6"; +} +.icon-bell-slash-o:before { + content: "\f1f7"; +} +.icon-trash:before { + content: "\f1f8"; +} +.icon-copyright:before { + content: "\f1f9"; +} +.icon-at:before { + content: "\f1fa"; +} +.icon-eyedropper:before { + content: "\f1fb"; +} +.icon-paint-brush:before { + content: "\f1fc"; +} +.icon-birthday-cake:before { + content: "\f1fd"; +} +.icon-area-chart:before { + content: "\f1fe"; +} +.icon-pie-chart:before { + content: "\f200"; +} +.icon-line-chart:before { + content: "\f201"; +} +.icon-lastfm:before { + content: "\f202"; +} +.icon-lastfm-square:before { + content: "\f203"; +} +.icon-toggle-off:before { + content: "\f204"; +} +.icon-toggle-on:before { + content: "\f205"; +} +.icon-bicycle:before { + content: "\f206"; +} +.icon-bus:before { + content: "\f207"; +} +.icon-ioxhost:before { + content: "\f208"; +} +.icon-angellist:before { + content: "\f209"; +} +.icon-cc:before { + content: "\f20a"; +} +.icon-shekel:before, +.icon-sheqel:before, +.icon-ils:before { + content: "\f20b"; +} +.icon-meanpath:before { + content: "\f20c"; +} [class^="oc-icon-"]:before, [class*=" oc-icon-"]:before { display: inline-block; @@ -5269,6 +5395,8 @@ a .icon-flip-vertical:before { .oc-icon-check:before { content: "\f00c"; } +.oc-icon-remove:before, +.oc-icon-close:before, .oc-icon-times:before { content: "\f00d"; } @@ -5598,7 +5726,8 @@ a .icon-flip-vertical:before { .oc-icon-arrows-h:before { content: "\f07e"; } -.oc-icon-bar-chart-o:before { +.oc-icon-bar-chart-o:before, +.oc-icon-bar-chart:before { content: "\f080"; } .oc-icon-twitter-square:before { @@ -6427,7 +6556,6 @@ a .icon-flip-vertical:before { .oc-icon-digg:before { content: "\f1a6"; } -.oc-icon-pied-piper-square:before, .oc-icon-pied-piper:before { content: "\f1a7"; } @@ -6544,6 +6672,7 @@ a .icon-flip-vertical:before { content: "\f1cc"; } .oc-icon-life-bouy:before, +.oc-icon-life-buoy:before, .oc-icon-life-saver:before, .oc-icon-support:before, .oc-icon-life-ring:before { @@ -6611,6 +6740,129 @@ a .icon-flip-vertical:before { .oc-icon-bomb:before { content: "\f1e2"; } +.oc-icon-soccer-ball-o:before, +.oc-icon-futbol-o:before { + content: "\f1e3"; +} +.oc-icon-tty:before { + content: "\f1e4"; +} +.oc-icon-binoculars:before { + content: "\f1e5"; +} +.oc-icon-plug:before { + content: "\f1e6"; +} +.oc-icon-slideshare:before { + content: "\f1e7"; +} +.oc-icon-twitch:before { + content: "\f1e8"; +} +.oc-icon-yelp:before { + content: "\f1e9"; +} +.oc-icon-newspaper-o:before { + content: "\f1ea"; +} +.oc-icon-wifi:before { + content: "\f1eb"; +} +.oc-icon-calculator:before { + content: "\f1ec"; +} +.oc-icon-paypal:before { + content: "\f1ed"; +} +.oc-icon-google-wallet:before { + content: "\f1ee"; +} +.oc-icon-cc-visa:before { + content: "\f1f0"; +} +.oc-icon-cc-mastercard:before { + content: "\f1f1"; +} +.oc-icon-cc-discover:before { + content: "\f1f2"; +} +.oc-icon-cc-amex:before { + content: "\f1f3"; +} +.oc-icon-cc-paypal:before { + content: "\f1f4"; +} +.oc-icon-cc-stripe:before { + content: "\f1f5"; +} +.oc-icon-bell-slash:before { + content: "\f1f6"; +} +.oc-icon-bell-slash-o:before { + content: "\f1f7"; +} +.oc-icon-trash:before { + content: "\f1f8"; +} +.oc-icon-copyright:before { + content: "\f1f9"; +} +.oc-icon-at:before { + content: "\f1fa"; +} +.oc-icon-eyedropper:before { + content: "\f1fb"; +} +.oc-icon-paint-brush:before { + content: "\f1fc"; +} +.oc-icon-birthday-cake:before { + content: "\f1fd"; +} +.oc-icon-area-chart:before { + content: "\f1fe"; +} +.oc-icon-pie-chart:before { + content: "\f200"; +} +.oc-icon-line-chart:before { + content: "\f201"; +} +.oc-icon-lastfm:before { + content: "\f202"; +} +.oc-icon-lastfm-square:before { + content: "\f203"; +} +.oc-icon-toggle-off:before { + content: "\f204"; +} +.oc-icon-toggle-on:before { + content: "\f205"; +} +.oc-icon-bicycle:before { + content: "\f206"; +} +.oc-icon-bus:before { + content: "\f207"; +} +.oc-icon-ioxhost:before { + content: "\f208"; +} +.oc-icon-angellist:before { + content: "\f209"; +} +.oc-icon-cc:before { + content: "\f20a"; +} +.oc-icon-shekel:before, +.oc-icon-sheqel:before, +.oc-icon-ils:before { + content: "\f20b"; +} +.oc-icon-meanpath:before { + content: "\f20c"; +} [class^="flag-"], [class*=" flag-"] { background-image: url("../images/flag-icons-small.png"); @@ -10857,35 +11109,39 @@ html.cssanimations .cursor-loading-indicator.hide { } .control-filelist.hero ul li { background: #ffffff; - border-bottom: 1px solid #ecf0f1; + border-bottom: none; } -.control-filelist.hero ul li a { +.control-filelist.hero ul li > a { padding: 16px 45px 15px 50px; font-size: 13px; + border-bottom: 1px solid #ecf0f1; } -.control-filelist.hero ul li a span.title { +.control-filelist.hero ul li > a span.title { font-size: 13px; font-weight: 600; color: #2b3e50; } -.control-filelist.hero ul li a:hover { +.control-filelist.hero ul li > a:hover { background: #58b6f7; + border-bottom: 1px solid #58b6f7 !important; } -.control-filelist.hero ul li a:hover span.title, -.control-filelist.hero ul li a:hover span.description { +.control-filelist.hero ul li > a:hover span.title, +.control-filelist.hero ul li > a:hover span.description { color: #ffffff !important; } .control-filelist.hero ul li .checkbox { top: 17px; right: 17px; } -.control-filelist.hero ul li.active a:after { +.control-filelist.hero ul li.active > a { + border-bottom: 1px solid #dddddd; +} +.control-filelist.hero ul li.active > a:after { top: -1px; bottom: -1px; height: auto; } -.control-filelist.hero ul li.active a > span.borders:before, -.control-filelist.hero ul li.active a > span.borders:after { +.control-filelist.hero ul li.active > a > span.borders:before { content: ' '; position: absolute; width: 100%; @@ -10894,11 +11150,19 @@ html.cssanimations .cursor-loading-indicator.hide { left: 0; background-color: #dddddd; } -.control-filelist.hero ul li.active a > span.borders:before { +.control-filelist.hero ul li.active > a > span.borders:before { top: -1px; } -.control-filelist.hero ul li.active a > span.borders:after { - bottom: -1px; +.control-filelist.hero ul li.active > a:hover > span.borders:before { + background-color: #58b6f7; +} +.control-filelist.hero ul li > h4 { + padding-top: 7px; + padding-bottom: 6px; + border-bottom: 1px solid #ecf0f1; +} +.control-filelist.hero ul > li.group > ul > li > a { + padding-left: 66px; } .touch .control-filelist li:not(.active) a:hover { background: transparent; @@ -11449,8 +11713,6 @@ body.dropdown-open .dropdown-overlay { color: #cccccc; background: #f9f9f9; font-weight: 400; - max-width: 150px; - text-overflow: ellipsis; overflow: hidden; } .control-tabs > ul.nav-tabs > li a:hover, @@ -11464,6 +11726,16 @@ body.dropdown-open .dropdown-overlay { .control-tabs > div > div > ul.nav-tabs > li a:before { font-size: 14px; } +.control-tabs > ul.nav-tabs > li a > span.title > span, +.control-tabs > div > ul.nav-tabs > li a > span.title > span, +.control-tabs > div > div > ul.nav-tabs > li a > span.title > span { + max-width: 150px; + height: 16px; + margin-bottom: -4px; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; +} .control-tabs > ul.nav-tabs > li span.tab-close, .control-tabs > div > ul.nav-tabs > li span.tab-close, .control-tabs > div > div > ul.nav-tabs > li span.tab-close { @@ -12880,6 +13152,99 @@ div.popover-overlay { -o-transform: scale(1, 1); transform: scale(1, 1); } +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs { + background: #f9f9f9; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li { + margin-left: -19px; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li:first-child, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li:first-child { + margin-left: 0; + padding-left: 8px; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a { + padding: 8px 16px 0 16px; + font-weight: 400; + color: #2b3e50; + opacity: 0.6; + filter: alpha(opacity=60); +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title { + position: relative; + display: inline-block; + padding: 4px 5px 9px 5px; + font-size: 13px; + z-index: 100; + height: 25px!important; + background-color: transparent; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:before, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:before, +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:after, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:after { + content: ' '; + position: absolute; + background: transparent url(../images/secondary-tab-shape-content.svg) no-repeat left top; + width: 15px; + height: 25px; + top: 0; + z-index: 100; + display: none; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:before, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:before { + left: -15px; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:after, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title:after { + right: -15px; + background-position: -60px 0; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title span, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li a > span.title span { + height: 18px; + font-size: 12px; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a { + opacity: 1; + filter: alpha(opacity=100); +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a > span.title, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a > span.title { + background-color: white; +} +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a > span.title:before, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a > span.title:before, +.fancy-layout .control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a > span.title:after, +.fancy-layout.control-tabs.secondary.content-tabs > div > ul.nav-tabs > li.active a > span.title:after { + display: block; +} +.fancy-layout .control-tabs.secondary.content-tabs .tab-collapse-icon.primary, +.fancy-layout.control-tabs.secondary.content-tabs .tab-collapse-icon.primary { + color: #808c8d; +} +.fancy-layout .control-tabs.secondary.content-tabs.primary-collapsed .tab-collapse-icon.primary, +.fancy-layout.control-tabs.secondary.content-tabs.primary-collapsed .tab-collapse-icon.primary { + color: white; +} +.fancy-layout .control-tabs.secondary.content-tabs.primary-collapsed > div > ul.nav-tabs, +.fancy-layout.control-tabs.secondary.content-tabs.primary-collapsed > div > ul.nav-tabs { + background: #e67e22; +} +.fancy-layout .control-tabs.secondary.content-tabs.primary-collapsed > div > ul.nav-tabs > li a, +.fancy-layout.control-tabs.secondary.content-tabs.primary-collapsed > div > ul.nav-tabs > li a { + color: white; +} +.fancy-layout .control-tabs.secondary.content-tabs.primary-collapsed > div > ul.nav-tabs > li.active a, +.fancy-layout.control-tabs.secondary.content-tabs.primary-collapsed > div > ul.nav-tabs > li.active a { + color: #2b3e50; +} .fancy-layout .control-tabs.primary > div > ul.nav-tabs, .fancy-layout.control-tabs.primary > div > ul.nav-tabs { background: #7f8c8d; @@ -13153,6 +13518,12 @@ div.popover-overlay { border-top-right-radius: 0; border-top-left-radius: 0; } +.fancy-layout .content-tabs .field-richeditor .redactor-box .redactor-toolbar { + margin: 20px 20px 0 20px!important; + -webkit-border-radius: 3px !important; + -moz-border-radius: 3px !important; + border-radius: 3px !important; +} body.side-panel-not-fixed .fancy-layout .field-richeditor { border-left: none; } diff --git a/modules/backend/assets/images/secondary-tab-shape-content.svg b/modules/backend/assets/images/secondary-tab-shape-content.svg new file mode 100644 index 000000000..164511a94 --- /dev/null +++ b/modules/backend/assets/images/secondary-tab-shape-content.svg @@ -0,0 +1,16 @@ + + + +]> + + + + + + + + diff --git a/modules/backend/assets/js/october.filter.js b/modules/backend/assets/js/october.filter.js deleted file mode 100644 index d0de10262..000000000 --- a/modules/backend/assets/js/october.filter.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Filter Behavior - * - * Data attributes: - * - data-behavior="filter" - enables the filter plugin - * - * JavaScript API: - * $('a#someLink').filterBehavior() - * - * Dependences: - * - October Popover (october.popover.js) - */ - diff --git a/modules/backend/assets/js/october.tab.js b/modules/backend/assets/js/october.tab.js index 2420f74c1..6c9a8bebe 100644 --- a/modules/backend/assets/js/october.tab.js +++ b/modules/backend/assets/js/october.tab.js @@ -142,7 +142,7 @@ var html = $a.html() $a.html('') - $a.append($('').html(html)) + $a.append($('').append($('').html(html))) var pane = $('> .tab-pane', this.$pagesContainer).eq(tabIndex).attr('id', targetId) $(li).append($('×').click(function(){ @@ -150,6 +150,8 @@ return false })) + pane.data('tab', li) + this.$el.trigger('initTab.oc.tab', [{'pane': pane, 'tab': li}]) } diff --git a/modules/backend/assets/less/controls/fancylayout.less b/modules/backend/assets/less/controls/fancylayout.less index f0223a242..e8fc91eb0 100644 --- a/modules/backend/assets/less/controls/fancylayout.less +++ b/modules/backend/assets/less/controls/fancylayout.less @@ -214,6 +214,98 @@ .scaleAxes(1, 1); } } + + &.content-tabs { + > div > ul.nav-tabs { + background: @color-body-bg; + + > li { + margin-left: -19px; + + &:first-child { + margin-left: 0; + padding-left: 8px; + } + + a { + padding: 8px 16px 0 16px; + font-weight: 400; + color: #2b3e50; + .opacity(0.6); + + > span.title { + position: relative; + display: inline-block; + padding: 4px 5px 9px 5px; + font-size: 13px; + z-index: 100; + height: 25px!important; + background-color: transparent; + + &:before, &:after { + content: ' '; + position: absolute; + background: transparent url(../images/secondary-tab-shape-content.svg) no-repeat left top; + width: 15px; + height: 25px; + top: 0; + z-index: 100; + display: none; + } + + &:before { + left: -15px; + } + + &:after { + right: -15px; + background-position: -60px 0; + } + + span { + height: 18px; + font-size: 12px; + } + } + } + + &.active a { + .opacity(1); + + > span.title { + background-color: white; + &:before, &:after { + display: block; + } + } + } + } + } + + .tab-collapse-icon.primary { + color: #808c8d; + } + + &.primary-collapsed { + .tab-collapse-icon.primary { + color: white; + } + + > div > ul.nav-tabs { + background: @color-fancy-form-tabless-fields-bg; + + > li { + a { + color: white; + } + + &.active a { + color: #2b3e50; + } + } + } + } + } } &.primary { @@ -459,6 +551,13 @@ .border-top-radius(0); } } + + .content-tabs .field-richeditor { + .redactor-box .redactor-toolbar { + margin: 20px 20px 0 20px!important; + .border-radius(3px)!important; + } + } } body.side-panel-not-fixed { diff --git a/modules/backend/assets/less/controls/filelist.less b/modules/backend/assets/less/controls/filelist.less index a73255bb1..697a1a442 100644 --- a/modules/backend/assets/less/controls/filelist.less +++ b/modules/backend/assets/less/controls/filelist.less @@ -3,9 +3,7 @@ // -------------------------------------------------- .control-filelist { - .listPaddings (@level) when (@level > 0) { - @offset-base: 27px; - + .listPaddings (@level, @offset-base) when (@level > 0) { > li.group { > ul { > li > a { @@ -13,11 +11,11 @@ margin-left: -1*@level*@offset-base; } - .listPaddings(@level - 1); + .listPaddings(@level - 1, @offset-base); } } } - .listPaddings (0) {} + .listPaddings (0, 27px) {} p.no-data { padding: 18px 0; @@ -139,7 +137,7 @@ padding-left: 20px; } - .listPaddings(10); + .listPaddings(10, 27px); } &[data-status=collapsed] { @@ -173,11 +171,12 @@ ul { li { background: @color-filelist-hero-item-bg; - border-bottom: 1px solid @color-panel-light; + border-bottom: none; - a { + > a { padding: 16px 45px 15px 50px; font-size: 13px; + border-bottom: 1px solid @color-panel-light; span.title { font-size: 13px; @@ -187,6 +186,7 @@ &:hover { background: @color-filelist-hero-hover-bg; + border-bottom: 1px solid @color-filelist-hero-hover-bg!important; span.title, span.description { color: @color-filelist-hero-hover-text!important; } @@ -199,7 +199,9 @@ } &.active { - a { + > a { + border-bottom: 1px solid @color-list-active; + &:after { top: -1px; bottom: -1px; @@ -207,7 +209,7 @@ } > span.borders { - &:before, &:after { + &:before { content: ' '; position: absolute; width: 100%; @@ -217,12 +219,26 @@ background-color: @color-list-active; } - &:before { top: -1px; } - &:after { bottom: -1px; } + &:before {top: -1px;} } + &:hover > span.borders:before { + background-color: @color-filelist-hero-hover-bg; + } } } + + > h4 { + padding-top: 7px; + padding-bottom: 6px; + border-bottom: 1px solid @color-panel-light; + } + } + + > li.group { + > ul > li > a { + padding-left: 66px; + } } } } diff --git a/modules/backend/assets/less/controls/lists.less b/modules/backend/assets/less/controls/lists.less index 5c0e9db14..20f61199c 100644 --- a/modules/backend/assets/less/controls/lists.less +++ b/modules/backend/assets/less/controls/lists.less @@ -9,8 +9,8 @@ // // //
-// -// +// +// //
// // Title @@ -26,7 +26,8 @@ // // //
-// +// +// //
// // Welcome to October diff --git a/modules/backend/assets/less/controls/tab.less b/modules/backend/assets/less/controls/tab.less index 8a2684f34..b3a85e520 100644 --- a/modules/backend/assets/less/controls/tab.less +++ b/modules/backend/assets/less/controls/tab.less @@ -47,8 +47,6 @@ background: @color-body-bg; font-weight: 400; - max-width: 150px; - text-overflow: ellipsis; overflow: hidden; &:hover { @@ -59,6 +57,15 @@ &:before { font-size: 14px; } + + > span.title > span { + max-width: 150px; + height: 16px; + margin-bottom: -4px; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + } } span.tab-close { diff --git a/modules/backend/assets/less/core/icons.less b/modules/backend/assets/less/core/icons.less index 66e970a21..4e542aba5 100644 --- a/modules/backend/assets/less/core/icons.less +++ b/modules/backend/assets/less/core/icons.less @@ -22,6 +22,8 @@ .oc-icon-th:before { content: @th; } .oc-icon-th-list:before { content: @th-list; } .oc-icon-check:before { content: @check; } +.oc-icon-remove:before, +.oc-icon-close:before, .oc-icon-times:before { content: @times; } .oc-icon-search-plus:before { content: @search-plus; } .oc-icon-search-minus:before { content: @search-minus; } @@ -137,7 +139,8 @@ .oc-icon-folder-open:before { content: @folder-open; } .oc-icon-arrows-v:before { content: @arrows-v; } .oc-icon-arrows-h:before { content: @arrows-h; } -.oc-icon-bar-chart-o:before { content: @bar-chart-o; } +.oc-icon-bar-chart-o:before, +.oc-icon-bar-chart:before { content: @bar-chart; } .oc-icon-twitter-square:before { content: @twitter-square; } .oc-icon-facebook-square:before { content: @facebook-square; } .oc-icon-camera-retro:before { content: @camera-retro; } @@ -440,7 +443,6 @@ .oc-icon-stumbleupon:before { content: @stumbleupon; } .oc-icon-delicious:before { content: @delicious; } .oc-icon-digg:before { content: @digg; } -.oc-icon-pied-piper-square:before, .oc-icon-pied-piper:before { content: @pied-piper; } .oc-icon-pied-piper-alt:before { content: @pied-piper-alt; } .oc-icon-drupal:before { content: @drupal; } @@ -485,6 +487,7 @@ .oc-icon-codepen:before { content: @codepen; } .oc-icon-jsfiddle:before { content: @jsfiddle; } .oc-icon-life-bouy:before, +.oc-icon-life-buoy:before, .oc-icon-life-saver:before, .oc-icon-support:before, .oc-icon-life-ring:before { content: @life-ring; } @@ -512,3 +515,46 @@ .oc-icon-share-alt:before { content: @share-alt; } .oc-icon-share-alt-square:before { content: @share-alt-square; } .oc-icon-bomb:before { content: @bomb; } +.oc-icon-soccer-ball-o:before, +.oc-icon-futbol-o:before { content: @futbol-o; } +.oc-icon-tty:before { content: @tty; } +.oc-icon-binoculars:before { content: @binoculars; } +.oc-icon-plug:before { content: @plug; } +.oc-icon-slideshare:before { content: @slideshare; } +.oc-icon-twitch:before { content: @twitch; } +.oc-icon-yelp:before { content: @yelp; } +.oc-icon-newspaper-o:before { content: @newspaper-o; } +.oc-icon-wifi:before { content: @wifi; } +.oc-icon-calculator:before { content: @calculator; } +.oc-icon-paypal:before { content: @paypal; } +.oc-icon-google-wallet:before { content: @google-wallet; } +.oc-icon-cc-visa:before { content: @cc-visa; } +.oc-icon-cc-mastercard:before { content: @cc-mastercard; } +.oc-icon-cc-discover:before { content: @cc-discover; } +.oc-icon-cc-amex:before { content: @cc-amex; } +.oc-icon-cc-paypal:before { content: @cc-paypal; } +.oc-icon-cc-stripe:before { content: @cc-stripe; } +.oc-icon-bell-slash:before { content: @bell-slash; } +.oc-icon-bell-slash-o:before { content: @bell-slash-o; } +.oc-icon-trash:before { content: @trash; } +.oc-icon-copyright:before { content: @copyright; } +.oc-icon-at:before { content: @at; } +.oc-icon-eyedropper:before { content: @eyedropper; } +.oc-icon-paint-brush:before { content: @paint-brush; } +.oc-icon-birthday-cake:before { content: @birthday-cake; } +.oc-icon-area-chart:before { content: @area-chart; } +.oc-icon-pie-chart:before { content: @pie-chart; } +.oc-icon-line-chart:before { content: @line-chart; } +.oc-icon-lastfm:before { content: @lastfm; } +.oc-icon-lastfm-square:before { content: @lastfm-square; } +.oc-icon-toggle-off:before { content: @toggle-off; } +.oc-icon-toggle-on:before { content: @toggle-on; } +.oc-icon-bicycle:before { content: @bicycle; } +.oc-icon-bus:before { content: @bus; } +.oc-icon-ioxhost:before { content: @ioxhost; } +.oc-icon-angellist:before { content: @angellist; } +.oc-icon-cc:before { content: @cc; } +.oc-icon-shekel:before, +.oc-icon-sheqel:before, +.oc-icon-ils:before { content: @ils; } +.oc-icon-meanpath:before { content: @meanpath; } diff --git a/modules/backend/behaviors/RelationController.php b/modules/backend/behaviors/RelationController.php index 15a768a27..7bb0e8d09 100644 --- a/modules/backend/behaviors/RelationController.php +++ b/modules/backend/behaviors/RelationController.php @@ -438,7 +438,7 @@ class RelationController extends ControllerBehavior */ protected function findExistingRelationIds($checkIds = null) { - $foreignKeyName = $this->relationModel->getKeyName(); + $foreignKeyName = $this->relationModel->getQualifiedKeyName(); $results = $this->relationObject ->getBaseQuery() diff --git a/modules/backend/classes/Controller.php b/modules/backend/classes/Controller.php index 97e189d1b..9ece22a09 100644 --- a/modules/backend/classes/Controller.php +++ b/modules/backend/classes/Controller.php @@ -304,8 +304,9 @@ class Controller extends Extendable } // No page title - if (!$this->pageTitle) + if (!$this->pageTitle) { $this->pageTitle = 'backend::lang.page.untitled'; + } // Load the view if (!$this->suppressView && is_null($result)) { diff --git a/modules/backend/classes/WidgetManager.php b/modules/backend/classes/WidgetManager.php index c7f65a4d2..b46cc3623 100644 --- a/modules/backend/classes/WidgetManager.php +++ b/modules/backend/classes/WidgetManager.php @@ -32,7 +32,7 @@ class WidgetManager /** * @var array An array of report widgets. */ - protected $formWidgetAliases; + protected $formWidgetHints; /** * @var array An array of report widgets. @@ -44,21 +44,6 @@ class WidgetManager */ protected $reportWidgetCallbacks = []; - /** - * @var array An array where keys are aliases and values are class names. - */ - protected $aliasMap; - - /** - * @var array An array where keys are class names and values are aliases. - */ - protected $classMap; - - /** - * @var array A cached array of widget details. - */ - protected $detailsCache; - /** * @var System\Classes\PluginManager */ @@ -142,18 +127,24 @@ class WidgetManager /** * Registers a single form form widget. * @param string $className Widget class name. - * @param array $widgetInfo Registration information, can contain an 'alias' key. + * @param array $widgetInfo Registration information, can contain an 'code' key. * @return void */ public function registerFormWidget($className, $widgetInfo = null) { - $widgetAlias = isset($widgetInfo['alias']) ? $widgetInfo['alias'] : null; - if (!$widgetAlias) { - $widgetAlias = Str::getClassId($className); + $widgetCode = isset($widgetInfo['code']) ? $widgetInfo['code'] : null; + + /* @todo Remove line if year >= 2015 */ + if (!$widgetCode) { + $widgetCode = isset($widgetInfo['alias']) ? $widgetInfo['alias'] : null; + } + + if (!$widgetCode) { + $widgetCode = Str::getClassId($className); } $this->formWidgets[$className] = $widgetInfo; - $this->formWidgetAliases[$widgetAlias] = $className; + $this->formWidgetHints[$widgetCode] = $className; } /** @@ -161,8 +152,10 @@ class WidgetManager * Usage: *
      *   WidgetManager::registerFormWidgets(function($manager){
-     *       $manager->registerFormWidget('Backend\FormWidgets\CodeEditor', 'codeeditor');
-     *       $manager->registerFormWidget('Backend\FormWidgets\RichEditor', 'richeditor');
+     *       $manager->registerFormWidget('Backend\FormWidgets\CodeEditor', [
+     *           'name' => 'Code editor',
+     *           'code'  => 'codeeditor'
+     *       ]);
      *   });
      * 
*/ @@ -172,9 +165,9 @@ class WidgetManager } /** - * Returns a class name from a form widget alias - * Normalizes a class name or converts an alias to it's class name. - * @param string $name Class name or form widget alias. + * Returns a class name from a form widget code + * Normalizes a class name or converts an code to it's class name. + * @param string $name Class name or form widget code. * @return string The class name resolved, or the original name. */ public function resolveFormWidget($name) @@ -183,10 +176,10 @@ class WidgetManager $this->listFormWidgets(); } - $aliases = $this->formWidgetAliases; + $hints = $this->formWidgetHints; - if (isset($aliases[$name])) { - return $aliases[$name]; + if (isset($hints[$name])) { + return $hints[$name]; } $_name = Str::normalizeClassName($name); diff --git a/modules/backend/formwidgets/CodeEditor.php b/modules/backend/formwidgets/CodeEditor.php index a12a9ad71..605f3d2b5 100644 --- a/modules/backend/formwidgets/CodeEditor.php +++ b/modules/backend/formwidgets/CodeEditor.php @@ -88,7 +88,7 @@ class CodeEditor extends FormWidgetBase } /** - * Prepares the list data + * Prepares the widget data */ public function prepareVars() { diff --git a/modules/backend/formwidgets/Datepicker.php b/modules/backend/formwidgets/DatePicker.php similarity index 100% rename from modules/backend/formwidgets/Datepicker.php rename to modules/backend/formwidgets/DatePicker.php diff --git a/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js b/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js index bf5073c9e..78ee0615a 100644 --- a/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js +++ b/modules/backend/formwidgets/codeeditor/assets/js/codeeditor.js @@ -267,6 +267,21 @@ $.fn.codeEditor.Constructor = CodeEditor + if ($.oc === undefined) + $.oc = {} + + $.oc.codeEditorExtensionModes = { + 'htm': 'html', + 'html': 'html', + 'md': 'markdown', + 'txt': 'plain_text', + 'js': 'javascript', + 'less': 'less', + 'scss': 'scss', + 'sass': 'sass', + 'css': 'css' + } + // CODEEDITOR NO CONFLICT // ================= diff --git a/modules/backend/formwidgets/richeditor/assets/css/richeditor.css b/modules/backend/formwidgets/richeditor/assets/css/richeditor.css index fde1cb191..df4d6abf6 100644 --- a/modules/backend/formwidgets/richeditor/assets/css/richeditor.css +++ b/modules/backend/formwidgets/richeditor/assets/css/richeditor.css @@ -1303,12 +1303,12 @@ body .redactor-box-fullscreen { } .redactor-toolbar, .redactor-dropdown { - z-index: 1350 !important; + z-index: 410 !important; } #redactor-modal-overlay, #redactor-modal-box, #redactor-modal { - z-index: 1351 !important; + z-index: 420 !important; } .redactor-toolbar { background: #dddddd; diff --git a/modules/backend/formwidgets/richeditor/assets/js/richeditor.js b/modules/backend/formwidgets/richeditor/assets/js/richeditor.js index a3b8ef3be..5ae2a4ee0 100644 --- a/modules/backend/formwidgets/richeditor/assets/js/richeditor.js +++ b/modules/backend/formwidgets/richeditor/assets/js/richeditor.js @@ -99,7 +99,7 @@ return if (this.$el.hasClass('stretch')) { - var height = $toolbar.height() + var height = $toolbar.outerHeight(true) $editor.css('top', height+1) $codeEditor.css('top', height) } diff --git a/modules/backend/formwidgets/richeditor/assets/less/richeditor.less b/modules/backend/formwidgets/richeditor/assets/less/richeditor.less index 5386d532f..bb2838a78 100644 --- a/modules/backend/formwidgets/richeditor/assets/less/richeditor.less +++ b/modules/backend/formwidgets/richeditor/assets/less/richeditor.less @@ -51,12 +51,12 @@ } .redactor-toolbar, .redactor-dropdown { - z-index: @richeditor-zindex + 1050 !important; + z-index: @richeditor-zindex + 110 !important; } #redactor-modal-overlay, #redactor-modal-box, #redactor-modal { - z-index: @richeditor-zindex + 1051 !important; + z-index: @richeditor-zindex + 120 !important; } .redactor-toolbar { diff --git a/modules/backend/models/BrandSettings.php b/modules/backend/models/BrandSettings.php index 961491a51..3367f2648 100644 --- a/modules/backend/models/BrandSettings.php +++ b/modules/backend/models/BrandSettings.php @@ -83,7 +83,7 @@ class BrandSettings extends Model 'secondary-color-dark' => self::get('secondary_color_dark', self::SECONDARY_DARK), ]); - $parser->parse(File::get(__DIR__.'/brandsettings/custom.less').self::get('custom_css')); + $parser->parse(File::get(PATH_BASE.'/modules/backend/models/brandsettings/custom.less').self::get('custom_css')); $css = $parser->getCss(); return $css; diff --git a/modules/backend/models/brandsettings/custom.less b/modules/backend/models/brandsettings/custom.less index d65485c92..ad62d9387 100644 --- a/modules/backend/models/brandsettings/custom.less +++ b/modules/backend/models/brandsettings/custom.less @@ -45,6 +45,16 @@ body.outer .layout > .layout-row.layout-head { background-color: @color-sidebarnav-bg; } +// +// Breadcrumb +// + +@color-breadcrumb-background: mix(rgb(43,43,43), @secondary-color-dark, 50%); + +.control-breadcrumb { + background-color: @color-breadcrumb-background; +} + // // Fancy layout // diff --git a/modules/cms/assets/js/october.cmspage.js b/modules/cms/assets/js/october.cmspage.js index ccf903e0d..2a12c3f76 100644 --- a/modules/cms/assets/js/october.cmspage.js +++ b/modules/cms/assets/js/october.cmspage.js @@ -389,16 +389,7 @@ parts = fileName.split('.'), extension = 'txt', mode = 'plain_text', - modes = { - 'htm': 'html', - 'md': 'markdown', - 'txt': 'plain_text', - 'js': 'javascript', - 'less': 'less', - 'scss': 'scss', - 'sass': 'sass', - 'css': 'css' - }, + modes = $.oc.codeEditorExtensionModes, editor = $('[data-control=codeeditor]', pane) if (parts.length >= 2) diff --git a/modules/cms/classes/CmsCompoundObject.php b/modules/cms/classes/CmsCompoundObject.php index 872780919..ad9275c4c 100644 --- a/modules/cms/classes/CmsCompoundObject.php +++ b/modules/cms/classes/CmsCompoundObject.php @@ -8,6 +8,10 @@ use October\Rain\Support\ValidationException; use Cms\Classes\ViewBag; use Cache; use Config; +use Twig_Environment; +use System\Twig\Extension as SystemTwigExtension; +use Cms\Twig\Extension as CmsTwigExtension; +use Cms\Twig\Loader as TwigLoader; /** * This is a base class for CMS objects that have multiple sections - pages, partials and layouts. @@ -56,6 +60,8 @@ class CmsCompoundObject extends CmsObject protected $viewBagCache = false; + protected $originalData = []; + protected static $objectComponentPropertyMap = null; /** @@ -79,6 +85,10 @@ class CmsCompoundObject extends CmsObject $obj->code = $parsedData['code']; $obj->markup = $parsedData['markup']; + $obj->originalData['settings'] = $obj->settings; + $obj->originalData['code'] = $obj->code; + $obj->originalData['markup'] = $obj->markup; + $obj->parseComponentSettings(); $obj->parseSettings(); @@ -213,11 +223,14 @@ class CmsCompoundObject extends CmsObject } if ($this->code) { - $code = preg_replace('/^\<\?php/', '', $this->code); - $code = preg_replace('/^\<\?/', '', $code); - $code = preg_replace('/\?>$/', '', $code); + if ($this->wrapCodeToPhpTags() && $this->originalData['code'] != $this->code) { + $code = preg_replace('/^\<\?php/', '', $this->code); + $code = preg_replace('/^\<\?/', '', $code); + $code = preg_replace('/\?>$/', '', $code); - $content[] = 'code.PHP_EOL.'?>'; + $content[] = 'code.PHP_EOL.'?>'; + } else { + $content[] = $this->code; } $content[] = $this->markup; @@ -371,6 +384,26 @@ class CmsCompoundObject extends CmsObject Cache::forget($key); } + /** + * Returns Twig node tree generated from the object's markup. + * This method is used by the system internally and shouldn't + * participate in the front-end request processing. + * @link http://twig.sensiolabs.org/doc/internals.html Twig internals + * @param mixed $markup Specifies the markup content. + * Use FALSE to load the content from the markup section. + * @return Twig_Node_Module A node tree + */ + public function getTwigNodeTree($markup = false) + { + $loader = new TwigLoader(); + $twig = new Twig_Environment($loader, []); + $twig->addExtension(new CmsTwigExtension()); + $twig->addExtension(new SystemTwigExtension); + + $stream = $twig->tokenize($markup === false ? $this->markup : $markup, 'getTwigNodeTree'); + return $twig->parse($stream); + } + /** * Parses the settings array. * Child classes can override this method in order to update @@ -429,4 +462,13 @@ class CmsCompoundObject extends CmsObject } } } + + /** + * Determines if the content of the code section should be wrapped to PHP tags. + * @return boolean + */ + protected function wrapCodeToPhpTags() + { + return true; + } } diff --git a/modules/cms/classes/Controller.php b/modules/cms/classes/Controller.php index 78a2a0872..f2f79c142 100644 --- a/modules/cms/classes/Controller.php +++ b/modules/cms/classes/Controller.php @@ -269,11 +269,17 @@ class Controller extends BaseController /* * Render the page */ - CmsException::mask($this->page, 400); - $this->loader->setObject($this->page); - $template = $this->twig->loadTemplate($this->page->getFullPath()); - $this->pageContents = $template->render($this->vars); - CmsException::unmask(); + Event::fire('cms.page.beforeTwigRender', [$page, $this->loader, $this->twig], true); + + $apiResult = Event::fire('cms.page.getRenderedContents', [$this->page], true); + if (!strlen($apiResult)) { + CmsException::mask($this->page, 400); + $this->loader->setObject($this->page); + $template = $this->twig->loadTemplate($this->page->getFullPath()); + $this->pageContents = $template->render($this->vars); + CmsException::unmask(); + } else + $this->pageContents = $apiResult; /* * Render the layout diff --git a/modules/cms/classes/Page.php b/modules/cms/classes/Page.php index c6811a910..bf8df9ed6 100644 --- a/modules/cms/classes/Page.php +++ b/modules/cms/classes/Page.php @@ -13,6 +13,11 @@ use Lang; */ class Page extends CmsCompoundObject { + /** + * @var array The API bag allows the API handler code to bind arbitrary data to the page object. + */ + public $apiBag = []; + protected $settingsValidationRules = [ 'title' => 'required', 'url' => ['required', 'regex:/^\/[a-z0-9\/\:_\-\*\[\]\+\?\|\.]*$/i'] @@ -141,8 +146,8 @@ class Page extends CmsCompoundObject } $result = [ - 'references' => $references, - 'nesting' => false, + 'references' => $references, + 'nesting' => false, 'dynamicItems' => false ]; } diff --git a/modules/cms/controllers/Index.php b/modules/cms/controllers/Index.php index 6e5732534..a182ae002 100644 --- a/modules/cms/controllers/Index.php +++ b/modules/cms/controllers/Index.php @@ -123,7 +123,7 @@ class Index extends Controller return [ 'tabTitle' => $this->getTabTitle($type, $template), - 'tab' => $this->makePartial('form_page', [ + 'tab' => $this->makePartial('form_page', [ 'form' => $widget, 'templateType' => $type, 'templateTheme' => $this->theme->getDirName(), diff --git a/modules/cms/controllers/themes/_theme_list.htm b/modules/cms/controllers/themes/_theme_list.htm index 45f0fdce9..3fe0fcb7b 100644 --- a/modules/cms/controllers/themes/_theme_list.htm +++ b/modules/cms/controllers/themes/_theme_list.htm @@ -2,48 +2,50 @@ $themes = Cms\Classes\Theme::all(); $activeTheme = Cms\Classes\Theme::getActiveTheme(); $cnt = count($themes); - - foreach ($themes as $index=>$theme): +?> + $theme): ?> + getDirName() == $theme->getDirName(); $author = $theme->getConfigValue('author'); -?> -
-
-
-
-
-

getConfigValue('name', $theme->getDirName())) ?>

- -

by

- -

getConfigValue('description', 'The theme description is not provided.')) ?>

-
- - - - + ?> +
+
+
+
+
+

getConfigValue('name', $theme->getDirName())) ?>

+ +

by

+

getConfigValue('description', 'The theme description is not provided.')) ?>

+
+ + + + + +
-
+