new: [userSettings] Added complete support of user settings
Including support of bookmarks, sidebar behavior and themingpull/72/head
parent
a2e3ad76dd
commit
78180fa90f
|
@ -132,7 +132,12 @@ class AppController extends Controller
|
|||
$this->set('ajax', $this->request->is('ajax'));
|
||||
$this->request->getParam('prefix');
|
||||
$this->set('baseurl', Configure::read('App.fullBaseUrl'));
|
||||
$this->set('bsTheme', Configure::read('Cerebrate')['ui.bsTheme']);
|
||||
|
||||
if (!empty($user) && !empty($user->user_settings_by_name_with_fallback['ui.bsTheme']['value'])) {
|
||||
$this->set('bsTheme', $user->user_settings_by_name_with_fallback['ui.bsTheme']['value']);
|
||||
} else {
|
||||
$this->set('bsTheme', Configure::read('Cerebrate')['ui.bsTheme']);
|
||||
}
|
||||
|
||||
if ($this->modelClass == 'Tags.Tags') {
|
||||
$this->set('metaGroup', !empty($this->isAdmin) ? 'Administration' : 'Cerebrate');
|
||||
|
|
|
@ -13,7 +13,7 @@ class UserSettingsNavigation extends BaseNavigation
|
|||
if (!empty($request->getQuery('Users_id'))) {
|
||||
$user_id = h($request->getQuery('Users_id'));
|
||||
$linkData = [
|
||||
'label' => __('View user ({0})', h($user_id)),
|
||||
'label' => __('View user [{0}]', h($user_id)),
|
||||
'url' => sprintf('/users/view/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
|
@ -24,7 +24,7 @@ class UserSettingsNavigation extends BaseNavigation
|
|||
if (!empty($request->getQuery('Users_id'))) {
|
||||
$user_id = h($request->getQuery('Users_id'));
|
||||
$linkData = [
|
||||
'label' => __('Edit user ({0})', h($user_id)),
|
||||
'label' => __('Edit user [{0}]', h($user_id)),
|
||||
'url' => sprintf('/users/edit/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
|
|
|
@ -5,31 +5,83 @@ require_once(APP . 'Controller' . DS . 'Component' . DS . 'Navigation' . DS . 'b
|
|||
|
||||
class UsersNavigation extends BaseNavigation
|
||||
{
|
||||
public function addRoutes()
|
||||
{
|
||||
$this->bcf->addRoute('Users', 'settings', [
|
||||
'label' => __('User settings'),
|
||||
'url' => '/users/settings/',
|
||||
'icon' => 'user-cog'
|
||||
]);
|
||||
}
|
||||
|
||||
public function addParents()
|
||||
{
|
||||
// $this->bcf->addParent('Users', 'settings', 'Users', 'view');
|
||||
}
|
||||
|
||||
public function addLinks()
|
||||
{
|
||||
$bcf = $this->bcf;
|
||||
$request = $this->request;
|
||||
$this->bcf->addLink('Users', 'view', 'UserSettings', 'index', function ($config) use ($bcf, $request) {
|
||||
if (!empty($this->passedData[0])) {
|
||||
$user_id = $this->passedData[0];
|
||||
$passedData = $this->request->getParam('pass');
|
||||
$this->bcf->addLink('Users', 'view', 'UserSettings', 'index', function ($config) use ($bcf, $request, $passedData) {
|
||||
if (!empty($passedData[0])) {
|
||||
$user_id = $passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('User Setting ({0})', h($user_id)),
|
||||
'label' => __('Account settings', h($user_id)),
|
||||
'url' => sprintf('/users/settings/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
$this->bcf->addLink('Users', 'view', 'UserSettings', 'index', function ($config) use ($bcf, $request, $passedData) {
|
||||
if (!empty($passedData[0])) {
|
||||
$user_id = $passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('User Setting [{0}]', h($user_id)),
|
||||
'url' => sprintf('/user-settings/index?Users.id=%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
$this->bcf->addLink('Users', 'edit', 'UserSettings', 'index', function ($config) use ($bcf, $request) {
|
||||
if (!empty($this->passedData[0])) {
|
||||
$user_id = $this->passedData[0];
|
||||
$this->bcf->addLink('Users', 'edit', 'UserSettings', 'index', function ($config) use ($bcf, $request, $passedData) {
|
||||
if (!empty($passedData[0])) {
|
||||
$user_id = $passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('User Setting ({0})', h($user_id)),
|
||||
'label' => __('Account settings', h($user_id)),
|
||||
'url' => sprintf('/users/settings/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
$this->bcf->addLink('Users', 'edit', 'UserSettings', 'index', function ($config) use ($bcf, $request, $passedData) {
|
||||
if (!empty($passedData[0])) {
|
||||
$user_id = $passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('User Setting [{0}]', h($user_id)),
|
||||
'url' => sprintf('/user-settings/index?Users.id=%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
|
||||
$this->bcf->addLink('Users', 'settings', 'Users', 'view', function ($config) use ($bcf, $request, $passedData) {
|
||||
if (!empty($passedData[0])) {
|
||||
$user_id = $passedData[0];
|
||||
$linkData = [
|
||||
'label' => __('View user', h($user_id)),
|
||||
'url' => sprintf('/users/view/%s', h($user_id))
|
||||
];
|
||||
return $linkData;
|
||||
}
|
||||
return [];
|
||||
});
|
||||
$this->bcf->addSelfLink('Users', 'settings', [
|
||||
'label' => __('Account settings')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ class NavigationComponent extends Component
|
|||
public function getUserBookmarks(): array
|
||||
{
|
||||
$userSettingTable = TableRegistry::getTableLocator()->get('UserSettings');
|
||||
$setting = $userSettingTable->getSettingByName($this->request->getAttribute('identity'), 'ui.sidebar.bookmarks');
|
||||
$setting = $userSettingTable->getSettingByName($this->request->getAttribute('identity'), 'ui.bookmarks');
|
||||
$bookmarks = is_null($setting) ? [] : json_decode($setting->value, true);
|
||||
|
||||
$links = array_map(function($bookmark) {
|
||||
|
@ -316,11 +316,11 @@ class BreadcrumbFactory
|
|||
$this->endpoints[$sourceController][$sourceAction]['after'] = $parents;
|
||||
}
|
||||
|
||||
public function addSelfLink(string $controller, string $action)
|
||||
public function addSelfLink(string $controller, string $action, array $options=[])
|
||||
{
|
||||
$this->addLink($controller, $action, $controller, $action, [
|
||||
'selfLink' => true
|
||||
]);
|
||||
$this->addLink($controller, $action, $controller, $action, array_merge($options, [
|
||||
'selfLink' => true,
|
||||
]));
|
||||
}
|
||||
|
||||
public function addLink(string $sourceController, string $sourceAction, string $targetController, string $targetAction, $overrides = [])
|
||||
|
|
|
@ -117,7 +117,7 @@ class UserSettingsController extends AppController
|
|||
$this->render('view');
|
||||
}
|
||||
|
||||
public function setSetting($settingsName)
|
||||
public function setSetting($settingsName = false)
|
||||
{
|
||||
if (!$this->request->is('get')) {
|
||||
$setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $settingsName);
|
||||
|
@ -137,6 +137,39 @@ class UserSettingsController extends AppController
|
|||
$this->set('settingName', $settingsName);
|
||||
}
|
||||
|
||||
public function saveSetting()
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$data = $this->ParamHandler->harvestParams([
|
||||
'name',
|
||||
'value'
|
||||
]);
|
||||
$setting = $this->UserSettings->getSettingByName($this->ACL->getUser(), $data['name']);
|
||||
if (is_null($setting)) { // setting not found, create it
|
||||
$result = $this->UserSettings->createSetting($this->ACL->getUser(), $data['name'], $data['value']);
|
||||
} else {
|
||||
$result = $this->UserSettings->editSetting($this->ACL->getUser(), $data['name'], $data['value']);
|
||||
}
|
||||
$success = !empty($result);
|
||||
$message = $success ? __('Setting saved') : __('Could not save setting');
|
||||
$this->CRUD->setResponseForController('setSetting', $success, $message, $result);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getBookmarks($forSidebar=false)
|
||||
{
|
||||
$bookmarks = $this->UserSettings->getSettingByName($this->ACL->getUser(), $this->UserSettings->BOOKMARK_SETTING_NAME);
|
||||
$bookmarks = json_decode($bookmarks['value'], true);
|
||||
$this->set('user_id', $this->ACL->getUser()->id);
|
||||
$this->set('bookmarks', $bookmarks);
|
||||
$this->set('forSidebar', $forSidebar);
|
||||
$this->render('/element/UserSettings/saved-bookmarks');
|
||||
}
|
||||
|
||||
public function saveBookmark()
|
||||
{
|
||||
if (!$this->request->is('get')) {
|
||||
|
@ -152,4 +185,19 @@ class UserSettingsController extends AppController
|
|||
$this->set('user_id', $this->ACL->getUser()->id);
|
||||
}
|
||||
|
||||
public function deleteBookmark()
|
||||
{
|
||||
if (!$this->request->is('get')) {
|
||||
$result = $this->UserSettings->deleteBookmark($this->ACL->getUser(), $this->request->getData());
|
||||
$success = !empty($result);
|
||||
$message = $success ? __('Bookmark deleted') : __('Could not delete bookmark');
|
||||
$this->CRUD->setResponseForController('deleteBookmark', $success, $message, $result);
|
||||
$responsePayload = $this->CRUD->getResponsePayload();
|
||||
if (!empty($responsePayload)) {
|
||||
return $responsePayload;
|
||||
}
|
||||
}
|
||||
$this->set('user_id', $this->ACL->getUser()->id);
|
||||
}
|
||||
|
||||
}
|
|
@ -151,6 +151,11 @@ class UsersController extends AppController
|
|||
public function settings()
|
||||
{
|
||||
$this->set('user', $this->ACL->getUser());
|
||||
$all = $this->Users->UserSettings->getSettingsFromProviderForUser($this->ACL->getUser()['id'], true);
|
||||
$this->set('settingsProvider', $all['settingsProvider']);
|
||||
$this->set('settings', $all['settings']);
|
||||
$this->set('settingsFlattened', $all['settingsFlattened']);
|
||||
$this->set('notices', $all['notices']);
|
||||
}
|
||||
|
||||
public function register()
|
||||
|
|
|
@ -6,11 +6,14 @@ use App\Model\Entity\AppModel;
|
|||
use Cake\ORM\Entity;
|
||||
use Authentication\PasswordHasher\DefaultPasswordHasher;
|
||||
|
||||
require_once(APP . 'Model' . DS . 'Table' . DS . 'SettingProviders' . DS . 'UserSettingsProvider.php');
|
||||
use App\Settings\SettingsProvider\UserSettingsProvider;
|
||||
|
||||
class User extends AppModel
|
||||
{
|
||||
protected $_hidden = ['password', 'confirm_password'];
|
||||
|
||||
protected $_virtual = ['user_settings_by_name'];
|
||||
protected $_virtual = ['user_settings_by_name', 'user_settings_by_name_with_fallback'];
|
||||
|
||||
protected function _getUserSettingsByName()
|
||||
{
|
||||
|
@ -23,6 +26,22 @@ class User extends AppModel
|
|||
return $settingsByName;
|
||||
}
|
||||
|
||||
protected function _getUserSettingsByNameWithFallback()
|
||||
{
|
||||
if (!isset($this->SettingsProvider)) {
|
||||
$this->SettingsProvider = new UserSettingsProvider();
|
||||
}
|
||||
$settingsByNameWithFallback = [];
|
||||
if (!empty($this->user_settings)) {
|
||||
foreach ($this->user_settings as $i => $setting) {
|
||||
$settingsByNameWithFallback[$setting->name] = $setting->value;
|
||||
}
|
||||
}
|
||||
$settingsProvider = $this->SettingsProvider->getSettingsConfiguration($settingsByNameWithFallback);
|
||||
$settingsFlattened = $this->SettingsProvider->flattenSettingsConfiguration($settingsProvider);
|
||||
return $settingsFlattened;
|
||||
}
|
||||
|
||||
protected function _setPassword(string $password) : ?string
|
||||
{
|
||||
if (strlen($password) > 0) {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace App\Settings\SettingsProvider;
|
||||
|
||||
use Cake\ORM\TableRegistry;
|
||||
|
||||
require_once(APP . 'Model' . DS . 'Table' . DS . 'SettingProviders' . DS . 'BaseSettingsProvider.php');
|
||||
|
||||
use App\Settings\SettingsProvider\BaseSettingsProvider;
|
||||
|
||||
class UserSettingsProvider extends BaseSettingsProvider
|
||||
{
|
||||
protected function generateSettingsConfiguration()
|
||||
{
|
||||
return [
|
||||
__('Appearance') => [
|
||||
__('User Interface') => [
|
||||
'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'
|
||||
],
|
||||
'ui.sidebar.expanded' => [
|
||||
'name' => __('Sidebar expanded'),
|
||||
'type' => 'boolean',
|
||||
'description' => __('Should the left navigation sidebar expanded and locked.'),
|
||||
'default' => false,
|
||||
'severity' => 'info',
|
||||
],
|
||||
'ui.sidebar.include_bookmarks' => [
|
||||
'name' => __('Include bookmarks in the sidebar'),
|
||||
'type' => 'boolean',
|
||||
'description' => __('Should bookmarks links included in the sidebar.'),
|
||||
'default' => false,
|
||||
'severity' => 'info',
|
||||
],
|
||||
]
|
||||
],
|
||||
__('Account Security') => [
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
|
@ -6,8 +6,13 @@ use App\Model\Table\AppTable;
|
|||
use Cake\ORM\Table;
|
||||
use Cake\Validation\Validator;
|
||||
|
||||
require_once(APP . 'Model' . DS . 'Table' . DS . 'SettingProviders' . DS . 'UserSettingsProvider.php');
|
||||
use App\Settings\SettingsProvider\UserSettingsProvider;
|
||||
|
||||
class UserSettingsTable extends AppTable
|
||||
{
|
||||
protected $BOOKMARK_SETTING_NAME = 'ui.bookmarks';
|
||||
|
||||
public function initialize(array $config): void
|
||||
{
|
||||
parent::initialize($config);
|
||||
|
@ -16,6 +21,8 @@ class UserSettingsTable extends AppTable
|
|||
'Users'
|
||||
);
|
||||
$this->setDisplayField('name');
|
||||
|
||||
$this->SettingsProvider = new UserSettingsProvider();
|
||||
}
|
||||
|
||||
public function validationDefault(Validator $validator): Validator
|
||||
|
@ -27,6 +34,35 @@ class UserSettingsTable extends AppTable
|
|||
return $validator;
|
||||
}
|
||||
|
||||
public function getSettingsFromProviderForUser($user_id, $full = false): array
|
||||
{
|
||||
$settingsTmp = $this->getSettingsForUser($user_id)->toArray();
|
||||
$settings = [];
|
||||
foreach ($settingsTmp as $setting) {
|
||||
$settings[$setting->name] = $setting->value;
|
||||
}
|
||||
if (empty($full)) {
|
||||
return $settings;
|
||||
} else {
|
||||
$settingsProvider = $this->SettingsProvider->getSettingsConfiguration($settings);
|
||||
$settingsFlattened = $this->SettingsProvider->flattenSettingsConfiguration($settingsProvider);
|
||||
$notices = $this->SettingsProvider->getNoticesFromSettingsConfiguration($settingsProvider, $settings);
|
||||
return [
|
||||
'settings' => $settings,
|
||||
'settingsProvider' => $settingsProvider,
|
||||
'settingsFlattened' => $settingsFlattened,
|
||||
'notices' => $notices,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function getSettingsForUser($user_id)
|
||||
{
|
||||
return $this->find()->where([
|
||||
'user_id' => $user_id,
|
||||
])->all();
|
||||
}
|
||||
|
||||
public function getSettingByName($user, $name)
|
||||
{
|
||||
return $this->find()->where([
|
||||
|
@ -60,8 +96,7 @@ class UserSettingsTable extends AppTable
|
|||
|
||||
public function saveBookmark($user, $data)
|
||||
{
|
||||
$bookmarkSettingName = 'ui.sidebar.bookmarks';
|
||||
$setting = $this->getSettingByName($user, $bookmarkSettingName);
|
||||
$setting = $this->getSettingByName($user, $this->BOOKMARK_SETTING_NAME);
|
||||
$bookmarkData = [
|
||||
'label' => $data['bookmark_label'],
|
||||
'name' => $data['bookmark_name'],
|
||||
|
@ -69,12 +104,34 @@ class UserSettingsTable extends AppTable
|
|||
];
|
||||
if (is_null($setting)) { // setting not found, create it
|
||||
$bookmarksData = json_encode([$bookmarkData]);
|
||||
$result = $this->createSetting($user, $bookmarkSettingName, $bookmarksData);
|
||||
$result = $this->createSetting($user, $this->BOOKMARK_SETTING_NAME, $bookmarksData);
|
||||
} else {
|
||||
$bookmarksData = json_decode($setting->value);
|
||||
$bookmarksData[] = $bookmarkData;
|
||||
$bookmarksData = json_encode($bookmarksData);
|
||||
$result = $this->editSetting($user, $bookmarkSettingName, $bookmarksData);
|
||||
$result = $this->editSetting($user, $this->BOOKMARK_SETTING_NAME, $bookmarksData);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function deleteBookmark($user, $data)
|
||||
{
|
||||
$setting = $this->getSettingByName($user, $this->BOOKMARK_SETTING_NAME);
|
||||
$bookmarkData = [
|
||||
'name' => $data['bookmark_name'],
|
||||
'url' => $data['bookmark_url'],
|
||||
];
|
||||
if (is_null($setting)) { // Can't delete something that doesn't exist
|
||||
return null;
|
||||
} else {
|
||||
$bookmarksData = json_decode($setting->value, true);
|
||||
foreach ($bookmarksData as $i => $savedBookmark) {
|
||||
if ($savedBookmark['name'] == $bookmarkData['name'] && $savedBookmark['url'] == $bookmarkData['url']) {
|
||||
unset($bookmarksData[$i]);
|
||||
}
|
||||
}
|
||||
$bookmarksData = json_encode($bookmarksData);
|
||||
$result = $this->editSetting($user, $this->BOOKMARK_SETTING_NAME, $bookmarksData);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
|
|
@ -652,21 +652,21 @@ class BoostrapTable extends BootstrapGeneric {
|
|||
$key = $field;
|
||||
}
|
||||
$cellValue = Hash::get($row, $key);
|
||||
$html .= $this->genCell($cellValue, $field, $row);
|
||||
$html .= $this->genCell($cellValue, $field, $row, $i);
|
||||
}
|
||||
} else { // indexed array
|
||||
foreach ($row as $cellValue) {
|
||||
$html .= $this->genCell($cellValue, $field, $row);
|
||||
$html .= $this->genCell($cellValue, $field, $row, $i);
|
||||
}
|
||||
}
|
||||
$html .= $this->closeNode('tr');
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function genCell($value, $field=[], $row=[])
|
||||
private function genCell($value, $field=[], $row=[], $i=0)
|
||||
{
|
||||
if (isset($field['formatter'])) {
|
||||
$cellContent = $field['formatter']($value, $row);
|
||||
$cellContent = $field['formatter']($value, $row, $i);
|
||||
} else if (isset($field['element'])) {
|
||||
$cellContent = $this->btHelper->getView()->element($field['element'], [
|
||||
'data' => [$value],
|
||||
|
|
|
@ -1,29 +1,56 @@
|
|||
<?php
|
||||
// $Parsedown = new Parsedown();
|
||||
// echo $Parsedown->text($md);
|
||||
$bookmarks = !empty($loggedUser->user_settings_by_name['ui.bookmarks']['value']) ? json_decode($loggedUser->user_settings_by_name['ui.bookmarks']['value'], true) : []
|
||||
?>
|
||||
|
||||
<h2><?= __('Home') ?></h2>
|
||||
<h3>
|
||||
<?= $this->Bootstrap->icon('bookmark', [
|
||||
'class' => ['fa-fw']
|
||||
]); ?>
|
||||
<?= __('Bookmarks') ?>
|
||||
</h3>
|
||||
<div class="row">
|
||||
<?php foreach ($statistics as $modelName => $statistics): ?>
|
||||
<? if (!empty($bookmarks)): ?>
|
||||
<ul class="col-sm-12 col-md-10 col-l-8 col-xl-8 mb-3">
|
||||
<?php foreach ($bookmarks as $bookmark) : ?>
|
||||
<li class="list-group-item">
|
||||
<a href="<?= h($bookmark['url']) ?>" class="link-primary w-bold">
|
||||
<?= h($bookmark['label']) ?>
|
||||
</a>
|
||||
<span class="ms-3 fw-light"><?= h($bookmark['name']) ?></span>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php else: ?>
|
||||
<p class="fw-light"><?= __('No bookmarks') ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h3>
|
||||
<?= $this->Bootstrap->icon('chart-bar', [
|
||||
'class' => ['fa-fw']
|
||||
]); ?>
|
||||
<?= __('Activity') ?>
|
||||
</h3>
|
||||
<div class="row">
|
||||
<?php foreach ($statistics as $modelName => $statistics) : ?>
|
||||
<div class="col-sm-6 col-md-5 col-l-4 col-xl-3 mb-3">
|
||||
<?php
|
||||
$exploded = explode('.', $modelName);
|
||||
$modelForDisplay = $exploded[count($exploded)-1];
|
||||
$panelTitle = $this->Html->link(
|
||||
h($modelForDisplay),
|
||||
$this->Url->build([
|
||||
'controller' => $modelForDisplay,
|
||||
'action' => 'index',
|
||||
]),
|
||||
['class' => 'text-white text-decoration-none fw-light stretched-link']
|
||||
);
|
||||
echo $this->element('widgets/highlight-panel', [
|
||||
'titleHtml' => $panelTitle,
|
||||
'number' => $statistics['amount'],
|
||||
'variation' => $statistics['variation'] ?? '',
|
||||
'chartData' => $statistics['timeline'] ?? []
|
||||
]);
|
||||
$exploded = explode('.', $modelName);
|
||||
$modelForDisplay = $exploded[count($exploded) - 1];
|
||||
$panelTitle = $this->Html->link(
|
||||
h($modelForDisplay),
|
||||
$this->Url->build([
|
||||
'controller' => $modelForDisplay,
|
||||
'action' => 'index',
|
||||
]),
|
||||
['class' => 'text-white text-decoration-none fw-light stretched-link']
|
||||
);
|
||||
echo $this->element('widgets/highlight-panel', [
|
||||
'titleHtml' => $panelTitle,
|
||||
'number' => $statistics['amount'],
|
||||
'variation' => $statistics['variation'] ?? '',
|
||||
'chartData' => $statistics['timeline'] ?? []
|
||||
]);
|
||||
?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', [
|
||||
'data' => [
|
||||
'description' => __('Authkeys are used for API access. A user can have more than one authkey, so if you would like to use separate keys per tool that queries Cerebrate, add additional keys. Use the comment field to make identifying your keys easier.'),
|
||||
'description' => __('Application setting form'),
|
||||
'fields' => [
|
||||
[
|
||||
'field' => 'name',
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', [
|
||||
'data' => [
|
||||
'title' => __('Delete a bookmark'),
|
||||
'description' => __('Specify the name and the URL of the bookmark to be deleted from your user profile.'),
|
||||
'model' => 'UserSettings',
|
||||
'fields' => [
|
||||
[
|
||||
'field' => 'bookmark_name',
|
||||
'label' => __('Name'),
|
||||
'placeholder' => __('Home page'),
|
||||
],
|
||||
[
|
||||
'field' => 'bookmark_url',
|
||||
'label' => __('URL'),
|
||||
'placeholder' => '/instance/home',
|
||||
],
|
||||
],
|
||||
'submit' => [
|
||||
'action' => $this->request->getParam('action')
|
||||
]
|
||||
],
|
||||
]);
|
||||
?>
|
||||
</div>
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
echo $this->element('genericElements/Form/genericForm', [
|
||||
'data' => [
|
||||
'description' => __('User settings form'),
|
||||
'fields' => [
|
||||
[
|
||||
'field' => 'name',
|
||||
],
|
||||
[
|
||||
'field' => 'value'
|
||||
],
|
||||
],
|
||||
'submit' => [
|
||||
'action' => $this->request->getParam('action')
|
||||
]
|
||||
]
|
||||
]);
|
|
@ -11,6 +11,7 @@ $variantFromSeverity = [
|
|||
'warning' => 'warning',
|
||||
'info' => 'info',
|
||||
];
|
||||
$this->set('variantFromSeverity', $variantFromSeverity);
|
||||
$includeScrollspy = !empty($includeScrollspy);
|
||||
|
||||
$groupedContent = [];
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
$forSidebar = !empty($forSidebar);
|
||||
|
||||
$table = $this->Bootstrap->table([
|
||||
'hover' => false,
|
||||
], [
|
||||
'fields' => [
|
||||
['key' => 'label', 'label' => __('Label')],
|
||||
['key' => 'name', 'label' => __('Name')],
|
||||
['key' => 'url', 'label' => __('URL'), 'formatter' => function ($value, $row) {
|
||||
return sprintf('<span class="font-monospace">%s</span>', h($value));
|
||||
}],
|
||||
['key' => 'action', 'label' => __('Action'), 'formatter' => function ($value, $row, $index) {
|
||||
return $this->Bootstrap->button([
|
||||
'icon' => 'trash',
|
||||
'variant' => 'danger',
|
||||
'size' => 'sm',
|
||||
'params' => [
|
||||
'onclick' => sprintf('deleteBookmark(window.bookmarks[%s])', $index),
|
||||
]
|
||||
]);
|
||||
}],
|
||||
],
|
||||
'items' => $bookmarks,
|
||||
'caption' => empty($bookmarks) ? __('No bookmark saved') : ''
|
||||
]);
|
||||
?>
|
||||
|
||||
<?php if (!empty($forSidebar)) : ?>
|
||||
<li class="bookmarks">
|
||||
<?php foreach ($bookmarks as $parentName => $entry) : ?>
|
||||
<?= $this->element('layouts/sidebar/bookmark-entry', [
|
||||
'entry' => $entry,
|
||||
])
|
||||
?>
|
||||
<?php endforeach; ?>
|
||||
<?= $this->element('layouts/sidebar/bookmark-add') ?>
|
||||
</li>
|
||||
<?php else : ?>
|
||||
<div class="bookmark-table-container m-2">
|
||||
<button class="btn btn-primary mb-2" onclick="openSaveBookmarkModal()">
|
||||
<?= __('Create bookmark') ?>
|
||||
</button>
|
||||
<?= $table ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.bookmarks = <?= json_encode($bookmarks) ?>;
|
||||
</script>
|
||||
<?php endif; ?>
|
|
@ -15,7 +15,7 @@ use Cake\Routing\Router;
|
|||
</div>
|
||||
</h6>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="<?= Router::url(['controller' => 'users', 'action' => 'view', 'plugin' => null]) ?>">
|
||||
<a class="dropdown-item" href="<?= Router::url(['controller' => 'users', 'action' => 'view', 'plugin' => null, h($this->request->getAttribute('identity')['id'])]) ?>">
|
||||
<i class="me-1 <?= $this->FontAwesome->getClass('user-circle') ?>"></i>
|
||||
<?= __('My Account') ?>
|
||||
</a>
|
||||
|
@ -24,7 +24,7 @@ use Cake\Routing\Router;
|
|||
href="<?= Router::url(['controller' => 'users', 'action' => 'settings', 'plugin' => null, h($this->request->getAttribute('identity')['id'])]) ?>"
|
||||
>
|
||||
<i class="me-1 <?= $this->FontAwesome->getClass('user-cog') ?>"></i>
|
||||
<?= __('Settings') ?>
|
||||
<?= __('Account Settings') ?>
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item dropdown-item-outline-danger" href="<?= Router::url(['controller' => 'users', 'action' => 'logout', 'plugin' => null]) ?>">
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<?php
|
||||
$bookmarkIncluded = $loggedUser->user_settings_by_name_with_fallback['ui.sidebar.include_bookmarks']['value'];
|
||||
?>
|
||||
<div class="sidebar-wrapper d-flex flex-column">
|
||||
<div class="sidebar-scroll">
|
||||
<div class="sidebar-content">
|
||||
<ul class="sidebar-elements">
|
||||
<?php foreach ($menu as $category => $categorized) : ?>
|
||||
<?php if ($category == '__bookmarks') : ?>
|
||||
<?= $this->element('layouts/sidebar/category', ['label' => __('Bookmarks'), 'class' => 'bookmark-categ']) ?>
|
||||
<li class="bookmarks">
|
||||
<?php foreach ($categorized as $parentName => $entry) : ?>
|
||||
<?= $this->element('layouts/sidebar/bookmark-entry', [
|
||||
'entry' => $entry,
|
||||
])
|
||||
?>
|
||||
<?php endforeach; ?>
|
||||
<?= $this->element('layouts/sidebar/bookmark-add') ?>
|
||||
</li>
|
||||
<?php else : ?>
|
||||
<?php if ($bookmarkIncluded) : ?>
|
||||
<?= $this->element('layouts/sidebar/category', ['label' => __('Bookmarks'), 'class' => 'bookmark-categ']) ?>
|
||||
<?= $this->element('UserSettings/saved-bookmarks', [
|
||||
'bookmarks' => $categorized,
|
||||
'forSidebar' => true,
|
||||
]) ?>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<?= $this->element('layouts/sidebar/category', ['label' => $category]) ?>
|
||||
<?php foreach ($categorized as $parentName => $parent) : ?>
|
||||
<?= $this->element('layouts/sidebar/entry', [
|
||||
|
|
|
@ -5,6 +5,7 @@ echo $this->Bootstrap->button([
|
|||
'title' => __('Add new bookmark'),
|
||||
'variant' => 'primary',
|
||||
'size' => 'sm',
|
||||
'class' => 'mb-1',
|
||||
'params' => [
|
||||
'id' => 'btn-add-bookmark',
|
||||
]
|
||||
|
|
|
@ -17,7 +17,7 @@ use Cake\Core\Configure;
|
|||
|
||||
$cakeDescription = 'Cerebrate';
|
||||
|
||||
$sidebarOpen = $loggedUser->user_settings_by_name['ui.sidebar.expanded']->value;
|
||||
$sidebarOpen = $loggedUser->user_settings_by_name_with_fallback['ui.sidebar.expanded']['value'];
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
|
|
@ -152,6 +152,49 @@ function focusSearchResults(evt) {
|
|||
}
|
||||
}
|
||||
|
||||
function openSaveBookmarkModal(bookmark_url = '') {
|
||||
const url = '/user-settings/saveBookmark';
|
||||
UI.submissionModal(url).then(([modalFactory, ajaxApi]) => {
|
||||
const $input = modalFactory.$modal.find('input[name="bookmark_url"]')
|
||||
$input.val(bookmark_url)
|
||||
})
|
||||
}
|
||||
|
||||
function deleteBookmark(bookmark, forSidebar=false) {
|
||||
const url = '/user-settings/deleteBookmark'
|
||||
AJAXApi.quickFetchAndPostForm(url, {
|
||||
bookmark_name: bookmark.name,
|
||||
bookmark_url: bookmark.url,
|
||||
}, {
|
||||
provideFeedback: true,
|
||||
statusNode: $('.bookmark-table-container'),
|
||||
}).then((apiResult) => {
|
||||
const url = `/userSettings/getBookmarks/${forSidebar ? '1' : '0'}`
|
||||
UI.reload(url, $('.bookmark-table-container').parent())
|
||||
const theToast = UI.toast({
|
||||
variant: 'success',
|
||||
title: apiResult.message,
|
||||
bodyHtml: $('<div/>').append(
|
||||
$('<span/>').text('Cancel deletion operation.'),
|
||||
$('<button/>').addClass(['btn', 'btn-primary', 'btn-sm', 'ms-3']).text('Restore bookmark').click(function () {
|
||||
const urlRestore = '/user-settings/saveBookmark'
|
||||
AJAXApi.quickFetchAndPostForm(urlRestore, {
|
||||
bookmark_label: bookmark.label,
|
||||
bookmark_name: bookmark.name,
|
||||
bookmark_url: bookmark.url,
|
||||
}, {
|
||||
provideFeedback: true,
|
||||
statusNode: $('.bookmark-table-container')
|
||||
}).then(() => {
|
||||
const url = `/userSettings/getBookmarks/${forSidebar ? '1' : '0'}`
|
||||
UI.reload(url, $('.bookmark-table-container').parent())
|
||||
})
|
||||
}),
|
||||
),
|
||||
})
|
||||
}).catch((e) => { })
|
||||
}
|
||||
|
||||
var UI
|
||||
$(document).ready(() => {
|
||||
if (typeof UIFactory !== "undefined") {
|
||||
|
@ -179,10 +222,6 @@ $(document).ready(() => {
|
|||
})
|
||||
|
||||
$('.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)
|
||||
})
|
||||
openSaveBookmarkModal(window.location.pathname)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue