Updating the Settings pages
This commit is contained in:
parent
1085d20f8c
commit
bfc59c9007
|
|
@ -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',
|
||||
],
|
||||
]);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<args.length; i++)
|
||||
methodArgs.push(args[i])
|
||||
|
||||
data[option].apply(data, methodArgs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.sidenavTree.Constructor = SidenavTree
|
||||
|
||||
// SIDENAVREE NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.sidenavTree.noConflict = function () {
|
||||
$.fn.sidenavTree = old
|
||||
return this
|
||||
}
|
||||
|
||||
// SIDENAVTREE DATA-API
|
||||
// ===============
|
||||
|
||||
$(document).ready(function () {
|
||||
$('[data-control=sidenav-tree]').sidenavTree()
|
||||
})
|
||||
|
||||
}(window.jQuery);
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*!
|
||||
* jQuery Cookie Plugin v1.4.1
|
||||
* https://github.com/carhartl/jquery-cookie
|
||||
*
|
||||
* Copyright 2006, 2014 Klaus Hartl
|
||||
* Released under the MIT license
|
||||
*/
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// CommonJS
|
||||
factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
var pluses = /\+/g;
|
||||
|
||||
function encode(s) {
|
||||
return config.raw ? s : encodeURIComponent(s);
|
||||
}
|
||||
|
||||
function decode(s) {
|
||||
return config.raw ? s : decodeURIComponent(s);
|
||||
}
|
||||
|
||||
function stringifyCookieValue(value) {
|
||||
return encode(config.json ? JSON.stringify(value) : String(value));
|
||||
}
|
||||
|
||||
function parseCookieValue(s) {
|
||||
if (s.indexOf('"') === 0) {
|
||||
// This is a quoted cookie as according to RFC2068, unescape...
|
||||
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
||||
}
|
||||
|
||||
try {
|
||||
// Replace server-side written pluses with spaces.
|
||||
// If we can't decode the cookie, ignore it, it's unusable.
|
||||
// If we can't parse the cookie, ignore it, it's unusable.
|
||||
s = decodeURIComponent(s.replace(pluses, ' '));
|
||||
return config.json ? JSON.parse(s) : s;
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
function read(s, converter) {
|
||||
var value = config.raw ? s : parseCookieValue(s);
|
||||
return $.isFunction(converter) ? converter(value) : value;
|
||||
}
|
||||
|
||||
var config = $.cookie = function (key, value, options) {
|
||||
|
||||
// Write
|
||||
|
||||
if (arguments.length > 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);
|
||||
};
|
||||
|
||||
}));
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
padding: 15px 15px 15px 33px;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
&:before {
|
||||
width: 10px;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
<script src="<?= URL::asset('modules/backend/assets/js/vendor/raphael-min.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.autoellipsis.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.waterfall.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/js/vendor/jquery.cookie.js') ?>"></script>
|
||||
|
||||
<script src="<?= URL::asset('modules/backend/assets/vendor/select2/select2.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/vendor/mustache/mustache.min.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/vendor/fileupload/jquery.fileupload.js') ?>"></script>
|
||||
|
|
@ -69,7 +71,7 @@
|
|||
<script src="<?= URL::asset('modules/backend/assets/js/october.treelist.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/js/october.autocomplete.js') ?>"></script>
|
||||
<script src="<?= URL::asset('modules/backend/assets/js/october.callout.js') ?>"></script>
|
||||
|
||||
<script src="<?= URL::asset('modules/backend/assets/js/october.sidenav-tree.js') ?>"></script>
|
||||
|
||||
<script>
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -132,29 +132,7 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
'icon' => 'icon-cog',
|
||||
'url' => Backend::url('system/settings'),
|
||||
'permissions' => ['backend.manage_users', 'system.*'],
|
||||
'order' => 1000,
|
||||
|
||||
'sideMenu' => [
|
||||
'settings' => [
|
||||
'label' => 'system::lang.settings.menu_label',
|
||||
'icon' => 'icon-cogs',
|
||||
'url' => Backend::url('system/settings'),
|
||||
'permissions' => ['system.manage_settings']
|
||||
],
|
||||
'users' => [
|
||||
'label' => 'backend::lang.user.menu_label',
|
||||
'icon' => 'icon-users',
|
||||
'url' => Backend::url('backend/users'),
|
||||
'permissions' => ['backend.manage_users']
|
||||
],
|
||||
'updates' => [
|
||||
'label' => 'system::lang.updates.menu_label',
|
||||
'icon' => 'icon-cloud-download',
|
||||
'url' => Backend::url('system/updates'),
|
||||
'permissions' => ['system.manage_updates']
|
||||
]
|
||||
]
|
||||
|
||||
'order' => 1000
|
||||
]
|
||||
]);
|
||||
});
|
||||
|
|
@ -237,8 +215,27 @@ class ServiceProvider extends ModuleServiceProvider
|
|||
'category' => 'System',
|
||||
'icon' => 'icon-envelope-square',
|
||||
'url' => Backend::url('system/mailtemplates'),
|
||||
'order' => 400,
|
||||
'order' => 500,
|
||||
],
|
||||
'administrators' => [
|
||||
'label' => 'backend::lang.user.menu_label',
|
||||
'description' => 'backend::lang.user.menu_description',
|
||||
'category' => 'System',
|
||||
'icon' => 'icon-users',
|
||||
'url' => Backend::url('backend/users'),
|
||||
'permissions' => ['backend.manage_users'],
|
||||
'order' => 600
|
||||
],
|
||||
'updates' => [
|
||||
'label' => 'system::lang.updates.menu_label',
|
||||
'description' => 'system::lang.updates.menu_description',
|
||||
'category' => 'System',
|
||||
'icon' => 'icon-cloud-download',
|
||||
'url' => Backend::url('system/updates'),
|
||||
'permissions' => ['system.manage_updates'],
|
||||
'order' => 700
|
||||
]
|
||||
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class SettingsManager
|
|||
'permissions' => [],
|
||||
'order' => 500,
|
||||
'context' => 'system',
|
||||
'keywords' => null
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
<div class="layout">
|
||||
<div class="layout-cell oc-bg-logo"></div>
|
||||
<div class="layout-cell oc-bg-logo">
|
||||
<script>$(document).ready(function(){
|
||||
$('#settings-search-input').focus()
|
||||
})</script>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -121,6 +121,7 @@ return [
|
|||
'title' => 'Manage Updates',
|
||||
'name' => 'Software update',
|
||||
'menu_label' => 'Updates',
|
||||
'menu_description' => 'Update the system, manage and install plugins and themes.',
|
||||
'check_label' => 'Check for updates',
|
||||
'retry_label' => 'Try again',
|
||||
'plugin_name' => 'Name',
|
||||
|
|
|
|||
|
|
@ -1,16 +1,23 @@
|
|||
<?php
|
||||
$context = System\Classes\SettingsManager::instance()->getContext();
|
||||
|
||||
$collapsedGroups = explode('|',
|
||||
isset($_COOKIE['sidenav_treegroupStatus']) ? $_COOKIE['sidenav_treegroupStatus'] : null
|
||||
);
|
||||
|
||||
?>
|
||||
<ul class="top-level">
|
||||
<?php foreach ($items as $category => $items): ?>
|
||||
<li>
|
||||
<?php foreach ($items as $category => $items):
|
||||
$collapsed = in_array($category, $collapsedGroups);
|
||||
?>
|
||||
<li data-group-code="<?= e($category) ?>" <?= $collapsed ? 'data-status="collapsed"' : null ?>>
|
||||
<div class="group">
|
||||
<h3><?= $category ?></h3>
|
||||
<h3><?= e($category) ?></h3>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
<?php foreach ($items as $item): ?>
|
||||
<li class="<?= strtolower($item->owner) == $context->owner && strtolower($item->code) == $context->itemCode ? 'active' : false ?>">
|
||||
<li class="<?= strtolower($item->owner) == $context->owner && strtolower($item->code) == $context->itemCode ? 'active' : false ?>" data-keywords="<?= e(trans($item->keywords)) ?>">
|
||||
<a href="<?= $item->url ?>">
|
||||
<i class="<?= $item->icon ?>"></i>
|
||||
<span class="header"><?= e(trans($item->label)) ?></span>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
<div class="layout-cell">
|
||||
<div class="relative toolbar-item loading-indicator-container size-input-text">
|
||||
<input placeholder="<?= e(trans('system::lang.settings.search')) ?>" type="text" name="search" value=""
|
||||
class="form-control icon search" autocomplete="off"
|
||||
class="form-control icon search"
|
||||
id="settings-search-input"
|
||||
autocomplete="off"
|
||||
data-track-input
|
||||
data-load-indicator
|
||||
data-load-indicator-opaque
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="layout-cell sidenav-tree">
|
||||
<div class="layout-cell sidenav-tree" data-control="sidenav-tree" data-search-input="#settings-search-input">
|
||||
<div class="layout">
|
||||
<div class="layout-row min-size">
|
||||
<?= $this->makePartial('@/modules/system/partials/_settings_menu_toolbar.htm') ?>
|
||||
|
|
|
|||
Loading…
Reference in New Issue