From 98eb3e2e8409d07693c432da796f3c0ad23d1d70 Mon Sep 17 00:00:00 2001 From: alekseybobkov Date: Thu, 24 Jul 2014 15:19:00 +1100 Subject: [PATCH 1/3] System page navigation improvements, not finished --- modules/backend/assets/css/october.css | 109 +++++++++++++++ .../assets/less/controls/sidenav-tree.less | 126 ++++++++++++++++++ .../backend/assets/less/core/variables.less | 8 ++ modules/backend/assets/less/october.less | 1 + modules/backend/classes/NavigationManager.php | 49 +++++-- .../backend/controllers/EditorPreferences.php | 2 + modules/backend/controllers/Users.php | 4 +- .../controllers/editorpreferences/index.htm | 7 - .../backend/controllers/users/myaccount.htm | 7 - modules/backend/layouts/_sidenav.htm | 47 ++++--- .../less/css/october.theme-selector.css | 112 ++++++++++++++++ modules/cms/controllers/Themes.php | 4 +- modules/cms/controllers/themes/index.htm | 10 -- modules/system/ServiceProvider.php | 6 + modules/system/classes/SettingsManager.php | 30 +++++ modules/system/controllers/Settings.php | 2 + modules/system/controllers/settings/index.htm | 27 +--- .../system/controllers/settings/update.htm | 7 - modules/system/lang/en/lang.php | 1 + modules/system/partials/_settings_menu.htm | 9 ++ .../system/partials/_settings_menu_items.htm | 26 ++++ .../partials/_settings_menu_toolbar.htm | 12 ++ modules/system/partials/_system_sidebar.htm | 21 +++ 23 files changed, 541 insertions(+), 86 deletions(-) create mode 100644 modules/backend/assets/less/controls/sidenav-tree.less create mode 100644 modules/cms/assets/less/css/october.theme-selector.css create mode 100644 modules/system/partials/_settings_menu.htm create mode 100644 modules/system/partials/_settings_menu_items.htm create mode 100644 modules/system/partials/_settings_menu_toolbar.htm create mode 100644 modules/system/partials/_system_sidebar.htm diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 1d57bdfa2..6b49d86d2 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -7271,6 +7271,7 @@ body { /* The html and body elements cannot have any padding or margin. */ } body { + webkit-font-smoothing: antialiased; background: #fafafa; } #layout-canvas { @@ -12858,3 +12859,111 @@ div[data-control="balloon-selector"]:not(.control-disabled) ul li:hover { .callout.no-subheader > .header i { margin-top: -5px; } +.sidenav-tree { + width: 280px; + background: #34495e; +} +.sidenav-tree .control-toolbar { + padding: 20px 0 20px 20px; +} +.sidenav-tree .control-toolbar input.form-control { + border: none; +} +.sidenav-tree ul { + padding: 0; + margin: 0; + list-style: none; +} +.sidenav-tree div.scrollbar-thumb { + background: #2b3e50!important; +} +.sidenav-tree ul.top-level > li[data-status=collapsed] > div.group h3:before { + -webkit-transform: rotate(0deg) translate(3px, 0); + -ms-transform: rotate(0deg) translate(3px, 0); + transform: rotate(0deg) translate(3px, 0); +} +.sidenav-tree ul.top-level > li[data-status=collapsed] ul { + display: none; +} +.sidenav-tree ul.top-level > li > div.group h3 { + background: #2b3e50; + color: #ecf0f1; + text-transform: uppercase; + font-size: 14px; + padding: 15px 15px 15px 33px; + margin: 0; + position: relative; +} +.sidenav-tree ul.top-level > li > div.group h3:before { + width: 10px; + height: 10px; + display: block; + position: absolute; + top: 1px; +} +.sidenav-tree ul.top-level > li > div.group h3:before { + left: 13px; + top: 15px; + color: #cfcfcf; + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + text-decoration: inherit; + -webkit-font-smoothing: antialiased; + *margin-right: .3em; + content: "\f0da"; + -webkit-transform: rotate(90deg) translate(5px, 0); + -ms-transform: rotate(90deg) translate(5px, 0); + transform: rotate(90deg) translate(5px, 0); + -webkit-transition: all 0.1s ease; + transition: all 0.1s ease; +} +.sidenav-tree ul.top-level > li > ul li a { + display: block; + position: relative; + padding: 15px 15px 15px 40px; + color: #808b93; + background: #3d5265; + margin-bottom: 1px; + text-decoration: none!important; +} +.sidenav-tree ul.top-level > li > ul li a:hover { + text-decoration: none; +} +.sidenav-tree ul.top-level > li > ul li a i { + position: absolute; + left: 15px; + top: 17px; + font-size: 16px; +} +.sidenav-tree ul.top-level > li > ul li a span { + display: block; + line-height: 150%; +} +.sidenav-tree ul.top-level > li > ul li a span.header { + font-size: 14px; + margin-bottom: 5px; +} +.sidenav-tree ul.top-level > li > ul li a span.description { + font-size: 12px; + font-weight: 100; +} +.sidenav-tree ul.top-level > li > ul li.active a { + background: #34495e; + color: #ecf0f1; +} +.sidenav-tree ul.top-level > li > ul li.active a:before { + content: ' '; + position: absolute; + width: 4px; + background: #e6802b; + left: 0; + top: 0; + height: 100%; +} +.sidenav-tree ul.top-level > li > ul li:last-child a { + margin-bottom: 0; +} +.sidenav-tree ul.top-level > li > ul li:hover a { + background-color: #34495e; +} diff --git a/modules/backend/assets/less/controls/sidenav-tree.less b/modules/backend/assets/less/controls/sidenav-tree.less new file mode 100644 index 000000000..b149a2df8 --- /dev/null +++ b/modules/backend/assets/less/controls/sidenav-tree.less @@ -0,0 +1,126 @@ +.sidenav-tree { + width: 280px; + background: @color-sidebarnav-bg; + + .control-toolbar { + padding: 20px 0 20px 20px; + + input.form-control { + border: none; + } + } + + ul { + padding: 0; + margin: 0; + list-style: none; + } + + div.scrollbar-thumb { + background: #2b3e50!important; + } + + ul.top-level > li { + &[data-status=collapsed] { + > div.group h3:before { + .transform( ~'rotate(0deg) translate(3px, 0)' ); + } + + ul { + display: none; + } + } + + > div.group { + h3 { + background: @color-sidebarnav-tree-group-bg; + color: @color-sidebarnav-tree-group; + text-transform: uppercase; + font-size: 14px; + padding: 15px 15px 15px 33px; + margin: 0; + position: relative; + + &:before { + width: 10px; + height: 10px; + display: block; + position: absolute; + top: 1px; + } + + &:before { + left: 13px; + top: 15px; + color: @color-list-arrow; + .icon(@caret-right); + .transform( ~'rotate(90deg) translate(5px, 0)' ); + .transition(all 0.1s ease); + } + } + } + + > ul { + li { + a { + display: block; + position: relative; + padding: 15px 15px 15px 40px; + color: @color-sidebarnav-tree-inactive-text; + background: @color-sidebarnav-tree-inactive-bg; + margin-bottom: 1px; + text-decoration: none!important; + + &:hover { + text-decoration: none; + } + + i { + position: absolute; + left: 15px; + top: 17px; + font-size: 16px; + } + + span { + display: block; + line-height: 150%; + + &.header { + font-size: 14px; + margin-bottom: 5px; + } + + &.description { + font-size: 12px; + font-weight: 100; + } + } + } + + &.active a { + background: @color-sidebarnav-tree-active-bg; + color: @color-sidebarnav-tree-active-text; + + &:before { + content: ' '; + position: absolute; + width: 4px; + background: @color-sidebarnav-tree-active-marker; + left: 0; + top: 0; + height: 100%; + } + } + + &:last-child a { + margin-bottom: 0; + } + + &:hover a { + background-color: @color-sidebarnav-tree-active-bg; + } + } + } + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/core/variables.less b/modules/backend/assets/less/core/variables.less index 99e18463c..2b205f73e 100644 --- a/modules/backend/assets/less/core/variables.less +++ b/modules/backend/assets/less/core/variables.less @@ -76,6 +76,14 @@ @color-sidebarnav-counter-bg: #d9350f; @color-sidebarnav-counter-text: #ffffff; +@color-sidebarnav-tree-group: #ecf0f1; +@color-sidebarnav-tree-group-bg: #2b3e50; +@color-sidebarnav-tree-inactive-text: #808b93; +@color-sidebarnav-tree-inactive-bg: #3d5265; +@color-sidebarnav-tree-active-bg: #34495e; +@color-sidebarnav-tree-active-text: #ecf0f1; +@color-sidebarnav-tree-active-marker: #e6802b; + @color-list-active: #dddddd; @color-list-hover: #dddddd; @color-list-active-border: #e67e22; diff --git a/modules/backend/assets/less/october.less b/modules/backend/assets/less/october.less index 2b7f57420..364de5238 100644 --- a/modules/backend/assets/less/october.less +++ b/modules/backend/assets/less/october.less @@ -42,3 +42,4 @@ @import "controls/reportwidgets.less"; @import "controls/treelist.less"; @import "controls/callout.less"; +@import "controls/sidenav-tree.less"; diff --git a/modules/backend/classes/NavigationManager.php b/modules/backend/classes/NavigationManager.php index fcd04cef7..e1a275bfa 100644 --- a/modules/backend/classes/NavigationManager.php +++ b/modules/backend/classes/NavigationManager.php @@ -24,6 +24,8 @@ class NavigationManager */ private $items; + private $contextSidenavPartials = []; + private $contextOwner; private $contextMainMenuItemCode; private $contextSideMenuItemCode; @@ -295,9 +297,9 @@ class NavigationManager /** * Sets the navigation context. * The function sets the navigation owner, main menu item code and the side menu item code. - * @param string @owner Specifies the navigation owner in the format Vendor/Module - * @param string @mainMenuItemCode Specifies the main menu item code - * @param string @sideMenuItemCode Specifies the side menu item code + * @param string $owner Specifies the navigation owner in the format Vendor/Module + * @param string $mainMenuItemCode Specifies the main menu item code + * @param string $sideMenuItemCode Specifies the side menu item code */ public function setContext($owner, $mainMenuItemCode, $sideMenuItemCode = null) { @@ -309,7 +311,7 @@ class NavigationManager /** * Sets the navigation context. * The function sets the navigation owner. - * @param string @owner Specifies the navigation owner in the format Vendor/Module + * @param string $owner Specifies the navigation owner in the format Vendor/Module */ public function setContextOwner($owner) { @@ -318,7 +320,7 @@ class NavigationManager /** * Specifies a code of the main menu item in the current navigation context. - * @param string @mainMenuItemCode Specifies the main menu item code + * @param string $mainMenuItemCode Specifies the main menu item code */ public function setContextMainMenu($mainMenuItemCode) { @@ -330,18 +332,20 @@ class NavigationManager * @return mixed Returns an object with the following fields: * - mainMenuCode * - sideMenuCode + * - owner */ public function getContext() { return (object)[ 'mainMenuCode' => $this->contextMainMenuItemCode, - 'sideMenuCode' => $this->contextSideMenuItemCode + 'sideMenuCode' => $this->contextSideMenuItemCode, + 'owner' => $this->contextOwner ]; } /** * Specifies a code of the side menu item in the current navigation context. - * @param string @sideMenuItemCode Specifies the side menu item code + * @param string $sideMenuItemCode Specifies the side menu item code */ public function setContextSideMenu($sideMenuItemCode) { @@ -350,7 +354,7 @@ class NavigationManager /** * Determines if a main menu item is active. - * @param mixed @item Specifies the item object. + * @param mixed $item Specifies the item object. * @return boolean Returns true if the menu item is active. */ public function isMainMenuItemActive($item) @@ -360,7 +364,7 @@ class NavigationManager /** * Determines if a side menu item is active. - * @param mixed @item Specifies the item object. + * @param mixed $item Specifies the item object. * @return boolean Returns true if the side item is active. */ public function isSideMenuItemActive($item) @@ -368,6 +372,33 @@ class NavigationManager return $this->contextOwner == $item->owner && $this->contextSideMenuItemCode == $item->code; } + /** + * Registers a special side navigation partial for a specific main menu. + * The sidenav partial replaces the standard side navigation. + * @param string $owner Specifies the navigation owner in the format Vendor/Module. + * @param string $mainMenuItemCode Specifies the main menu item code. + * @param string $partial Specifies the partial name. + */ + public function registerContextSidenavPartial($owner, $mainMenuItemCode, $partial) + { + $this->contextSidenavPartials[$owner.$mainMenuItemCode] = $partial; + } + + /** + * Returns the side navigation partial for a specific main menu previously registered with the registerContextSidenavPartial() method. + * @param string $owner Specifies the navigation owner in the format Vendor/Module. + * @param string $mainMenuItemCode Specifies the main menu item code. + * @return mixed Returns the partial name or null. + */ + public function getContextSidenavPartial($owner, $mainMenuItemCode) + { + $key = $owner.$mainMenuItemCode; + + return array_key_exists($key, $this->contextSidenavPartials) ? + $this->contextSidenavPartials[$key] : + null; + } + /** * Removes menu items from an array if the supplied user lacks permission. * @param User $user A user object diff --git a/modules/backend/controllers/EditorPreferences.php b/modules/backend/controllers/EditorPreferences.php index 51937200c..bc37ec44a 100644 --- a/modules/backend/controllers/EditorPreferences.php +++ b/modules/backend/controllers/EditorPreferences.php @@ -3,6 +3,7 @@ use Lang; use BackendMenu; use Backend\Classes\Controller; +use System\Classes\SettingsManager; use Backend\Models\EditorPreferences as EditorPreferencesModel; /** @@ -34,6 +35,7 @@ class EditorPreferences extends Controller $this->addJs('/modules/backend/assets/js/editorpreferences/editorpreferences.js', 'core'); BackendMenu::setContext('October.System', 'system', 'mysettings'); + SettingsManager::setContext('October.Backend', 'editor'); } public function index() diff --git a/modules/backend/controllers/Users.php b/modules/backend/controllers/Users.php index 6d8247f65..d00a5bb43 100644 --- a/modules/backend/controllers/Users.php +++ b/modules/backend/controllers/Users.php @@ -6,6 +6,7 @@ use Redirect; use BackendMenu; use BackendAuth; use Backend\Classes\Controller; +use System\Classes\SettingsManager; /** * Backend user controller @@ -55,7 +56,8 @@ class Users extends Controller */ public function myaccount() { - BackendMenu::setContextSideMenu('mysettings'); + SettingsManager::setContext('October.Backend', 'myaccount'); + $this->pageTitle = Lang::get('backend::lang.myaccount.menu_label'); return $this->update($this->user->id, 'myaccount'); } diff --git a/modules/backend/controllers/editorpreferences/index.htm b/modules/backend/controllers/editorpreferences/index.htm index a66351741..26ec34f6e 100644 --- a/modules/backend/controllers/editorpreferences/index.htm +++ b/modules/backend/controllers/editorpreferences/index.htm @@ -1,10 +1,3 @@ - - - - fatalError): ?> 'layout-item stretch layout-column']) ?> diff --git a/modules/backend/controllers/users/myaccount.htm b/modules/backend/controllers/users/myaccount.htm index e046fa852..d9f646246 100644 --- a/modules/backend/controllers/users/myaccount.htm +++ b/modules/backend/controllers/users/myaccount.htm @@ -1,10 +1,3 @@ - - - - fatalError): ?> diff --git a/modules/backend/layouts/_sidenav.htm b/modules/backend/layouts/_sidenav.htm index 2bdf98ad0..636f4e1ce 100644 --- a/modules/backend/layouts/_sidenav.htm +++ b/modules/backend/layouts/_sidenav.htm @@ -1,25 +1,32 @@ owner, $context->mainMenuCode); + + if (!$contextSidenav): + $sideMenuItems = BackendMenu::listSideMenuItems(); + if ($sideMenuItems): ?> -
-
- +
+
+ +
-
+ + + makePartial($contextSidenav) ?> \ No newline at end of file diff --git a/modules/cms/assets/less/css/october.theme-selector.css b/modules/cms/assets/less/css/october.theme-selector.css new file mode 100644 index 000000000..92d8cca90 --- /dev/null +++ b/modules/cms/assets/less/css/october.theme-selector.css @@ -0,0 +1,112 @@ +.theme-selector-layout .layout-cell { + padding: 24px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.theme-selector-layout .theme-thumbnail { + width: 288px; + background: #ecf0f1; + border-bottom: 1px solid #e3e7e9; +} +.theme-selector-layout .theme-thumbnail img { + opacity: 0.6; + filter: alpha(opacity=60); + width: 240px; +} +.theme-selector-layout .theme-description { + border-bottom: 1px solid #f2f3f4; +} +.theme-selector-layout .theme-description h3, +.theme-selector-layout .theme-description p { + opacity: 0.6; + filter: alpha(opacity=60); +} +.theme-selector-layout .theme-description h3 { + margin: 0 0 25px 0; + font-size: 28px; + color: #2b3e50; + display: inline-block; +} +.theme-selector-layout .theme-description p.author { + font-size: 13px; + display: inline-block; + color: #808c8d; +} +.theme-selector-layout .theme-description p.description { + color: #2b3e50; + font-size: 14px; + line-height: 180%; + margin-bottom: 30px; +} +.theme-selector-layout .theme-description .controls button i.icon-star { + margin-right: 5px; + color: #f1a84e; + font-size: 16px; + vertical-align: middle; +} +.theme-selector-layout .layout-row.active .theme-thumbnail { + background: #bdc3c7; + border-bottom-color: #bdc3c7; +} +.theme-selector-layout .layout-row.active .thumbnail-container { + position: relative; +} +.theme-selector-layout .layout-row.active .thumbnail-container:after { + content: ''; + display: block; + width: 0; + height: 0; + border-top: 14px solid transparent; + border-bottom: 14px solid transparent; + border-left: 15px solid #bdc3c7; + position: absolute; + right: -35px; + top: 50%; + margin-top: -14px; +} +.theme-selector-layout .layout-row.active .theme-description h3, +.theme-selector-layout .layout-row:hover .theme-description h3, +.theme-selector-layout .layout-row.active .theme-description p, +.theme-selector-layout .layout-row:hover .theme-description p { + opacity: 1; + filter: alpha(opacity=100); +} +.theme-selector-layout .layout-row.active .theme-thumbnail img, +.theme-selector-layout .layout-row:hover .theme-thumbnail img { + opacity: 1; + filter: alpha(opacity=100); +} +.theme-selector-layout .layout-row.last .theme-description, +.theme-selector-layout .layout-row.last .theme-thumbnail { + border-bottom: none!important; +} +.theme-selector-layout .find-more-themes { + background: #ecf0f1; + color: #2b3e50; + text-decoration: none; + display: block; + padding: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.theme-selector-layout .find-more-themes:hover { + background: #1795f1; + color: white; +} +@media (max-width: 768px) { + .theme-selector-layout .layout-cell, + .theme-selector-layout .layout-row { + display: block!important; + width: auto!important; + height: auto!important; + } + .theme-selector-layout .theme-thumbnail img { + width: 100%; + } + .theme-selector-layout .layout-row.links .theme-thumbnail { + background: transparent; + padding: 0; + } +} diff --git a/modules/cms/controllers/Themes.php b/modules/cms/controllers/Themes.php index 1fabb4f48..a1c0b98fa 100644 --- a/modules/cms/controllers/Themes.php +++ b/modules/cms/controllers/Themes.php @@ -5,6 +5,7 @@ use Config; use BackendMenu; use Input; use Backend\Classes\Controller; +use System\Classes\SettingsManager; use Cms\Classes\Theme as CmsTheme; /** @@ -18,7 +19,7 @@ class Themes extends Controller { public $requiredPermissions = ['cms.manage_themes']; - public $bodyClass = 'slim-container'; + public $bodyClass = 'compact-container'; /** * Constructor. @@ -31,6 +32,7 @@ class Themes extends Controller $this->pageTitle = Lang::get('cms::lang.theme.settings_menu'); BackendMenu::setContext('October.System', 'system', 'settings'); + SettingsManager::setContext('October.Cms', 'theme'); } public function index() diff --git a/modules/cms/controllers/themes/index.htm b/modules/cms/controllers/themes/index.htm index 7f5a47ef0..5b7fe3e33 100644 --- a/modules/cms/controllers/themes/index.htm +++ b/modules/cms/controllers/themes/index.htm @@ -1,14 +1,5 @@
-
-
-
    -
  • -
  • pageTitle) ?>
  • -
-
-
-
'return false']) ?>
@@ -16,6 +7,5 @@
-
\ No newline at end of file diff --git a/modules/system/ServiceProvider.php b/modules/system/ServiceProvider.php index 05438b4b9..1c8554f14 100644 --- a/modules/system/ServiceProvider.php +++ b/modules/system/ServiceProvider.php @@ -258,6 +258,12 @@ class ServiceProvider extends ModuleServiceProvider App::bindShared('command.cache.clear', function($app) { return new \System\Console\CacheClear($app['cache'], $app['files']); }); + + /* + * Register the sidebar for the System main menu + */ + + BackendMenu::registerContextSidenavPartial('October.System', 'system', '@/modules/system/partials/_system_sidebar.htm'); } /** diff --git a/modules/system/classes/SettingsManager.php b/modules/system/classes/SettingsManager.php index 0b7201cfd..be8d47374 100644 --- a/modules/system/classes/SettingsManager.php +++ b/modules/system/classes/SettingsManager.php @@ -29,6 +29,9 @@ class SettingsManager */ private $allItems; + private $contextOwner; + private $contextItemCode; + static $itemDefaults = [ 'code' => null, 'label' => null, @@ -211,6 +214,33 @@ class SettingsManager } } + /** + * Sets the navigation context. + * @param string $owner Specifies the setting items owner plugin or module in the format Vendor/Module. + * @param string $code Specifies the settings item code. + */ + public static function setContext($owner, $code) + { + $instance = self::instance(); + + $instance->contextOwner = strtolower($owner); + $instance->contextItemCode = strtolower($code); + } + + /** + * Returns information about the current settings context. + * @return mixed Returns an object with the following fields: + * - itemCode + * - owner + */ + public function getContext() + { + return (object)[ + 'itemCode' => $this->contextItemCode, + 'owner' => $this->contextOwner + ]; + } + /** * Locates a setting item object by it's owner and code * @param string $owner diff --git a/modules/system/controllers/Settings.php b/modules/system/controllers/Settings.php index 5e6e44fe0..aae6d2394 100644 --- a/modules/system/controllers/Settings.php +++ b/modules/system/controllers/Settings.php @@ -57,6 +57,8 @@ class Settings extends Controller public function update($author, $plugin, $code = null) { + SettingsManager::setContext($author.'.'.$plugin, $code); + try { $item = $this->findSettingItem($author, $plugin, $code); $this->pageTitle = $item->label; diff --git a/modules/system/controllers/settings/index.htm b/modules/system/controllers/settings/index.htm index 32d8c0220..2f5dd3c1c 100644 --- a/modules/system/controllers/settings/index.htm +++ b/modules/system/controllers/settings/index.htm @@ -1,24 +1,3 @@ -
- - $items): ?> - -
-

-
- - - - -
+
+ +
\ No newline at end of file diff --git a/modules/system/controllers/settings/update.htm b/modules/system/controllers/settings/update.htm index 4005714ff..9f46bd05a 100644 --- a/modules/system/controllers/settings/update.htm +++ b/modules/system/controllers/settings/update.htm @@ -1,10 +1,3 @@ - - - - fatalError): ?> 'layout-item stretch layout-column']) ?> diff --git a/modules/system/lang/en/lang.php b/modules/system/lang/en/lang.php index 66336b6ba..4ac2c3a5b 100644 --- a/modules/system/lang/en/lang.php +++ b/modules/system/lang/en/lang.php @@ -65,6 +65,7 @@ return [ 'missing_model' => 'The settings page is missing a Model definition.', 'update_success' => 'Settings for :name have been updated successfully.', 'return' => 'Return to system settings', + 'search' => 'Search' ], 'mail' => [ 'menu_label' => 'Mail Configuration', diff --git a/modules/system/partials/_settings_menu.htm b/modules/system/partials/_settings_menu.htm new file mode 100644 index 000000000..08fb2f3f0 --- /dev/null +++ b/modules/system/partials/_settings_menu.htm @@ -0,0 +1,9 @@ +listItems('system'); + $mySettingItems = System\Classes\SettingsManager::instance()->listItems('mysettings'); + + // + Administrators +?> + +makePartial('@/modules/system/partials/_settings_menu_items.htm', ['items'=>$mySettingItems]); ?> +makePartial('@/modules/system/partials/_settings_menu_items.htm', ['items'=>$systemItems]); ?> \ No newline at end of file diff --git a/modules/system/partials/_settings_menu_items.htm b/modules/system/partials/_settings_menu_items.htm new file mode 100644 index 000000000..861ed7fc4 --- /dev/null +++ b/modules/system/partials/_settings_menu_items.htm @@ -0,0 +1,26 @@ +getContext(); +?> + \ No newline at end of file diff --git a/modules/system/partials/_settings_menu_toolbar.htm b/modules/system/partials/_settings_menu_toolbar.htm new file mode 100644 index 000000000..982279dfc --- /dev/null +++ b/modules/system/partials/_settings_menu_toolbar.htm @@ -0,0 +1,12 @@ +
+
+
+ +
+
+
\ No newline at end of file diff --git a/modules/system/partials/_system_sidebar.htm b/modules/system/partials/_system_sidebar.htm new file mode 100644 index 000000000..59f2f000d --- /dev/null +++ b/modules/system/partials/_system_sidebar.htm @@ -0,0 +1,21 @@ +
+
+
+ makePartial('@/modules/system/partials/_settings_menu_toolbar.htm') ?> +
+ +
+
+
+ +
+
+ makePartial('@/modules/system/partials/_settings_menu.htm') ?> +
+
+ +
+
+
+
+
\ No newline at end of file From bfc59c9007447dae108bbef2b04b04040eac38a7 Mon Sep 17 00:00:00 2001 From: alekseybobkov Date: Sun, 27 Jul 2014 11:11:16 +1100 Subject: [PATCH 2/3] Updating the Settings pages --- modules/backend/ServiceProvider.php | 3 +- modules/backend/assets/css/october.css | 1 + .../backend/assets/js/october.sidenav-tree.js | 248 ++++++++++++++++++ .../backend/assets/js/vendor/jquery.cookie.js | 117 +++++++++ .../assets/less/controls/sidenav-tree.less | 1 + modules/backend/lang/en/lang.php | 2 + modules/backend/layouts/_head.htm | 4 +- modules/system/ServiceProvider.php | 45 ++-- modules/system/classes/SettingsManager.php | 1 + modules/system/controllers/settings/index.htm | 6 +- modules/system/lang/en/lang.php | 1 + .../system/partials/_settings_menu_items.htm | 15 +- .../partials/_settings_menu_toolbar.htm | 4 +- modules/system/partials/_system_sidebar.htm | 2 +- 14 files changed, 417 insertions(+), 33 deletions(-) create mode 100644 modules/backend/assets/js/october.sidenav-tree.js create mode 100755 modules/backend/assets/js/vendor/jquery.cookie.js diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php index 34aea94e1..9f3dd231d 100644 --- a/modules/backend/ServiceProvider.php +++ b/modules/backend/ServiceProvider.php @@ -101,7 +101,8 @@ class ServiceProvider extends ModuleServiceProvider 'icon' => 'icon-user', 'url' => Backend::URL('backend/users/myaccount'), 'order' => 400, - 'context' => 'mysettings' + 'context' => 'mysettings', + 'keywords' => 'backend::lang.myaccount.menu_keywords', ], ]); }); diff --git a/modules/backend/assets/css/october.css b/modules/backend/assets/css/october.css index 6b49d86d2..5b7d56b26 100644 --- a/modules/backend/assets/css/october.css +++ b/modules/backend/assets/css/october.css @@ -12893,6 +12893,7 @@ div[data-control="balloon-selector"]:not(.control-disabled) ul li:hover { padding: 15px 15px 15px 33px; margin: 0; position: relative; + cursor: pointer; } .sidenav-tree ul.top-level > li > div.group h3:before { width: 10px; diff --git a/modules/backend/assets/js/october.sidenav-tree.js b/modules/backend/assets/js/october.sidenav-tree.js new file mode 100644 index 000000000..55d8ef192 --- /dev/null +++ b/modules/backend/assets/js/october.sidenav-tree.js @@ -0,0 +1,248 @@ +/* + * Side navigation tree + * + * Data attributes: + * - data-control="sidenav-tree" - enables the plugin + * - data-tree-name - unique name of the tree control. The name is used for storing user configuration in the browser cookies. + * + * JavaScript API: + * $('#tree').sidenavTree() + * + * Dependences: + * - Null + */ + ++function ($) { "use strict"; + + // SIDENAVTREE CLASS DEFINITION + // ============================ + + var SidenavTree = function(element, options) { + this.options = options + this.$el = $(element) + + this.init(); + } + + SidenavTree.DEFAULTS = { + treeName: 'sidenav_tree' + } + + SidenavTree.prototype.init = function (){ + var self = this + + this.statusCookieName = this.options.treeName + 'groupStatus' + this.searchCookieName = this.options.treeName + 'search' + this.$searchInput = $(this.options.searchInput) + + this.$el.on('click', 'li > div.group', function() { + self.toggleGroup($(this).closest('li')) + + return false; + }); + + this.$searchInput.on('keyup', function(){ + self.handleSearchChange() + }) + + var searchTerm = $.cookie(this.searchCookieName) + if (searchTerm !== undefined && searchTerm.length > 0) { + this.$searchInput.val(searchTerm) + this.applySearch() + } + } + + SidenavTree.prototype.toggleGroup = function(group) { + var $group = $(group), + status = $group.attr('data-status') + + status === undefined || status == 'expanded' ? + this.collapseGroup($group) : + this.expandGroup($group) + } + + SidenavTree.prototype.collapseGroup = function(group) { + var + $list = $('> ul', group), + self = this; + + $list.css('overflow', 'hidden') + $list.animate({'height': 0}, { duration: 100, queue: false, complete: function() { + $list.css({ + 'overflow': 'visible', + 'display': 'none' + }) + $(group).attr('data-status', 'collapsed') + $(window).trigger('oc.updateUi') + self.saveGroupStatus($(group).data('group-code'), true) + } }) + } + + SidenavTree.prototype.expandGroup = function(group, duration) { + var + $list = $('> ul', group), + self = this + + duration = duration === undefined ? 100 : duration + + $list.css({ + 'overflow': 'hidden', + 'display': 'block', + 'height': 0 + }) + $list.animate({'height': $list[0].scrollHeight}, { duration: duration, queue: false, complete: function() { + $list.css({ + 'overflow': 'visible', + 'height': 'auto' + }) + $(group).attr('data-status', 'expanded') + $(window).trigger('oc.updateUi') + self.saveGroupStatus($(group).data('group-code'), false) + } }) + } + + SidenavTree.prototype.saveGroupStatus = function(groupCode, collapsed) { + var collapsedGroups = $.cookie(this.statusCookieName), + updatedGroups = [] + + if (collapsedGroups === undefined) + collapsedGroups = '' + + collapsedGroups = collapsedGroups.split('|') + $.each(collapsedGroups, function() { + if (groupCode != this) + updatedGroups.push(this) + }) + + if (collapsed) + updatedGroups.push(groupCode) + + $.cookie(this.statusCookieName, updatedGroups.join('|'), { expires: 30, path: '/' }) + } + + SidenavTree.prototype.handleSearchChange = function() { + var lastValue = this.$searchInput.data('oc.lastvalue'); + + if (lastValue !== undefined && lastValue == this.$searchInput.val()) + return + + this.$searchInput.data('oc.lastvalue', this.$searchInput.val()) + + if (this.dataTrackInputTimer !== undefined) + window.clearTimeout(this.dataTrackInputTimer); + + var self = this + this.dataTrackInputTimer = window.setTimeout(function(){ + self.applySearch() + }, 300); + + $.cookie(this.searchCookieName, $.trim(this.$searchInput.val()), { expires: 30, path: '/' }) + } + + SidenavTree.prototype.applySearch = function() { + var query = $.trim(this.$searchInput.val()), + words = query.toLowerCase().split(' '), + visibleGroups = [], + visibleItems = [], + self = this + + if (query.length == 0) { + $('li', this.$el).removeClass('hidden') + + return + } + + // Find visible groups and items + // + $('ul.top-level > li', this.$el).each(function() { + var $li = $(this) + + if (self.textContainsWords($('div.group h3', $li).text(), words)) { + visibleGroups.push($li.get(0)) + + $('ul li', $li).each(function(){ + visibleItems.push(this) + }) + } else { + $('ul li', $li).each(function(){ + if (self.textContainsWords($(this).text(), words) || self.textContainsWords($(this).data('keywords'), words)) { + visibleGroups.push($li.get(0)) + visibleItems.push(this) + } + }) + } + }) + + // Hide invisible groups and items + // + $('ul.top-level > li', this.$el).each(function() { + var $li = $(this), + groupIsVisible = $.inArray(this, visibleGroups) !== -1 + + $li.toggleClass('hidden', !groupIsVisible) + if (groupIsVisible) + self.expandGroup($li, 0) + + $('ul li', $li).each(function(){ + var $itemLi = $(this) + + $itemLi.toggleClass('hidden', $.inArray(this, visibleItems) == -1) + }) + }) + + return false + } + + SidenavTree.prototype.textContainsWords = function(text, words) { + text = text.toLowerCase() + + for (var i = 0; i < words.length; i++) { + if (text.indexOf(words[i]) === -1) + return false + } + + return true + } + + // SIDENAVTREE PLUGIN DEFINITION + // ============================ + + var old = $.fn.sidenavTree + + $.fn.sidenavTree = function (option) { + var args = arguments; + + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.sidenavTree') + var options = $.extend({}, SidenavTree.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('oc.sidenavTree', (data = new SidenavTree(this, options))) + if (typeof option == 'string') { + var methodArgs = []; + for (var i=1; i 1 && !$.isFunction(value)) { + options = $.extend({}, config.defaults, options); + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setTime(+t + days * 864e+5); + } + + return (document.cookie = [ + encode(key), '=', stringifyCookieValue(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // Read + + var result = key ? undefined : {}; + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling $.cookie(). + var cookies = document.cookie ? document.cookie.split('; ') : []; + + for (var i = 0, l = cookies.length; i < l; i++) { + var parts = cookies[i].split('='); + var name = decode(parts.shift()); + var cookie = parts.join('='); + + if (key && key === name) { + // If second argument (value) is a function it's a converter... + result = read(cookie, value); + break; + } + + // Prevent storing a cookie that we couldn't decode. + if (!key && (cookie = read(cookie)) !== undefined) { + result[name] = cookie; + } + } + + return result; + }; + + config.defaults = {}; + + $.removeCookie = function (key, options) { + if ($.cookie(key) === undefined) { + return false; + } + + // Must not alter options, thus extending a fresh object... + $.cookie(key, '', $.extend({}, options, { expires: -1 })); + return !$.cookie(key); + }; + +})); diff --git a/modules/backend/assets/less/controls/sidenav-tree.less b/modules/backend/assets/less/controls/sidenav-tree.less index b149a2df8..72eb5b3df 100644 --- a/modules/backend/assets/less/controls/sidenav-tree.less +++ b/modules/backend/assets/less/controls/sidenav-tree.less @@ -40,6 +40,7 @@ padding: 15px 15px 15px 33px; margin: 0; position: relative; + cursor: pointer; &:before { width: 10px; diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index 28f721349..13ec1161b 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -49,6 +49,7 @@ return [ 'user' => [ 'name' => 'Administrator', 'menu_label' => 'Administrators', + 'menu_description' => 'Manage back-end administrator users, groups and permissions.', 'list_title' => 'Manage Administrators', 'new' => 'New Administrator', 'login' => "Login", @@ -178,6 +179,7 @@ return [ 'myaccount' => [ 'menu_label' => 'My Account', 'menu_description' => 'Update your account details such as name, email address and password.', + 'menu_keywords' => 'security login' ], 'backend_preferences' => [ 'menu_label' => 'Backend Preferences', diff --git a/modules/backend/layouts/_head.htm b/modules/backend/layouts/_head.htm index 8dceb3af1..fc61b28d6 100644 --- a/modules/backend/layouts/_head.htm +++ b/modules/backend/layouts/_head.htm @@ -18,6 +18,8 @@ + + @@ -69,7 +71,7 @@ - +