From a9e2e2d80fa5486475672fcedb2677f0c3f76548 Mon Sep 17 00:00:00 2001 From: alekseybobkov Date: Thu, 18 Sep 2014 15:29:56 -0700 Subject: [PATCH] Improvements in the CMS objects and back-end UI. --- app/config/cms.php | 2 +- modules/backend/assets/css/october.css | 105 +++++++++++++++--- .../assets/js/october.changemonitor.js | 11 +- modules/backend/assets/js/october.filelist.js | 9 ++ modules/backend/assets/js/october.utils.js | 23 ++++ .../assets/less/controls/filelist.less | 27 +++++ .../backend/assets/less/controls/forms.less | 44 +++++++- .../assets/less/controls/inspector.less | 24 +--- .../assets/less/controls/treeview.less | 44 +++++++- .../backend/assets/less/core/variables.less | 2 + .../widgets/form/partials/_field_checkbox.htm | 2 +- modules/cms/classes/CmsObject.php | 10 +- modules/cms/classes/FileHelper.php | 14 ++- modules/cms/classes/Router.php | 1 - modules/cms/classes/Theme.php | 21 +++- 15 files changed, 288 insertions(+), 51 deletions(-) diff --git a/app/config/cms.php b/app/config/cms.php index a0d940450..ad0263d98 100644 --- a/app/config/cms.php +++ b/app/config/cms.php @@ -80,7 +80,7 @@ return array( | */ - 'parsedPageCacheTTL' => 0, + 'parsedPageCacheTTL' => 10, /* |-------------------------------------------------------------------------- diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index ded4469d7..75d8a3cb5 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -8729,6 +8729,22 @@ label { .form-group.no-padding.span-right { width: 50%; } +.form-group.input-sidebar-control { + padding-right: 35px; +} +.form-group.input-sidebar-control .sidebar-control { + position: absolute; + right: 8px; + bottom: 28px; + font-size: 16px; + color: #c4c4c4; +} +.form-group.input-sidebar-control .sidebar-control:hover, +.form-group.input-sidebar-control .sidebar-control:focus { + text-decoration: none; + color: #0181b9; + outline: none; +} .form-group-preview .form-control { background-color: #f6f6f6; height: auto; @@ -9071,6 +9087,19 @@ label { border: 0 !important; border-radius: 2px; } +.custom-select.select2-container .loading-indicator { + background: transparent; +} +.custom-select.select2-container .loading-indicator > span { + background-image: url(../images/loading-indicator-transparent.svg); + left: auto; + right: 10px; + top: 19px; + background-size: 17px 17px; +} +.custom-select.select2-container.in-progress .select2-choice .select2-arrow { + display: none!important; +} .custom-select.select2-container.select2-dropdown-open { border-color: #808c8d; } @@ -9081,6 +9110,9 @@ label { .custom-select.select2-container.select2-dropdown-open.select2-drop-above { border-radius: 0 0 2px 2px; } +.custom-select.select2-container-active { + border-color: #808c8d; +} .custom-select.select2-container .select2-choice { height: 36px; line-height: 36px; @@ -9214,6 +9246,9 @@ label { .select2-drop .select2-results .select2-selection-limit { background: #FFFFFF; } +.select2-drop .select2-results .select2-no-results { + padding: 7px!important; +} .select2-drop .select2-results .select2-highlighted { background: #4da7e8; } @@ -10844,6 +10879,27 @@ html.cssanimations .cursor-loading-indicator.hide { top: 17px; right: 17px; } +.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 { + content: ' '; + position: absolute; + width: 100%; + height: 1px; + display: block; + left: 0; + background-color: #dddddd; +} +.control-filelist.hero ul li.active a > span.borders:before { + top: -1px; +} +.control-filelist.hero ul li.active a > span.borders:after { + bottom: -1px; +} .touch .control-filelist li:not(.active) a:hover { background: transparent; } @@ -13287,22 +13343,12 @@ html.cssanimations .fancy-layout .form-tabless-fields .loading-indicator-contain .inspector-fields div.custom-select.select2-container .select2-choice.select2-default { font-weight: normal!Important; } +.inspector-fields div.custom-select.select2-container .loading-indicator > span { + top: 15px; +} .inspector-fields div.custom-select.select2-container.select2-dropdown-open .select2-choice { background: white; } -.inspector-fields div.custom-select.select2-container .loading-indicator { - background: transparent; -} -.inspector-fields div.custom-select.select2-container .loading-indicator > span { - background-image: url(../images/loading-indicator-transparent.svg); - left: auto; - right: 10px; - top: 15px; - background-size: 17px 17px; -} -.inspector-fields div.custom-select.select2-container.in-progress .select2-choice .select2-arrow { - display: none!important; -} .inspector-fields tr.changed td { font-weight: 600; } @@ -13893,6 +13939,14 @@ div[data-control="balloon-selector"]:not(.control-disabled) ul li:hover { .control-treeview ol > li.active > div > span.borders:after { bottom: -1px; } +.control-treeview ol > li.no-data { + padding: 18px 0; + margin: 0; + color: #666666; + font-size: 12px; + text-align: center; + font-weight: 400; +} .control-treeview ol > li > ol > li > div { margin-left: -20px; padding-left: 71px; @@ -14041,6 +14095,31 @@ div[data-control="balloon-selector"]:not(.control-disabled) ul li:hover { text-align: center; font-weight: 400; } +.control-treeview a.menu-control { + display: block; + margin: 20px; + padding: 13px 15px; + border: dotted 2px #ebebeb; + color: #bdc3c7; + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + vertical-align: middle; +} +.control-treeview a.menu-control:hover { + text-decoration: none; + background-color: #58b6f7 !important; + color: #ffffff !important; + border: none; + padding: 15px 17px; +} +.control-treeview a.menu-control i { + margin-right: 10px; + font-size: 14px; +} .control-treeview.light { margin-bottom: 0; margin-top: 20px; diff --git a/modules/backend/assets/js/october.changemonitor.js b/modules/backend/assets/js/october.changemonitor.js index 128ac2418..40478b4ae 100644 --- a/modules/backend/assets/js/october.changemonitor.js +++ b/modules/backend/assets/js/october.changemonitor.js @@ -57,10 +57,16 @@ $(window).on('beforeunload', $.proxy(this.onBeforeUnload, this)) } - ChangeMonitor.prototype.change = function(ev) { + ChangeMonitor.prototype.change = function(ev, inputChange) { if (this.paused) return + if (!inputChange) { + var type = $(ev.target).attr('type') + if (type == 'text' || type == "password") + return + } + if (!this.$el.hasClass('oc-data-changed')) { this.$el.trigger('changed.oc.changeMonitor') this.$el.addClass('oc-data-changed') @@ -83,8 +89,9 @@ var $el = $(ev.target) if ($el.data('oldval.oc.changeMonitor') != $el.val()) { + $el.data('oldval.oc.changeMonitor', $el.val()); - this.change(ev); + this.change(ev, true); } } diff --git a/modules/backend/assets/js/october.filelist.js b/modules/backend/assets/js/october.filelist.js index f6afce5d0..998abd7c2 100644 --- a/modules/backend/assets/js/october.filelist.js +++ b/modules/backend/assets/js/october.filelist.js @@ -48,6 +48,8 @@ return false }) + + this.$el.on('ajaxUpdate', $.proxy(this.update, this)) } FileList.prototype.toggleGroup = function(group) { @@ -112,6 +114,13 @@ $('li.item', this.$el).removeClass('active') if (dataId) $('li.item[data-id="'+dataId+'"]', this.$el).addClass('active') + + this.dataId = dataId + } + + FileList.prototype.update = function() { + if (this.dataId !== undefined) + this.markActive(this.dataId) } // FILELIST PLUGIN DEFINITION diff --git a/modules/backend/assets/js/october.utils.js b/modules/backend/assets/js/october.utils.js index 80129263c..694da800e 100644 --- a/modules/backend/assets/js/october.utils.js +++ b/modules/backend/assets/js/october.utils.js @@ -194,3 +194,26 @@ assetManager = new AssetManager(); return this; } }) + +/* + * String escape + */ + +if ($.oc === undefined) + $.oc = {} + +$.oc.escapeHtmlString = function(string) { + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + }, + htmlEscaper = /[&<>"'\/]/g + + return ('' + string).replace(htmlEscaper, function(match) { + return htmlEscapes[match]; + }) +} \ No newline at end of file diff --git a/modules/backend/assets/less/controls/filelist.less b/modules/backend/assets/less/controls/filelist.less index 7000b44f1..eccaaeae7 100644 --- a/modules/backend/assets/less/controls/filelist.less +++ b/modules/backend/assets/less/controls/filelist.less @@ -194,6 +194,33 @@ top: 17px; right: 17px; } + + &.active { + a { + &:after { + top: -1px; + bottom: -1px; + height: auto; + } + + > span.borders { + &:before, &:after { + content: ' '; + position: absolute; + width: 100%; + height: 1px; + display: block; + left: 0; + background-color: @color-list-active; + } + + &:before {top: -1px;} + &:after {bottom: -1px;} + } + + + } + } } } } diff --git a/modules/backend/assets/less/controls/forms.less b/modules/backend/assets/less/controls/forms.less index 970e28e16..d5b1839cd 100644 --- a/modules/backend/assets/less/controls/forms.less +++ b/modules/backend/assets/less/controls/forms.less @@ -145,6 +145,23 @@ label { width: 50%; } } + + &.input-sidebar-control { + padding-right: 35px; + + .sidebar-control { + position: absolute; + right: 8px; + bottom: 28px; + font-size: 16px; + color: @color-input-sidebar-control; + &:hover, &:focus { + text-decoration: none; + color: @color-link; + outline: none; + } + } + } } .form-group-preview { @@ -485,6 +502,24 @@ label { border: 0 !important; border-radius: @border-radius-base; } + + .loading-indicator { + background: transparent; + + > span { + background-image:url(../images/loading-indicator-transparent.svg); + left: auto; + right: 10px; + top: 19px; + background-size: 17px 17px; + } + } + + &.in-progress { + .select2-choice .select2-arrow { + display: none!important; + } + } } &.select2-container.select2-dropdown-open { @@ -498,6 +533,10 @@ label { } } + &.select2-container-active { + border-color: @color-form-field-border-focus; + } + // // Restyle Select2 // @@ -617,7 +656,6 @@ label { .border-bottom-radius(@border-radius-base); } - &.select2-drop-above.select2-drop-active { border-top: 1px solid @color-custom-select-border; .border-bottom-radius(0); @@ -643,6 +681,10 @@ label { background: #FFFFFF; } + .select2-no-results { + padding: 7px!important; + } + .select2-highlighted { background: @color-custom-select-bg-hover; } diff --git a/modules/backend/assets/less/controls/inspector.less b/modules/backend/assets/less/controls/inspector.less index c112085d1..2a2b94622 100644 --- a/modules/backend/assets/less/controls/inspector.less +++ b/modules/backend/assets/less/controls/inspector.less @@ -194,29 +194,17 @@ } } + .loading-indicator { + > span { + top: 15px; + } + } + &.select2-dropdown-open { .select2-choice { background: white; } } - - .loading-indicator { - background: transparent; - - > span { - background-image:url(../images/loading-indicator-transparent.svg); - left: auto; - right: 10px; - top: 15px; - background-size: 17px 17px; - } - } - - &.in-progress { - .select2-choice .select2-arrow { - display: none!important; - } - } } } diff --git a/modules/backend/assets/less/controls/treeview.less b/modules/backend/assets/less/controls/treeview.less index a93d9c4a1..0ed9a6cb0 100644 --- a/modules/backend/assets/less/controls/treeview.less +++ b/modules/backend/assets/less/controls/treeview.less @@ -1,6 +1,15 @@ .control-treeview { margin-bottom: 40px; + .no-data() { + padding: 18px 0; + margin: 0; + color: @color-filelist-norecords-text; + font-size: 12px; + text-align: center; + font-weight: 400; + } + ol { margin: 0; padding: 0; @@ -367,6 +376,10 @@ } } } + + &.no-data { + .no-data(); + } } @max-level: 10; @@ -401,12 +414,33 @@ } p.no-data { - padding: 18px 0; - margin: 0; - color: @color-filelist-norecords-text; + .no-data(); + } + + a.menu-control { + display: block; + margin: 20px; + padding: 13px 15px; + border: dotted 2px #ebebeb; + color: #bdc3c7; font-size: 12px; - text-align: center; - font-weight: 400; + font-weight: 600; + text-transform: uppercase; + .border-radius(5px); + vertical-align: middle; + + &:hover { + text-decoration: none; + background-color: @color-treeview-hover-bg!important; + color: @color-treeview-hover-text!important; + border: none; + padding: 15px 17px; + } + + i { + margin-right: 10px; + font-size: 14px; + } } /* diff --git a/modules/backend/assets/less/core/variables.less b/modules/backend/assets/less/core/variables.less index f1ebf30c8..355a56f7d 100644 --- a/modules/backend/assets/less/core/variables.less +++ b/modules/backend/assets/less/core/variables.less @@ -188,6 +188,8 @@ @color-custom-input-icon: #666666; @color-custom-input-border: #999999; +@color-input-sidebar-control: #C4C4C4; + @color-switch-input-bg: #f6f6f6; @color-switch-input-on: #8da85e; @color-switch-input-off: #cc3300; diff --git a/modules/backend/widgets/form/partials/_field_checkbox.htm b/modules/backend/widgets/form/partials/_field_checkbox.htm index 5b29d8eca..1ed55a9ba 100644 --- a/modules/backend/widgets/form/partials/_field_checkbox.htm +++ b/modules/backend/widgets/form/partials/_field_checkbox.htm @@ -1,5 +1,5 @@ -
+
$fileName])); if (!strlen(File::extension($fileName))) - $fileName .= '.htm'; + $fileName .= '.'.static::$defaultExtension; $filePath = static::getFilePath($theme, $fileName); if (array_key_exists($filePath, ObjectMemoryCache::$cache)) @@ -153,7 +155,7 @@ class CmsObject implements ArrayAccess throw new SystemException(Lang::get('cms::lang.cms_object.invalid_file', ['name'=>$fileName])); if (!strlen(File::extension($fileName))) - $fileName .= '.htm'; + $fileName .= '.'.static::$defaultExtension; $fullPath = static::getFilePath($theme, $fileName); @@ -331,6 +333,7 @@ class CmsObject implements ArrayAccess throw new ApplicationException(Lang::get('cms::lang.cms_object.error_creating_directory', ['name'=>$dirPath])); } + $newFullPath = $fullPath; if (@File::put($fullPath, $this->content) === false) throw new ApplicationException(Lang::get('cms::lang.cms_object.error_saving', ['name'=>$this->fileName])); @@ -342,7 +345,8 @@ class CmsObject implements ArrayAccess } clearstatcache(); - $this->mtime = @File::lastModified($fullPath); + + $this->mtime = @File::lastModified($newFullPath); $this->originalFileName = $this->fileName; } diff --git a/modules/cms/classes/FileHelper.php b/modules/cms/classes/FileHelper.php index 250b813cb..c95786525 100644 --- a/modules/cms/classes/FileHelper.php +++ b/modules/cms/classes/FileHelper.php @@ -80,10 +80,10 @@ class FileHelper $sections[$key] = self::formatIniString($value, $level+1); else { foreach ($value as $val) - $content .= $key.'[] = "'.$val.'"'.PHP_EOL; + $content .= $key.'[] = "'.self::escapeIniString($val).'"'.PHP_EOL; } } elseif (strlen($value)) - $content .= $key.' = "'.$value.'"'.PHP_EOL; + $content .= $key.' = "'.self::escapeIniString($value).'"'.PHP_EOL; } foreach ($sections as $key=>$section) @@ -91,4 +91,14 @@ class FileHelper return trim($content); } + + /** + * Escapes a string for saving in INI format + * @param string $string Specifies the string to escape + * @return string Returns the processed string + */ + public static function escapeIniString($string) + { + return str_replace('"', '\"', $string); + } } diff --git a/modules/cms/classes/Router.php b/modules/cms/classes/Router.php index 5c014e25a..d3e86432f 100644 --- a/modules/cms/classes/Router.php +++ b/modules/cms/classes/Router.php @@ -90,7 +90,6 @@ class Router */ if (!$fileName) { $router = $this->getRouterObject(); - if ($router->match($url)) { $this->parameters = $router->getParameters(); diff --git a/modules/cms/classes/Theme.php b/modules/cms/classes/Theme.php index 56b65e686..dd0380f03 100644 --- a/modules/cms/classes/Theme.php +++ b/modules/cms/classes/Theme.php @@ -32,6 +32,10 @@ class Theme */ protected $configCache = null; + protected static $activeThemeCache = false; + + protected static $editThemeCache = false; + /** * Loads the theme. */ @@ -95,6 +99,9 @@ class Theme */ public static function getActiveTheme() { + if (self::$activeThemeCache !== false) + return self::$activeThemeCache; + $paramKey = 'cms::theme.active'; $activeTheme = Config::get('cms.activeTheme'); @@ -118,9 +125,9 @@ class Theme $theme = new static; $theme->load($activeTheme); if (!File::isDirectory($theme->getPath())) - return null; + return self::$activeThemeCache = null; - return $theme; + return self::$activeThemeCache = $theme; } /** @@ -130,6 +137,9 @@ class Theme */ public static function setActiveTheme($code) { + self::$activeThemeCache = false; + self::$editThemeCache = false; + $paramKey = 'cms::theme.active'; Parameters::set($paramKey, $code); Cache::forget($paramKey); @@ -146,6 +156,9 @@ class Theme */ public static function getEditTheme() { + if (self::$editThemeCache !== false) + return self::$editThemeCache; + $editTheme = Config::get('cms.editTheme'); if (!$editTheme) $editTheme = static::getActiveTheme()->getDirName(); @@ -160,9 +173,9 @@ class Theme $theme = new static; $theme->load($editTheme); if (!File::isDirectory($theme->getPath())) - return null; + return self::$editThemeCache = null; - return $theme; + return self::$editThemeCache = $theme; } /**