diff --git a/webroot/js/main.js b/webroot/js/main.js index f2a5293..4de4f5e 100644 --- a/webroot/js/main.js +++ b/webroot/js/main.js @@ -162,4 +162,18 @@ $(document).ready(() => { $('#globalSearch') .keydown(debouncedGlobalSearch) .keydown(focusSearchResults); -}) + + $('.lock-sidebar a.btn-lock-sidebar').click(() => { + const $sidebar = $('.sidebar') + let expanded = $sidebar.hasClass('expanded'); + if (expanded) { + $sidebar.removeClass('expanded') + } else { + $sidebar.addClass('expanded') + } + const settingName = 'ui.sidebar.expanded'; + const url = `/user-settings/setSetting/${settingName}` + AJAXApi.quickFetchAndPostForm(url, { + value: expanded ? 0 : 1 + }, { provideFeedback: false}) + }) From 29ca08ce608519f140e59ce0f4214c5f0893610f Mon Sep 17 00:00:00 2001 From: Sami Mokaddem Date: Fri, 8 Oct 2021 16:57:38 +0200 Subject: [PATCH 12/26] new: [sidebar:bookmarks] Added early version of user-defined bookmarks Bookmark configs are saved in their respective user setting for each users --- src/Controller/Component/ACLComponent.php | 3 ++ .../Component/NavigationComponent.php | 30 +++++++++++++++++- src/Controller/UserSettingsController.php | 16 ++++++++++ src/Model/Table/UserSettingsTable.php | 22 +++++++++++++ templates/UserSettings/save_bookmark.php | 30 ++++++++++++++++++ templates/element/layouts/sidebar.php | 31 +++++++++++++------ .../element/layouts/sidebar/bookmark-add.php | 11 +++++++ .../layouts/sidebar/bookmark-entry.php | 30 ++++++++++++++++++ .../element/layouts/sidebar/category.php | 2 +- webroot/css/layout.css | 19 ++++++++++++ webroot/js/main.js | 9 ++++++ 11 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 templates/UserSettings/save_bookmark.php create mode 100644 templates/element/layouts/sidebar/bookmark-add.php create mode 100644 templates/element/layouts/sidebar/bookmark-entry.php diff --git a/src/Controller/Component/ACLComponent.php b/src/Controller/Component/ACLComponent.php index 58c19fc..1376d96 100644 --- a/src/Controller/Component/ACLComponent.php +++ b/src/Controller/Component/ACLComponent.php @@ -457,6 +457,9 @@ class ACLComponent extends Component { $menu = $this->Navigation->getSideMenu(); foreach ($menu as $group => $subMenu) { + if ($group == '__bookmarks') { + continue; + } foreach ($subMenu as $subMenuElementName => $subMenuElement) { if (!empty($subMenuElement['url']) && !$this->checkAccessUrl($subMenuElement['url'], true) === true) { unset($menu[$group][$subMenuElementName]); diff --git a/src/Controller/Component/NavigationComponent.php b/src/Controller/Component/NavigationComponent.php index b18a34b..f1ad538 100644 --- a/src/Controller/Component/NavigationComponent.php +++ b/src/Controller/Component/NavigationComponent.php @@ -50,9 +50,37 @@ class NavigationComponent extends Component public function getSideMenu(): array { $sidemenu = new Sidemenu($this->iconToTableMapping, $this->request); - return $sidemenu->get(); + $sidemenu = $sidemenu->get(); + $sidemenu = $this->addUserBookmarks($sidemenu); + return $sidemenu; } + + public function addUserBookmarks($sidemenu): array + { + $bookmarks = $this->getUserBookmarks(); + $sidemenu = array_merge([ + '__bookmarks' => $bookmarks + ], $sidemenu); + return $sidemenu; + } + + public function getUserBookmarks(): array + { + $userSettingTable = TableRegistry::getTableLocator()->get('UserSettings'); + $setting = $userSettingTable->getSettingByName($this->request->getAttribute('identity'), 'ui.sidebar.bookmarks'); + $bookmarks = is_null($setting) ? [] : json_decode($setting->value, true); + + $links = array_map(function($bookmark) { + return [ + 'name' => $bookmark['name'], + 'label' => $bookmark['label'], + 'url' => $bookmark['url'], + ]; + }, $bookmarks); + return $links; + } + public function getBreadcrumb(): array { $controller = $this->request->getParam('controller'); diff --git a/src/Controller/UserSettingsController.php b/src/Controller/UserSettingsController.php index 4da2ed4..99c212e 100644 --- a/src/Controller/UserSettingsController.php +++ b/src/Controller/UserSettingsController.php @@ -136,4 +136,20 @@ class UserSettingsController extends AppController } $this->set('settingName', $settingsName); } + + public function saveBookmark() + { + if (!$this->request->is('get')) { + $result = $this->UserSettings->saveBookmark($this->ACL->getUser(), $this->request->getData()); + $success = !empty($result); + $message = $success ? __('Bookmark saved') : __('Could not save bookmark'); + $this->CRUD->setResponseForController('saveBookmark', $success, $message, $result); + $responsePayload = $this->CRUD->getResponsePayload(); + if (!empty($responsePayload)) { + return $responsePayload; + } + } + $this->set('user_id', $this->ACL->getUser()->id); + } + } \ No newline at end of file diff --git a/src/Model/Table/UserSettingsTable.php b/src/Model/Table/UserSettingsTable.php index b4168f9..1e34b17 100644 --- a/src/Model/Table/UserSettingsTable.php +++ b/src/Model/Table/UserSettingsTable.php @@ -57,3 +57,25 @@ class UserSettingsTable extends AppTable $savedData = $this->save($setting); return $savedData; } + + public function saveBookmark($user, $data) + { + $bookmarkSettingName = 'ui.sidebar.bookmarks'; + $setting = $this->getSettingByName($user, $bookmarkSettingName); + $bookmarkData = [ + 'label' => $data['bookmark_label'], + 'name' => $data['bookmark_name'], + 'url' => $data['bookmark_url'], + ]; + if (is_null($setting)) { // setting not found, create it + $bookmarksData = json_encode([$bookmarkData]); + $result = $this->createSetting($user, $bookmarkSettingName, $bookmarksData); + } else { + $bookmarksData = json_decode($setting->value); + $bookmarksData[] = $bookmarkData; + $bookmarksData = json_encode($bookmarksData); + $result = $this->editSetting($user, $bookmarkSettingName, $bookmarksData); + } + return $result; + } +} diff --git a/templates/UserSettings/save_bookmark.php b/templates/UserSettings/save_bookmark.php new file mode 100644 index 0000000..e48626e --- /dev/null +++ b/templates/UserSettings/save_bookmark.php @@ -0,0 +1,30 @@ +element('genericElements/Form/genericForm', [ + 'data' => [ + 'title' => __('Add a bookmark'), + 'description' => __('Specify the name and the URL of the bookmark which will be tied to your user profile.'), + 'model' => 'UserSettings', + 'fields' => [ + [ + 'field' => 'bookmark_name', + 'label' => __('Name'), + 'placeholder' => __('Home page'), + ], + [ + 'field' => 'bookmark_label', + 'label' => __('Label'), + 'placeholder' => __('Home'), + ], + [ + 'field' => 'bookmark_url', + 'label' => __('URL'), + 'placeholder' => '/instance/home', + ], + ], + 'submit' => [ + 'action' => $this->request->getParam('action') + ] + ], + ]); +?> + diff --git a/templates/element/layouts/sidebar.php b/templates/element/layouts/sidebar.php index 3c20ce7..4aeb15f 100644 --- a/templates/element/layouts/sidebar.php +++ b/templates/element/layouts/sidebar.php @@ -2,19 +2,32 @@ - - + + - + \ No newline at end of file diff --git a/templates/element/layouts/sidebar/bookmark-add.php b/templates/element/layouts/sidebar/bookmark-add.php new file mode 100644 index 0000000..8e906d2 --- /dev/null +++ b/templates/element/layouts/sidebar/bookmark-add.php @@ -0,0 +1,11 @@ +Bootstrap->button([ + 'nodeType' => 'a', + 'icon' => 'plus', + 'title' => __('Add new bookmark'), + 'variant' => 'primary', + 'size' => 'sm', + 'params' => [ + 'id' => 'btn-add-bookmark', + ] +]); diff --git a/templates/element/layouts/sidebar/bookmark-entry.php b/templates/element/layouts/sidebar/bookmark-entry.php new file mode 100644 index 0000000..f2d01c1 --- /dev/null +++ b/templates/element/layouts/sidebar/bookmark-entry.php @@ -0,0 +1,30 @@ +Bootstrap->button([ + 'nodeType' => 'a', + 'text' => h($label), + 'title' => h($name), + 'variant' => 'dark', + 'outline' => !$active, + 'size' => 'sm', + 'icon' => h($icon), + 'class' => ['mb-1'], + 'params' => [ + 'href' => h($url), + ] + ]); +?> diff --git a/templates/element/layouts/sidebar/category.php b/templates/element/layouts/sidebar/category.php index 7c2be88..eaa4d00 100644 --- a/templates/element/layouts/sidebar/category.php +++ b/templates/element/layouts/sidebar/category.php @@ -1,4 +1,4 @@ -
  • +

  • diff --git a/webroot/css/layout.css b/webroot/css/layout.css index bd7e88d..1e62241 100644 --- a/webroot/css/layout.css +++ b/webroot/css/layout.css @@ -243,11 +243,30 @@ ul.sidebar-elements > li { list-style: none; } +ul.sidebar-elements li.bookmarks { + padding: 0 calc((var(--sidebar-width-collapsed) - 25px) / 2); +} + .sidebar.expanded ul.sidebar-elements li > a.sidebar-link, .sidebar:hover ul.sidebar-elements li > a.sidebar-link { text-overflow: ellipsis; } +.sidebar ul.sidebar-elements li.bookmark-categ, +.sidebar ul.sidebar-elements li.bookmarks { + display: none; +} + +.sidebar.expanded ul.sidebar-elements li.bookmark-categ, +.sidebar:hover ul.sidebar-elements li.bookmark-categ { + display: flex; +} + +.sidebar.expanded ul.sidebar-elements li.bookmarks, +.sidebar:hover ul.sidebar-elements li.bookmarks { + display: list-item; +} + ul.sidebar-elements li > a.sidebar-link { position: relative; display: block; diff --git a/webroot/js/main.js b/webroot/js/main.js index 4de4f5e..5f6bd46 100644 --- a/webroot/js/main.js +++ b/webroot/js/main.js @@ -177,3 +177,12 @@ $(document).ready(() => { value: expanded ? 0 : 1 }, { provideFeedback: false}) }) + + $('.sidebar #btn-add-bookmark').click(() => { + const url = '/user-settings/saveBookmark'; + UI.submissionModal(url).then(([modalFactory, ajaxApi]) => { + const $input = modalFactory.$modal.find('input[name="bookmark_url"]') + $input.val(window.location.pathname) + }) + }) +}) From 0d6e6aa7a4875a07e0192dae662a86a985b20994 Mon Sep 17 00:00:00 2001 From: Sami Mokaddem Date: Tue, 12 Oct 2021 10:16:36 +0200 Subject: [PATCH 13/26] chg: [userSettings] Initial version of template - WiP --- src/Controller/UsersController.php | 5 ++ src/Model/Entity/Individual.php | 10 +++ templates/Instance/settings.php | 2 - templates/Users/settings.php | 80 +++++++++++++++++++ .../element/layouts/header/header-profile.php | 5 +- 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 templates/Users/settings.php diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 4b13df6..ec17d6b 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -148,6 +148,11 @@ class UsersController extends AppController } } + public function settings() + { + $this->set('user', $this->ACL->getUser()); + } + public function register() { $this->InboxProcessors = TableRegistry::getTableLocator()->get('InboxProcessors'); diff --git a/src/Model/Entity/Individual.php b/src/Model/Entity/Individual.php index a14e339..15ea1f2 100644 --- a/src/Model/Entity/Individual.php +++ b/src/Model/Entity/Individual.php @@ -16,4 +16,14 @@ class Individual extends AppModel protected $_accessibleOnNew = [ 'uuid' => true, ]; + + protected $_virtual = ['full_name']; + + protected function _getFullName() + { + if (empty($this->first_name) && empty($this->last_name)) { + return $this->username; + } + return sprintf("%s %s", $this->first_name, $this->last_name); + } } diff --git a/templates/Instance/settings.php b/templates/Instance/settings.php index 0e9adf6..5e85df6 100644 --- a/templates/Instance/settings.php +++ b/templates/Instance/settings.php @@ -42,8 +42,6 @@ function genNavcard($settingsProvider, $appView) ]); array_unshift($cardContent, $notice); $tabsOptions0 = [ - // 'vertical' => true, - // 'vertical-size' => 2, 'card' => false, 'pills' => false, 'justify' => 'center', diff --git a/templates/Users/settings.php b/templates/Users/settings.php new file mode 100644 index 0000000..22222bf --- /dev/null +++ b/templates/Users/settings.php @@ -0,0 +1,80 @@ + [ + 'ui.bsTheme' => [ + 'description' => 'The Bootstrap theme to use for the application', + 'default' => 'default', + 'name' => 'UI Theme', + 'options' => (function () { + $instanceTable = TableRegistry::getTableLocator()->get('Instance'); + $themes = $instanceTable->getAvailableThemes(); + return array_combine($themes, $themes); + })(), + 'severity' => 'info', + 'type' => 'select' + ], + ], + __('Bookmarks') => 'Bookmarks', + __('Account Security') => 'Account Security', +]; + +$cardNavs = array_keys($settings); +$cardContent = []; + +$sectionHtml = ''; +foreach ($settings[__('Appearance')] as $sectionName => $sectionContent) { + $sectionHtml .= $this->element('Settings/panel', [ + 'sectionName' => $sectionName, + 'panelName' => $sectionName, + 'panelSettings' => $sectionContent, + ]); +} +$cardContent[] = $sectionHtml; +$cardContent[] = $settings[__('Bookmarks')]; +$cardContent[] = $settings[__('Account Security')]; + +$tabsOptions = [ + 'vertical' => true, + 'vertical-size' => 2, + 'card' => true, + 'pills' => true, + 'justify' => 'center', + 'nav-class' => ['settings-tabs'], + 'data' => [ + 'navs' => $cardNavs, + 'content' => $cardContent + ] +]; +$tabs = $this->Bootstrap->tabs($tabsOptions); +?> + +

    +
    +
    +
    + username) ?> + individual->full_name) ?> +
    +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/templates/element/layouts/header/header-profile.php b/templates/element/layouts/header/header-profile.php index 27c5b8d..bcc0fbf 100644 --- a/templates/element/layouts/header/header-profile.php +++ b/templates/element/layouts/header/header-profile.php @@ -19,7 +19,10 @@ use Cake\Routing\Router; - + From 3ea877fe10965f03550d97b5ccc678c61c4f7b9c Mon Sep 17 00:00:00 2001 From: Sami Mokaddem Date: Tue, 12 Oct 2021 10:21:12 +0200 Subject: [PATCH 14/26] chg: [ui:settings] Refactored setting factory to be more generic --- templates/Instance/settings.php | 144 +++++--------------- templates/element/Settings/category.php | 61 +++++++++ templates/element/Settings/panel.php | 17 +++ templates/element/Settings/scrollspyNav.php | 13 ++ templates/element/Settings/section.php | 46 +++++++ 5 files changed, 169 insertions(+), 112 deletions(-) create mode 100644 templates/element/Settings/category.php create mode 100644 templates/element/Settings/section.php diff --git a/templates/Instance/settings.php b/templates/Instance/settings.php index 5e85df6..20215c6 100644 --- a/templates/Instance/settings.php +++ b/templates/Instance/settings.php @@ -5,8 +5,24 @@ $variantFromSeverity = [ 'warning' => 'warning', 'info' => 'info', ]; -$this->set('variantFromSeverity', $variantFromSeverity); -$settingTable = genNavcard($settingsProvider, $this); + +$navLinks = []; +$tabContents = []; + +foreach ($settingsProvider as $settingTitle => $settingContent) { + $navLinks[] = h($settingTitle); + $tabContents[] = $this->element('Settings/category', [ + 'settings' => $settingContent, + 'includeScrollspy' => true, + ]); +} + +array_unshift($navLinks, __('Settings Diagnostic')); +$notice = $this->element('Settings/notice', [ + 'variantFromSeverity' => $variantFromSeverity, + 'notices' => $notices, +]); +array_unshift($tabContents, $notice); ?>
    element('Settings/search', [ - 'settingsFlattened' => $settingsFlattened, - ]); + $this->element('Settings/search', [ + 'settingsFlattened' => $settingsFlattened, + ]); ?>
    false, - 'pills' => false, - 'justify' => 'center', - 'nav-class' => ['settings-tabs'], - 'data' => [ - 'navs' => $navLinks, - 'content' => $tabContents - ] - ]; - echo $this->Bootstrap->tabs($tabsOptions); + $tabsOptions = [ + 'card' => false, + 'pills' => false, + 'justify' => 'center', + 'nav-class' => ['settings-tabs'], + 'data' => [ + 'navs' => $navLinks, + 'content' => $tabContents + ] + ]; + echo $this->Bootstrap->tabs($tabsOptions); + echo $this->Html->script('settings'); ?>
    - -