From 2d385c163fcba4544ac461932aa8544e0778f8ba Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 5 Nov 2020 14:12:57 +0200 Subject: [PATCH] entity manager page --- .../Resources/i18n/en_US/EntityManager.json | 1 + .../templates/admin/entity-manager/index.tpl | 60 ++---- .../templates/admin/entity-manager/scope.tpl | 113 ++++++++++ .../templates/admin/field-manager/index.tpl | 2 +- .../templates/admin/link-manager/index.tpl | 7 +- client/src/controllers/admin.js | 8 +- .../src/views/admin/entity-manager/index.js | 37 ++-- .../entity-manager/modals/edit-entity.js | 5 +- .../entity-manager/modals/edit-formula.js | 2 +- .../src/views/admin/entity-manager/scope.js | 203 ++++++++++++++++++ client/src/views/admin/layouts/index.js | 6 +- frontend/less/espo/elements/buttons.less | 6 + 12 files changed, 375 insertions(+), 75 deletions(-) create mode 100644 client/res/templates/admin/entity-manager/scope.tpl create mode 100644 client/src/views/admin/entity-manager/scope.js diff --git a/application/Espo/Resources/i18n/en_US/EntityManager.json b/application/Espo/Resources/i18n/en_US/EntityManager.json index 665a68c93a..7a0f513c81 100644 --- a/application/Espo/Resources/i18n/en_US/EntityManager.json +++ b/application/Espo/Resources/i18n/en_US/EntityManager.json @@ -64,6 +64,7 @@ } }, "messages": { + "confirmRemove": "Are you sure you want to remove the entity type from the system?", "entityCreated": "Entity has been created", "linkAlreadyExists": "Link name conflict.", "linkConflict": "Name conflict: link or field with the same name already exists." diff --git a/client/res/templates/admin/entity-manager/index.tpl b/client/res/templates/admin/entity-manager/index.tpl index 0b888cb4d9..31c29cab4f 100644 --- a/client/res/templates/admin/entity-manager/index.tpl +++ b/client/res/templates/admin/entity-manager/index.tpl @@ -3,73 +3,43 @@ {{translate 'Entity Manager' scope='Admin'}}
- +
+
+
- - - - {{#each scopeDataList}} - - - - - - - {{/each}}
{{translate 'name' scope='EntityManager' category='fields'}} {{translate 'label' scope='EntityManager' category='fields'}} {{translate 'type' scope='EntityManager' category='fields'}}    
+ + {{#if customizable}} + {{name}} + {{else}} {{name}} + {{/if}} + {{label}} + {{#if type}} {{translateOption type field='type' scope='EntityManager'}} {{/if}} - {{#if customizable}} - {{translate 'Fields' scope='EntityManager'}} - {{/if}} - - {{#if customizable}} - {{translate 'Relationships' scope='EntityManager'}} - {{/if}} - - {{#if customizable}} - - {{translate 'Edit'}} - - {{/if}} - - {{#if customizable}} -
- - -
- {{/if}} -
+
+
diff --git a/client/res/templates/admin/entity-manager/scope.tpl b/client/res/templates/admin/entity-manager/scope.tpl new file mode 100644 index 0000000000..e408982f11 --- /dev/null +++ b/client/res/templates/admin/entity-manager/scope.tpl @@ -0,0 +1,113 @@ + + +
+
+ + {{#if isRemovable}} + + + {{/if}} +
+
+ +
+
+
+
+
+
+
+ +
+ {{scope}} +
+
+ {{#if type}} +
+ +
+ {{type}} +
+
+ {{/if}} +
+
+
+ +
+ {{label}} +
+
+
+
+
+
+
+
+
+ {{#if isCustomizable}} + + {{/if}} +
+
+ {{#if isCustomizable}} + + {{/if}} +
+
+ {{#if hasLayouts}} + + {{/if}} +
+
+
+
+ {{#if isCustomizable}} + + {{/if}} +
+
+
+
+
+
+
+ diff --git a/client/res/templates/admin/field-manager/index.tpl b/client/res/templates/admin/field-manager/index.tpl index fc7737140e..4ec84c832b 100644 --- a/client/res/templates/admin/field-manager/index.tpl +++ b/client/res/templates/admin/field-manager/index.tpl @@ -4,7 +4,7 @@ {{translate 'Entity Manager' scope='Admin'}} - {{translate scope category='scopeNames'}} + {{translate scope category='scopeNames'}} {{translate 'Fields' scope='EntityManager'}} diff --git a/client/res/templates/admin/link-manager/index.tpl b/client/res/templates/admin/link-manager/index.tpl index e5f9bc0f3e..6219ef62e1 100644 --- a/client/res/templates/admin/link-manager/index.tpl +++ b/client/res/templates/admin/link-manager/index.tpl @@ -4,14 +4,17 @@ {{translate 'Entity Manager' scope='Admin'}} - {{translate scope category='scopeNames'}} + {{translate scope category='scopeNames'}} {{translate 'Relationships' scope='EntityManager'}}
- +
diff --git a/client/src/controllers/admin.js b/client/src/controllers/admin.js index bedd8540ca..2d943739f0 100644 --- a/client/src/controllers/admin.js +++ b/client/src/controllers/admin.js @@ -87,7 +87,13 @@ define('controllers/admin', ['controller', 'search-manager'], function (Dep, Sea actionEntityManager: function (options) { var scope = options.scope || null; - this.main('views/admin/entity-manager/index', {scope: scope}); + if (scope) { + this.main('views/admin/entity-manager/scope', {scope: scope}); + + return; + } + + this.main('views/admin/entity-manager/index'); }, actionLinkManager: function (options) { diff --git a/client/src/views/admin/entity-manager/index.js b/client/src/views/admin/entity-manager/index.js index a8d99dbe2a..2c86513b2d 100644 --- a/client/src/views/admin/entity-manager/index.js +++ b/client/src/views/admin/entity-manager/index.js @@ -39,28 +39,27 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { data: function () { return { scopeDataList: this.scopeDataList, - scope: this.scope, }; }, events: { - 'click a[data-action="editEntity"]': function (e) { + /*'click a[data-action="editEntity"]': function (e) { var scope = $(e.currentTarget).data('scope'); this.editEntity(scope); }, 'click [data-action="editFormula"]': function (e) { var scope = $(e.currentTarget).data('scope'); this.editFormula(scope); - }, + },*/ 'click button[data-action="createEntity"]': function (e) { this.createEntity(); }, - 'click [data-action="removeEntity"]': function (e) { + /*'click [data-action="removeEntity"]': function (e) { var scope = $(e.currentTarget).data('scope'); this.confirm(this.translate('confirmation', 'messages'), function () { this.removeEntity(scope); }, this); - } + }*/ }, setupScopeData: function () { @@ -78,6 +77,7 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { scopeListSorted.push(scope); } }, this); + scopeList.forEach(function (scope) { var d = this.getMetadata().get('scopes.' + scope); if (d.entity && !d.customizable) { @@ -109,8 +109,6 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { }, setup: function () { - this.scope = this.options.scope || null; - this.setupScopeData(); }, @@ -118,10 +116,9 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { this.createView('edit', 'views/admin/entity-manager/modals/edit-entity', {}, function (view) { view.render(); - this.listenTo(view, 'after:save', function () { + this.listenTo(view, 'after:save', function (o) { this.clearView('edit'); - this.setupScopeData(); - this.render(); + this.getRouter().navigate('#Admin/entityManager/scope=' + o.scope, {trigger: true}); }, this); this.listenTo(view, 'close', function () { @@ -130,7 +127,7 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { }, this); }, - editEntity: function (scope) { + /*editEntity: function (scope) { this.createView('edit', 'views/admin/entity-manager/modals/edit-entity', { scope: scope, }, function (view) { @@ -154,7 +151,7 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { { name: 'close', label: this.translate('Close'), - } + }, ], }, function (view) { view.render(); @@ -166,14 +163,14 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { this.clearView('edit'); }, this); }, this); - }, + },*/ - removeEntity: function (scope) { + /*removeEntity: function (scope) { $.ajax({ url: 'EntityManager/action/removeEntity', type: 'POST', data: JSON.stringify({ - name: scope + name: scope, }) }).done(function () { this.$el.find('table tr[data-scope="'+scope+'"]').remove(); @@ -184,11 +181,11 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { }.bind(this), true); }.bind(this), true); }.bind(this)); - }, + },*/ - editFormula: function (scope) { + /*editFormula: function (scope) { this.createView('edit', 'views/admin/entity-manager/modals/edit-formula', { - scope: scope + scope: scope, }, function (view) { view.render(); @@ -200,12 +197,10 @@ define('views/admin/entity-manager/index', 'view', function (Dep) { this.clearView('edit'); }, this); }, this); - }, + },*/ updatePageTitle: function () { this.setPageTitle(this.getLanguage().translate('Entity Manager', 'labels', 'Admin')); }, }); }); - - diff --git a/client/src/views/admin/entity-manager/modals/edit-entity.js b/client/src/views/admin/entity-manager/modals/edit-entity.js index f73b5d7135..42682b868c 100644 --- a/client/src/views/admin/entity-manager/modals/edit-entity.js +++ b/client/src/views/admin/entity-manager/modals/edit-entity.js @@ -485,7 +485,7 @@ define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'model'] 'stream', 'disabled', 'statusField', - 'iconClass' + 'iconClass', ]; if (this.scope) { @@ -608,7 +608,8 @@ define('views/admin/entity-manager/modals/edit-entity', ['views/modal', 'model'] function () { var rebuildRequired = data.fullTextSearch && !fetchedAttributes.fullTextSearch; var o = { - rebuildRequired: rebuildRequired + rebuildRequired: rebuildRequired, + scope: name, }; this.trigger('after:save', o); }.bind(this) diff --git a/client/src/views/admin/entity-manager/modals/edit-formula.js b/client/src/views/admin/entity-manager/modals/edit-formula.js index a78c050169..9494e76db3 100644 --- a/client/src/views/admin/entity-manager/modals/edit-formula.js +++ b/client/src/views/admin/entity-manager/modals/edit-formula.js @@ -26,7 +26,7 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -Espo.define('views/admin/entity-manager/modals/edit-formula', ['views/modal', 'model'], function (Dep, Model) { +define('views/admin/entity-manager/modals/edit-formula', ['views/modal', 'model'], function (Dep, Model) { return Dep.extend({ diff --git a/client/src/views/admin/entity-manager/scope.js b/client/src/views/admin/entity-manager/scope.js new file mode 100644 index 0000000000..452246813f --- /dev/null +++ b/client/src/views/admin/entity-manager/scope.js @@ -0,0 +1,203 @@ +/************************************************************************ + * This file is part of EspoCRM. + * + * EspoCRM - Open Source CRM application. + * Copyright (C) 2014-2020 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko + * Website: https://www.espocrm.com + * + * EspoCRM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * EspoCRM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EspoCRM. If not, see http://www.gnu.org/licenses/. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU General Public License version 3. + * + * In accordance with Section 7(b) of the GNU General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +define('views/admin/entity-manager/scope', 'view', function (Dep) { + + return Dep.extend({ + + template: 'admin/entity-manager/scope', + + scope: null, + + data: function () { + return { + scope: this.scope, + isRemovable: this.isRemovable, + isCustomizable: this.isCustomizable, + type: this.type, + hasLayouts: this.hasLayouts, + label: this.label, + }; + }, + + events: { + 'click [data-action="editEntity"]': function (e) { + this.editEntity(); + }, + 'click [data-action="editFormula"]': function (e) { + this.editFormula(); + + }, + 'click [data-action="removeEntity"]': function (e) { + this.removeEntity(); + }, + }, + + setup: function () { + this.scope = this.options.scope; + + this.setupScopeData(); + }, + + setupScopeData: function () { + var scopeData = this.getMetadata().get(['scopes', this.scope]); + + if (!scopeData) { + throw new Espo.Exceptions.NotFound(); + } + + this.isRemovable = !!scopeData.isCustom; + + if (scopeData.isNotRemovable) { + this.isRemovable = false; + } + + this.isCustomizable = !!scopeData.customizable; + + this.type = scopeData.type; + + this.hasLayouts = scopeData.layouts; + + this.label = this.getLanguage().translate(this.scope, 'scopeNames'); + }, + + editEntity: function () { + this.createView('edit', 'views/admin/entity-manager/modals/edit-entity', { + scope: this.scope, + }, function (view) { + view.render(); + + this.listenTo(view, 'after:save', function (o) { + this.clearView('edit'); + + this.setupScopeData(); + + this.reRender(); + + if (o.rebuildRequired) { + this.createView('dialog', 'views/modal', { + templateContent: + "{{complexText viewObject.options.msg}}" + + "{{complexText viewObject.options.msgRebuild}}", + headerText: this.translate('rebuildRequired', 'strings', 'Admin'), + backdrop: 'static', + msg: this.translate('rebuildRequired', 'messages', 'Admin'), + msgRebuild: '```php rebuild.php```', + buttonList: [ + { + name: 'close', + label: this.translate('Close'), + }, + ], + }, function (view) { + view.render(); + }); + } + }, this); + + this.listenTo(view, 'close', function () { + this.clearView('edit'); + }, this); + + }, this); + }, + + removeEntity: function () { + var scope = this.scope; + + this.confirm(this.translate('confirmRemove', 'messages', 'EntityManager'), function () { + + Espo.Ui.notify( + this.translate('pleaseWait', 'messages') + ); + + this.disableButtons(); + + Espo.Ajax.postRequest('EntityManager/action/removeEntity', { + name: scope, + }) + .then( + function () { + this.getMetadata().load(function () { + this.getConfig().load(function () { + Espo.Ui.notify(false); + + this.getRouter().navigate('#Admin/entityManager', {trigger: true}); + }.bind(this), true); + }.bind(this), true); + }.bind(this) + ) + .fail( + function () { + this.enableButtons(); + }.bind(this) + ); + + }.bind(this)); + }, + + afterRender: function () { + + }, + + editFormula: function (scope) { + var scope = this.scope; + + this.createView('edit', 'views/admin/entity-manager/modals/edit-formula', { + scope: scope, + }, function (view) { + view.render(); + + this.listenTo(view, 'after:save', function () { + this.clearView('edit'); + }, this); + + this.listenTo(view, 'close', function () { + this.clearView('edit'); + }, this); + }, this); + }, + + updatePageTitle: function () { + this.setPageTitle( + this.getLanguage().translate('Entity Manager', 'labels', 'Admin') + ); + }, + + disableButtons: function () { + this.$el.find('.btn.action').addClass('disabled').attr('disabled', 'disabled'); + this.$el.find('.item-dropdown-button').addClass('disabled').attr('disabled', 'disabled'); + }, + + enableButtons: function () { + this.$el.find('.btn.action').removeClass('disabled').removeAttr('disabled'); + this.$el.find('.item-dropdown-button"]').removeClass('disabled').removeAttr('disabled'); + }, + + }); +}); diff --git a/client/src/views/admin/layouts/index.js b/client/src/views/admin/layouts/index.js index c0a7c7103b..076713644e 100644 --- a/client/src/views/admin/layouts/index.js +++ b/client/src/views/admin/layouts/index.js @@ -258,8 +258,10 @@ define('views/admin/layouts/index', 'view', function (Dep) { html += "" + this.translate('Entity Manager', 'labels', 'Admin') + ""; if (this.scope) { - html += ' ' + separatorHtml + ' ' + this.translate(this.scope, 'scopeNames') + - ' ' + separatorHtml + ' ' + this.translate('Layouts', 'labels', 'EntityManager'); + html += ' ' + separatorHtml + ' ' + + "" + + this.translate(this.scope, 'scopeNames') + '' + + ' ' + separatorHtml + ' ' + this.translate('Layouts', 'labels', 'EntityManager'); } } else { html += this.translate('Layout Manager', 'labels', 'Admin'); diff --git a/frontend/less/espo/elements/buttons.less b/frontend/less/espo/elements/buttons.less index a90aaaa04f..3da643d34a 100644 --- a/frontend/less/espo/elements/buttons.less +++ b/frontend/less/espo/elements/buttons.less @@ -97,6 +97,12 @@ width: 100px; } +.btn.btn-full-wide { + width: 100%; + text-overflow: ellipsis; + overflow: hidden; +} + .btn-default > .fa, .btn-default > .fas { color: @gray-soft;