From 0899e20cad259739e7da26ef85b0f328e727afab Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 6 Dec 2024 13:00:10 +0200 Subject: [PATCH] record panel reference --- .idea/jsonSchemas.xml | 19 +++ .vscode/settings.json | 6 + .../Metadata/BasePlus/clientDefs.json | 12 +- .../Metadata/Company/clientDefs.json | 12 +- .../Templates/Metadata/Person/clientDefs.json | 12 +- .../metadata/clientDefs/Account.json | 24 +--- .../Resources/metadata/clientDefs/Case.json | 68 +++++------ .../metadata/clientDefs/Contact.json | 24 +--- .../Resources/metadata/clientDefs/Lead.json | 42 +++---- .../metadata/clientDefs/Opportunity.json | 68 +++++------ .../Resources/metadata/app/clientRecord.json | 22 ++++ .../metadata/clientDefs/PortalUser.json | 18 +-- .../Resources/metadata/clientDefs/User.json | 26 ++-- .../admin/layouts/bottom-panels-detail.js | 9 +- .../views/admin/layouts/side-panels-detail.js | 9 +- client/src/views/record/detail-bottom.js | 20 +++- client/src/views/record/detail-side.js | 15 +++ schema/metadata/app/clientRecord.json | 18 +++ schema/metadata/clientDefs.json | 113 ++++++++++-------- 19 files changed, 280 insertions(+), 257 deletions(-) create mode 100644 application/Espo/Resources/metadata/app/clientRecord.json create mode 100644 schema/metadata/app/clientRecord.json diff --git a/.idea/jsonSchemas.xml b/.idea/jsonSchemas.xml index 74188ba28f..859c5652b2 100644 --- a/.idea/jsonSchemas.xml +++ b/.idea/jsonSchemas.xml @@ -341,6 +341,25 @@ + + + + + + + diff --git a/.vscode/settings.json b/.vscode/settings.json index 603397e5ac..1db639ab7d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -184,6 +184,12 @@ ], "url": "./schema/metadata/app/client.json" }, + { + "fileMatch": [ + "*/Resources/metadata/app/clientRecord.json" + ], + "url": "./schema/metadata/app/clientRecord.json" + }, { "fileMatch": [ "*/Resources/metadata/app/clientRoutes.json" diff --git a/application/Espo/Core/Templates/Metadata/BasePlus/clientDefs.json b/application/Espo/Core/Templates/Metadata/BasePlus/clientDefs.json index 6d02b78b4a..1b34cc159c 100644 --- a/application/Espo/Core/Templates/Metadata/BasePlus/clientDefs.json +++ b/application/Espo/Core/Templates/Metadata/BasePlus/clientDefs.json @@ -5,21 +5,15 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ] } diff --git a/application/Espo/Core/Templates/Metadata/Company/clientDefs.json b/application/Espo/Core/Templates/Metadata/Company/clientDefs.json index 6d02b78b4a..1b34cc159c 100644 --- a/application/Espo/Core/Templates/Metadata/Company/clientDefs.json +++ b/application/Espo/Core/Templates/Metadata/Company/clientDefs.json @@ -5,21 +5,15 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ] } diff --git a/application/Espo/Core/Templates/Metadata/Person/clientDefs.json b/application/Espo/Core/Templates/Metadata/Person/clientDefs.json index 6d02b78b4a..1b34cc159c 100644 --- a/application/Espo/Core/Templates/Metadata/Person/clientDefs.json +++ b/application/Espo/Core/Templates/Metadata/Person/clientDefs.json @@ -5,21 +5,15 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ] } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json index e0bf3c9b06..07c2886b20 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Account.json @@ -8,41 +8,29 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ], "detailSmall": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ] }, diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json index f703ddd449..e28f862b95 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json @@ -19,46 +19,36 @@ "checkVisibilityFunction": "isRejectAvailable" } ], - "sidePanels":{ - "detail":[ - { - "name":"activities", - "label":"Activities", - "view":"crm:views/case/record/panels/activities", - "aclScope": "Activities" - }, - { - "name":"history", - "label":"History", - "view":"crm:views/record/panels/history", - "aclScope": "Activities" - }, - { - "name":"tasks", - "label":"Tasks", - "view":"crm:views/record/panels/tasks", - "aclScope": "Task" - } + "sidePanels": { + "detail": [ + { + "name": "activities", + "reference": "activities", + "view": "crm:views/case/record/panels/activities" + }, + { + "name": "history", + "reference": "history" + }, + { + "name": "tasks", + "reference": "tasks" + } ], - "detailSmall":[ - { - "name":"activities", - "label":"Activities", - "view":"crm:views/case/record/panels/activities", - "aclScope": "Activities" - }, - { - "name":"history", - "label":"History", - "view":"crm:views/record/panels/history", - "aclScope": "Activities" - }, - { - "name":"tasks", - "label":"Tasks", - "view":"crm:views/record/panels/tasks", - "aclScope": "Task" - } + "detailSmall": [ + { + "name": "activities", + "reference": "activities", + "view": "crm:views/case/record/panels/activities" + }, + { + "name": "history", + "reference": "history" + }, + { + "name": "tasks", + "reference": "tasks" + } ] }, "filterList": [ diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json index 5cd1641368..7e24631184 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json @@ -12,41 +12,29 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ], "detailSmall": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks" } ] }, diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json index 1b0f3235e7..fc90d6f6fa 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Lead.json @@ -6,8 +6,8 @@ "recordViews":{ "detail":"crm:views/lead/record/detail" }, - "sidePanels":{ - "detail":[ + "sidePanels": { + "detail": [ { "name":"convertedTo", "label":"Converted To", @@ -18,22 +18,16 @@ "isForm": true }, { - "name":"activities", - "label":"Activities", - "view":"crm:views/record/panels/activities", - "aclScope":"Activities" + "name": "activities", + "reference": "activities" }, { - "name":"history", - "label":"History", - "view":"crm:views/record/panels/history", - "aclScope":"Activities" + "name": "history", + "reference": "history" }, { - "name":"tasks", - "label":"Tasks", - "view":"crm:views/record/panels/tasks", - "aclScope":"Task" + "name": "tasks", + "reference": "tasks" } ], "edit":[ @@ -47,7 +41,7 @@ "isForm": true } ], - "detailSmall":[ + "detailSmall": [ { "name":"convertedTo", "label":"Converted To", @@ -58,22 +52,16 @@ "isForm": true }, { - "name":"activities", - "label":"Activities", - "view":"crm:views/record/panels/activities", - "aclScope":"Activities" + "name": "activities", + "reference": "activities" }, { - "name":"history", - "label":"History", - "view":"crm:views/record/panels/history", - "aclScope":"Activities" + "name": "history", + "reference": "history" }, { - "name":"tasks", - "label":"Tasks", - "view":"crm:views/record/panels/tasks", - "aclScope":"Task" + "name": "tasks", + "reference": "tasks" } ], "editSmall":[ diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json index 00b65a8707..5352d4b54c 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json @@ -10,46 +10,36 @@ "list":"crm:views/opportunity/record/list", "kanban": "crm:views/opportunity/record/kanban" }, - "sidePanels":{ - "detail":[ - { - "name":"activities", - "label":"Activities", - "view":"crm:views/opportunity/record/panels/activities", - "aclScope": "Activities" - }, - { - "name":"history", - "label":"History", - "view":"crm:views/record/panels/history", - "aclScope": "Activities" - }, - { - "name":"tasks", - "label":"Tasks", - "view":"crm:views/record/panels/tasks", - "aclScope": "Task" - } + "sidePanels": { + "detail": [ + { + "name": "activities", + "reference": "activities", + "view": "crm:views/opportunity/record/panels/activities" + }, + { + "name": "history", + "reference": "history" + }, + { + "name": "tasks", + "reference": "tasks" + } ], - "detailSmall":[ - { - "name":"activities", - "label":"Activities", - "view":"crm:views/record/panels/activities", - "aclScope": "Activities" - }, - { - "name":"history", - "label":"History", - "view":"crm:views/record/panels/history", - "aclScope": "Activities" - }, - { - "name":"tasks", - "label":"Tasks", - "view":"crm:views/record/panels/tasks", - "aclScope": "Task" - } + "detailSmall": [ + { + "name": "activities", + "reference": "activities", + "view": "crm:views/opportunity/record/panels/activities" + }, + { + "name": "history", + "reference": "history" + }, + { + "name": "tasks", + "reference": "tasks" + } ] }, "filterList": [ diff --git a/application/Espo/Resources/metadata/app/clientRecord.json b/application/Espo/Resources/metadata/app/clientRecord.json new file mode 100644 index 0000000000..72d3aa9bf3 --- /dev/null +++ b/application/Espo/Resources/metadata/app/clientRecord.json @@ -0,0 +1,22 @@ +{ + "panels": { + "activities": { + "name": "activities", + "label": "Activities", + "view": "crm:views/record/panels/activities", + "aclScope": "Activities" + }, + "history": { + "name": "history", + "label": "History", + "view": "crm:views/record/panels/history", + "aclScope": "Activities" + }, + "tasks": { + "name": "tasks", + "label": "Tasks", + "view": "crm:views/record/panels/tasks", + "aclScope": "Task" + } + } +} diff --git a/application/Espo/Resources/metadata/clientDefs/PortalUser.json b/application/Espo/Resources/metadata/clientDefs/PortalUser.json index 539a2cd587..3d25d24cb8 100644 --- a/application/Espo/Resources/metadata/clientDefs/PortalUser.json +++ b/application/Espo/Resources/metadata/clientDefs/PortalUser.json @@ -32,29 +32,21 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" } ], "detailSmall": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" } ] }, @@ -66,4 +58,4 @@ "filter": "activePortal" }, "iconClass": "far fa-user-circle" -} \ No newline at end of file +} diff --git a/application/Espo/Resources/metadata/clientDefs/User.json b/application/Espo/Resources/metadata/clientDefs/User.json index 312bf11f97..8ecbbfe6a5 100644 --- a/application/Espo/Resources/metadata/clientDefs/User.json +++ b/application/Espo/Resources/metadata/clientDefs/User.json @@ -73,41 +73,31 @@ "detail": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/user/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks", + "view": "crm:views/user/record/panels/tasks" } ], "detailSmall": [ { "name": "activities", - "label": "Activities", - "view": "crm:views/record/panels/activities", - "aclScope": "Activities" + "reference": "activities" }, { "name": "history", - "label": "History", - "view": "crm:views/record/panels/history", - "aclScope": "Activities" + "reference": "history" }, { "name": "tasks", - "label": "Tasks", - "view": "crm:views/user/record/panels/tasks", - "aclScope": "Task" + "reference": "tasks", + "view": "crm:views/user/record/panels/tasks" } ] }, diff --git a/client/src/views/admin/layouts/bottom-panels-detail.js b/client/src/views/admin/layouts/bottom-panels-detail.js index 80ed90c746..3ad007175e 100644 --- a/client/src/views/admin/layouts/bottom-panels-detail.js +++ b/client/src/views/admin/layouts/bottom-panels-detail.js @@ -82,7 +82,14 @@ class LayoutBottomPanelsDetail extends LayoutSidePanelsDetailView { (this.getMetadata() .get(['clientDefs', this.scope, 'bottomPanels', this.viewType]) || [] - ).forEach(item => { + ).forEach(/** Record */item => { + if (item.reference) { + item = { + ...this.getMetadata().get(`app.clientRecord.panels.${item.reference}`), + ...item, + }; + } + if (!item.name) { return; } diff --git a/client/src/views/admin/layouts/side-panels-detail.js b/client/src/views/admin/layouts/side-panels-detail.js index 95cebfdc41..772fc5c648 100644 --- a/client/src/views/admin/layouts/side-panels-detail.js +++ b/client/src/views/admin/layouts/side-panels-detail.js @@ -150,7 +150,14 @@ class LayoutSidePanelsDetailView extends LayoutRowsView { } (this.getMetadata().get(['clientDefs', this.scope, 'sidePanels', this.viewType]) || []) - .forEach(item => { + .forEach(/** Record */item => { + if (item.reference) { + item = { + ...this.getMetadata().get(`app.clientRecord.panels.${item.reference}`), + ...item, + }; + } + if (!item.name) { return; } diff --git a/client/src/views/record/detail-bottom.js b/client/src/views/record/detail-bottom.js index 8d361420ed..227686eaa5 100644 --- a/client/src/views/record/detail-bottom.js +++ b/client/src/views/record/detail-bottom.js @@ -50,9 +50,23 @@ class DetailBottomRecordView extends PanelsContainerRecordView { setupPanels() { const scope = this.scope; - this.panelList = Espo.Utils.clone( - this.getMetadata() - .get(['clientDefs', scope, 'bottomPanels', this.type]) || this.panelList || []); + this.panelList = this.getMetadata().get(['clientDefs', scope, 'bottomPanels', this.type]) || + this.panelList || []; + + this.panelList = [...this.panelList].map(item => { + if ('reference' in item && item.reference) { + // noinspection UnnecessaryLocalVariableJS + /** @type {module:views/record/panels-container~panel} */ + const newItem = { + ...this.getMetadata().get(`app.clientRecord.panels.${item.reference}`), + ...item, + }; + + return newItem; + } + + return item; + }); this.panelList.forEach(item => { if ('index' in item) { diff --git a/client/src/views/record/detail-side.js b/client/src/views/record/detail-side.js index 951206f286..73c91832bd 100644 --- a/client/src/views/record/detail-side.js +++ b/client/src/views/record/detail-side.js @@ -111,6 +111,21 @@ class DetailSideRecordView extends PanelsContainerRecordView { }); } + this.panelList = this.panelList.map(item => { + if ('reference' in item && item.reference) { + // noinspection UnnecessaryLocalVariableJS + /** @type {module:views/record/panels-container~panel} */ + const newItem = { + ...this.getMetadata().get(`app.clientRecord.panels.${item.reference}`), + ...item, + }; + + return newItem; + } + + return item; + }); + this.panelList = this.panelList.filter((p) => { if (p.aclScope) { if (!this.getAcl().checkScope(p.aclScope)) { diff --git a/schema/metadata/app/clientRecord.json b/schema/metadata/app/clientRecord.json new file mode 100644 index 0000000000..1bf5f0ab1e --- /dev/null +++ b/schema/metadata/app/clientRecord.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/app/clientRecord.json", + "title": "app/navbar", + "description": "Client record definitions.", + "type": "object", + "properties": { + "panels": { + "description": "Detail view panels. Can be references from clientDefs > sidePanels/bottomPanels. As of v9.0.", + "type": "object", + "additionalProperties": { + "description": "A panel.", + "type": "object", + "$ref": "../clientDefs.json#/definitions/panel" + } + } + } +} diff --git a/schema/metadata/clientDefs.json b/schema/metadata/clientDefs.json index 4edb76f8c0..8c91752e51 100644 --- a/schema/metadata/clientDefs.json +++ b/schema/metadata/clientDefs.json @@ -330,59 +330,7 @@ "anyOf": [ {"const": "__APPEND__"}, { - "type": "object", - "properties": { - "name": { - "description": "A name.", - "type": "string" - }, - "label": { - "description": "A translatable label.", - "type": "string" - }, - "view": { - "description": "A view class.", - "type": "string" - }, - "options": { - "description": "Options to be passed to the view.", - "type": "object" - }, - "isForm": { - "description": "Whether the panel should display a form.", - "type": "boolean" - }, - "notRefreshable": { - "description": "Disable the ability to refresh the panel.", - "type": "boolean" - }, - "style": { - "description": "A style.", - "enum": ["default", "success", "warning", "danger"] - }, - "hidden": { - "description": "Hidden by default.", - "type": "boolean" - }, - "aclScope": { - "description": "A scope access to which is required for the panel being visible.", - "type": "string" - }, - "acl": { - "description": "An ACL action access to which is required for the panel being visible.", - "type": "string", - "enum": [ - "create", - "read", - "edit", - "delete", - "stream" - ] - }, - "accessDataList": { - "$ref": "#/definitions/accessDataList" - } - } + "$ref": "#/definitions/panel" } ] } @@ -1247,6 +1195,65 @@ } } } + }, + "panel": { + "type": "object", + "properties": { + "name": { + "description": "A name.", + "type": "string" + }, + "label": { + "description": "A translatable label.", + "type": "string" + }, + "view": { + "description": "A view class.", + "type": "string" + }, + "options": { + "description": "Options to be passed to the view.", + "type": "object" + }, + "isForm": { + "description": "Whether the panel should display a form.", + "type": "boolean" + }, + "notRefreshable": { + "description": "Disable the ability to refresh the panel.", + "type": "boolean" + }, + "style": { + "description": "A style.", + "enum": ["default", "success", "warning", "danger"] + }, + "hidden": { + "description": "Hidden by default.", + "type": "boolean" + }, + "aclScope": { + "description": "A scope access to which is required for the panel being visible.", + "type": "string" + }, + "acl": { + "description": "An ACL action access to which is required for the panel being visible.", + "type": "string", + "enum": [ + "create", + "read", + "edit", + "delete", + "stream" + ] + }, + "accessDataList": { + "$ref": "#/definitions/accessDataList" + }, + "reference": { + "type": "string", + "description": "A panel reference name. Panels are defined in app > clientRecord > panels. As of v9.0." + } + } } } }