From e89cb2547e49a3bf669bf3c4a82f47da996b124e Mon Sep 17 00:00:00 2001 From: yuri Date: Fri, 17 Aug 2018 14:20:24 +0300 Subject: [PATCH] preferences: ability to reset dashboard to default --- application/Espo/Controllers/Preferences.php | 44 ++++++++++++++++++- .../Resources/i18n/en_US/Preferences.json | 3 +- .../Resources/metadata/app/aclPortal.json | 3 +- client/src/views/main.js | 4 +- client/src/views/preferences/record/edit.js | 40 ++++++++++++++--- client/src/views/record/base.js | 4 ++ client/src/views/record/detail.js | 36 ++++++++++++++- 7 files changed, 119 insertions(+), 15 deletions(-) diff --git a/application/Espo/Controllers/Preferences.php b/application/Espo/Controllers/Preferences.php index 73a5c3cb98..03f01ba179 100644 --- a/application/Espo/Controllers/Preferences.php +++ b/application/Espo/Controllers/Preferences.php @@ -88,7 +88,7 @@ class Preferences extends \Espo\Core\Controllers\Base throw new BadRequest(); } - if ($this->getAcl()->getLevel('Preferences', 'read') === 'no') { + if ($this->getAcl()->getLevel('Preferences', 'edit') === 'no') { throw new Forbidden(); } @@ -142,5 +142,45 @@ class Preferences extends \Espo\Core\Controllers\Base return $entity->getValueMap(); } -} + public function postActionResetDashboard($params, $data) + { + if (empty($data->id)) throw new BadRequest(); + + $userId = $data->id; + + $this->handleUserAccess($userId); + + $user = $this->getEntityManager()->getEntity('User', $userId); + $preferences = $this->getEntityManager()->getEntity('Preferences', $userId); + if (!$user) throw new NotFound(); + if (!$preferences) throw new NotFound(); + + if ($user->isPortal()) throw new Forbidden(); + + if ($this->getAcl()->getLevel('Preferences', 'edit') === 'no') { + throw new Forbidden(); + } + + $forbiddenAttributeList = $this->getAcl()->getScopeForbiddenAttributeList('Preferences', 'edit'); + + if (in_array('dashboardLayout', $forbiddenAttributeList)) { + throw new Forbidden(); + } + + $dashboardLayout = $this->getConfig()->get('dashboardLayout'); + $dashletsOptions = $this->getConfig()->get('dashletsOptions'); + + $preferences->set([ + 'dashboardLayout' => $dashboardLayout, + 'dashletsOptions' => $dashletsOptions + ]); + + $this->getEntityManager()->saveEntity($preferences); + + return (object) [ + 'dashboardLayout' => $preferences->get('dashboardLayout'), + 'dashletsOptions' => $preferences->get('dashletsOptions') + ]; + } +} diff --git a/application/Espo/Resources/i18n/en_US/Preferences.json b/application/Espo/Resources/i18n/en_US/Preferences.json index 0e1a3e2cac..43217a0410 100644 --- a/application/Espo/Resources/i18n/en_US/Preferences.json +++ b/application/Espo/Resources/i18n/en_US/Preferences.json @@ -37,7 +37,8 @@ "followCreatedEntityTypeList": "Auto-follow created records of specific entity types", "emailUseExternalClient": "Use an external email client", "scopeColorsDisabled": "Disable scope colors", - "tabColorsDisabled": "Disable tab colors" + "tabColorsDisabled": "Disable tab colors", + "Reset Dashboard to Default": "Reset Dashboard to Default" }, "links": { }, diff --git a/application/Espo/Resources/metadata/app/aclPortal.json b/application/Espo/Resources/metadata/app/aclPortal.json index 56f18e7156..69c3d73a84 100644 --- a/application/Espo/Resources/metadata/app/aclPortal.json +++ b/application/Espo/Resources/metadata/app/aclPortal.json @@ -66,7 +66,8 @@ "doNotFillAssignedUserIfNotRequired": false, "useCustomTabList": false, "tabList": false, - "emailUseExternalClient": false + "emailUseExternalClient": false, + "dashboardLayout": false }, "Call": { "reminders": false diff --git a/client/src/views/main.js b/client/src/views/main.js index 5b9d567c97..bbf06c8135 100644 --- a/client/src/views/main.js +++ b/client/src/views/main.js @@ -156,11 +156,11 @@ Espo.define('views/main', 'view', function (Dep) { }, disableMenuItem: function (name) { - this.$el.find('.header .header-buttons [data-name="'+name+'"]').addClass('disabled'); + this.$el.find('.header .header-buttons [data-name="'+name+'"]').addClass('disabled').attr('disabled'); }, enableMenuItem: function (name) { - this.$el.find('.header .header-buttons [data-name="'+name+'"]').removeClass('disabled'); + this.$el.find('.header .header-buttons [data-name="'+name+'"]').removeClass('disabled').removeAttr('disabled'); }, removeMenuItem: function (name, doNotReRender) { diff --git a/client/src/views/preferences/record/edit.js b/client/src/views/preferences/record/edit.js index 4fe1f75ade..e0a8155eb3 100644 --- a/client/src/views/preferences/record/edit.js +++ b/client/src/views/preferences/record/edit.js @@ -82,13 +82,20 @@ Espo.define('views/preferences/record/edit', 'views/record/edit', function (Dep) setup: function () { Dep.prototype.setup.call(this); - this.buttonList.push( - { - name: 'reset', - html: this.getLanguage().translate('Reset to Default', 'labels', 'Admin'), - style: 'danger' - } - ); + this.addButton({ + name: 'reset', + html: this.getLanguage().translate('Reset to Default', 'labels', 'Admin'), + style: 'danger' + }); + + var forbiddenEditFieldList = this.getAcl().getScopeForbiddenFieldList('Preferences', 'edit'); + + if (!~forbiddenEditFieldList.indexOf('dashboardLayout')) { + this.addDropdownItem({ + name: 'resetDashboard', + html: this.getLanguage().translate('Reset Dashboard to Default', 'labels', 'Preferences') + }); + } if (this.model.get('isPortalUser')) { this.layoutName = 'detailPortal'; @@ -198,6 +205,25 @@ Espo.define('views/preferences/record/edit', 'views/record/edit', function (Dep) }).done(function (data) { Espo.Ui.success(this.translate('resetPreferencesDone', 'messages')); this.model.set(data); + for (var attribute in data) { + this.setInitalAttributeValue(attribute, data[attribute]); + } + this.getPreferences().set(this.model.toJSON()); + this.getPreferences().trigger('update'); + }.bind(this)); + }, this); + }, + + actionResetDashboard: function () { + this.confirm(this.translate('confirmation', 'messages'), function () { + this.ajaxPostRequest('Preferences/action/resetDashboard', { + id: this.model.id + }).done(function (data) { + Espo.Ui.success(this.translate('Done')); + this.model.set(data); + for (var attribute in data) { + this.setInitalAttributeValue(attribute, data[attribute]); + } this.getPreferences().set(this.model.toJSON()); this.getPreferences().trigger('update'); }.bind(this)); diff --git a/client/src/views/record/base.js b/client/src/views/record/base.js index f89d829c5a..dcb53e4c9b 100644 --- a/client/src/views/record/base.js +++ b/client/src/views/record/base.js @@ -317,6 +317,10 @@ Espo.define('views/record/base', ['view', 'view-record-helper', 'dynamic-logic'] this.initDynamicLogic(); }, + setInitalAttributeValue: function (attribute, value) { + this.attributes[attribute] = value; + }, + checkAttributeIsChanged: function (name) { return !_.isEqual(this.attributes[name], this.model.get(name)); }, diff --git a/client/src/views/record/detail.js b/client/src/views/record/detail.js index 4e80b0e2eb..24148711ea 100644 --- a/client/src/views/record/detail.js +++ b/client/src/views/record/detail.js @@ -253,6 +253,14 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'], } }, + disableActionItems: function () { + this.disableButtons(); + }, + + enableActionItems: function () { + this.enableButtons(); + }, + hideActionItem: function (name) { for (var i in this.buttonList) { if (this.buttonList[i].name == name) { @@ -1065,12 +1073,36 @@ Espo.define('views/record/detail', ['views/record/base', 'view-record-helper'], this.manageAccessDelete(); }, + addButton: function (o) { + var name = o.name; + if (!name) return; + for (var i in this.buttonList) { + if (this.buttonList[i].name == name) { + return; + } + } + this.buttonList.push(o); + }, + + addDropdownItem: function (o) { + var name = o.name; + if (!name) return; + for (var i in this.dropdownItemList) { + if (this.dropdownItemList[i].name == name) { + return; + } + } + this.dropdownItemList.push(o); + }, + enableButtons: function () { - this.$el.find(".button-container button").removeAttr('disabled'); + this.$el.find(".button-container .action").removeAttr('disabled').removeClass('disabled'); + this.$el.find(".button-container .dropdown-toggle").removeAttr('disabled').removeClass('disabled'); }, disableButtons: function () { - this.$el.find(".button-container button").attr('disabled', 'disabled'); + this.$el.find(".button-container .action").attr('disabled', 'disabled').addClass('disabled'); + this.$el.find(".button-container .dropdown-toggle").attr('disabled', 'disabled').addClass('disabled'); }, removeButton: function (name) {