diff --git a/client/src/views/detail.js b/client/src/views/detail.js index 451204e280..07125caf73 100644 --- a/client/src/views/detail.js +++ b/client/src/views/detail.js @@ -133,6 +133,12 @@ class DetailView extends MainView { */ MODE_DETAIL = 'detail' + /** + * @private + * @type {string} + */ + nameAttribute + /** @inheritDoc */ setup() { super.setup(); @@ -145,6 +151,8 @@ class DetailView extends MainView { this.rootUrl = this.options.rootUrl || this.options.params.rootUrl || '#' + this.scope; this.isReturn = this.options.isReturn || this.options.params.isReturn || false; + this.nameAttribute = this.getMetadata().get(`clientDefs.${this.entityType}.nameAttribute`) || 'name'; + this.setupModes(); this.setupHeader(); this.setupRecord(); @@ -199,8 +207,8 @@ class DetailView extends MainView { this.updatePageTitle(); }); - this.listenTo(this.model, 'sync', (model) => { - if (model && model.hasChanged('name')) { + this.listenTo(this.model, 'sync', model => { + if (model && model.hasChanged(this.nameAttribute)) { this.updatePageTitle(); } }); @@ -217,8 +225,8 @@ class DetailView extends MainView { fontSizeFlexible: true, }); - this.listenTo(this.model, 'sync', (model) => { - if (model && model.hasChanged('name')) { + this.listenTo(this.model, 'sync', model => { + if (model && model.hasChanged(this.nameAttribute)) { if (this.getView('header')) { this.getView('header').reRender(); } @@ -564,7 +572,7 @@ class DetailView extends MainView { * @inheritDoc */ getHeader() { - const name = this.model.attributes.name || this.model.id; + const name = this.model.attributes[this.nameAttribute] || this.model.id; const title = document.createElement('span'); title.classList.add('font-size-flexible', 'title') @@ -614,8 +622,8 @@ class DetailView extends MainView { * @inheritDoc */ updatePageTitle() { - if (this.model.has('name')) { - this.setPageTitle(this.model.get('name') || this.model.id); + if (this.model.has(this.nameAttribute)) { + this.setPageTitle(this.model.attributes[this.nameAttribute] || this.model.id); return; } diff --git a/client/src/views/edit.js b/client/src/views/edit.js index 7670737fca..66a9ea5b6a 100644 --- a/client/src/views/edit.js +++ b/client/src/views/edit.js @@ -80,12 +80,20 @@ class EditView extends MainView { */ rootUrl + /** + * @private + * @type {string} + */ + nameAttribute + /** @inheritDoc */ setup() { this.headerView = this.options.headerView || this.headerView; this.recordView = this.options.recordView || this.recordView; - this.rootUrl = this.options.rootUrl || this.options.params.rootUrl || '#' + this.scope + this.rootUrl = this.options.rootUrl || this.options.params.rootUrl || '#' + this.scope; + + this.nameAttribute = this.getMetadata().get(`clientDefs.${this.entityType}.nameAttribute`) || 'name'; this.setupHeader(); this.setupRecord(); @@ -193,7 +201,7 @@ class EditView extends MainView { return this.buildHeaderHtml([root, create]); } - const name = this.model.attributes.name || this.model.id; + const name = this.model.attributes[this.nameAttribute] || this.model.id; let title = document.createElement('span'); title.textContent = name; @@ -224,7 +232,7 @@ class EditView extends MainView { return; } - const name = this.model.get('name'); + const name = this.model.attributes[this.nameAttribute]; const title = name ? name : this.getLanguage().translate(this.scope, 'scopeNames'); diff --git a/client/src/views/modals/detail.js b/client/src/views/modals/detail.js index c18e1e4329..35003db84a 100644 --- a/client/src/views/modals/detail.js +++ b/client/src/views/modals/detail.js @@ -53,6 +53,12 @@ class DetailModalView extends ModalView { flexibleHeaderFontSize = true duplicateAction = false + /** + * @private + * @type {string} + */ + nameAttribute + shortcutKeys = { /** @this DetailModalView */ 'Control+Space': function (e) { @@ -135,6 +141,8 @@ class DetailModalView extends ModalView { this.removeDisabled = this.getMetadata().get(['clientDefs', this.entityType, 'removeDisabled']) || this.removeDisabled; + this.nameAttribute = this.getMetadata().get(`clientDefs.${this.entityType}.nameAttribute`) || 'name'; + this.fullFormDisabled = this.options.fullFormDisabled || this.fullFormDisabled; this.layoutName = this.options.layoutName || this.layoutName; @@ -340,7 +348,7 @@ class DetailModalView extends ModalView { .text(this.getLanguage().translate(scope, 'scopeNames')) .get(0).outerHTML; - if (model.get('name')) { + if (model.attributes[this.nameAttribute]) { this.headerHtml += ' ' + $('') .addClass('chevron-right') @@ -348,7 +356,7 @@ class DetailModalView extends ModalView { this.headerHtml += ' ' + $('') - .text(model.get('name')) + .text(model.attributes[this.nameAttribute]) .get(0).outerHTML; } diff --git a/client/src/views/modals/edit.js b/client/src/views/modals/edit.js index fe469d8bf7..f58413d9fd 100644 --- a/client/src/views/modals/edit.js +++ b/client/src/views/modals/edit.js @@ -52,6 +52,12 @@ class EditModalView extends ModalView { /** @protected */ bottomDisabled = false + /** + * @private + * @type {string} + */ + nameAttribute + shortcutKeys = { /** @this EditModalView */ 'Control+Enter': function (e) { @@ -183,6 +189,8 @@ class EditModalView extends ModalView { this.entityType = this.options.entityType || this.scope; this.id = this.options.id; + this.nameAttribute = this.getMetadata().get(`clientDefs.${this.entityType}.nameAttribute`) || 'name'; + if (this.options.headerText !== undefined) { this.headerHtml = undefined; this.headerText = this.options.headerText; @@ -312,7 +320,7 @@ class EditModalView extends ModalView { const separator = document.createElement('span'); separator.classList.add('chevron-right'); - const name = this.model.attributes.name; + const name = this.model.attributes[this.nameAttribute]; wrapper.append( document.createTextNode(this.getLanguage().translate('Edit') + ' ยท '), @@ -379,8 +387,8 @@ class EditModalView extends ModalView { this.dialog.close(); if (wasNew) { - const url = '#' + this.scope + '/view/' + model.id; - const name = model.get('name') || this.model.id; + const url = `#${this.scope}/view/${model.id}`; + const name = model.attributes[this.nameAttribute] || this.model.id; const msg = this.translate('Created') + '\n' + `[${name}](${url})`; diff --git a/schema/metadata/clientDefs.json b/schema/metadata/clientDefs.json index 4d1f2ec354..4c1a4f1c16 100644 --- a/schema/metadata/clientDefs.json +++ b/schema/metadata/clientDefs.json @@ -305,6 +305,10 @@ } } }, + "nameAttribute": { + "type": "string", + "description": "An entity attribute to be used to display the record name on views. As of v9.1." + }, "menu": { "description": "Top-right menu for views (list, detail, edit). Action types: buttons, dropdowns. https://docs.espocrm.com/development/custom-buttons/", "type": "object",