entity manager params group index

This commit is contained in:
Yurii
2026-03-05 19:42:16 +02:00
parent 10dd636646
commit c22390ffc7
4 changed files with 320 additions and 178 deletions
@@ -5,7 +5,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -13,35 +14,40 @@
"type": "multiEnum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Contact": {
@@ -50,7 +56,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -58,35 +65,40 @@
"type": "multiEnum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Lead": {
@@ -95,7 +107,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -103,35 +116,40 @@
"type": "bool",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Opportunity": {
@@ -140,28 +158,32 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Document": {
@@ -170,28 +192,32 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Case": {
@@ -200,28 +226,32 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"KnowledgeBaseArticle": {
@@ -230,28 +260,32 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Meeting": {
@@ -296,14 +330,16 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Call": {
@@ -348,14 +384,16 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"Task": {
@@ -382,28 +420,32 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"TargetList": {
@@ -412,21 +454,24 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"@Event": {
@@ -471,14 +516,16 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"aclContactLink": {
"location": "aclDefs",
@@ -487,7 +534,8 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-contact-link"
}
},
"groupIndex": 4
},
"aclAccountLink": {
"location": "aclDefs",
@@ -496,21 +544,24 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-account-link"
}
},
"groupIndex": 4
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
}
}
@@ -28,7 +28,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -36,21 +37,24 @@
"type": "multiEnum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"aclContactLink": {
"location": "aclDefs",
@@ -59,7 +63,8 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-contact-link"
}
},
"groupIndex": 4
},
"aclAccountLink": {
"location": "aclDefs",
@@ -68,21 +73,24 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-account-link"
}
},
"groupIndex": 4
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"@Person": {
@@ -91,7 +99,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -99,21 +108,24 @@
"type": "multiEnum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"aclContactLink": {
"location": "aclDefs",
@@ -122,7 +134,8 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-contact-link"
}
},
"groupIndex": 4
},
"aclAccountLink": {
"location": "aclDefs",
@@ -131,21 +144,24 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-account-link"
}
},
"groupIndex": 4
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"@Base": {
@@ -154,7 +170,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -162,21 +179,24 @@
"type": "multiEnum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"aclContactLink": {
"location": "aclDefs",
@@ -185,7 +205,8 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-contact-link"
}
},
"groupIndex": 4
},
"aclAccountLink": {
"location": "aclDefs",
@@ -194,28 +215,32 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-account-link"
}
},
"groupIndex": 4
},
"categories": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
},
"@BasePlus": {
@@ -224,7 +249,8 @@
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 3
},
"duplicateCheckFieldList": {
"location": "scopes",
@@ -232,21 +258,24 @@
"type": "multiEnum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/duplicate-check-field-list"
}
},
"groupIndex": 3
},
"collaborators": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"assignedUsers": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"aclContactLink": {
"location": "aclDefs",
@@ -255,7 +284,8 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-contact-link"
}
},
"groupIndex": 4
},
"aclAccountLink": {
"location": "aclDefs",
@@ -264,28 +294,32 @@
"type": "enum",
"tooltip": true,
"view": "views/admin/entity-manager/fields/acl-account-link"
}
},
"groupIndex": 4
},
"categories": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 1
},
"lockable": {
"location": "scopes",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
},
"transactionalSave": {
"location": "entityDefs",
"fieldDefs": {
"type": "bool",
"tooltip": true
}
},
"groupIndex": 2
}
}
}
+146 -93
View File
@@ -38,6 +38,7 @@ class EntityManagerEditView extends View {
* string: {
* fieldDefs: Object.<string, *>,
* location?: string,
* groupIndex?: number,
* }
* }}
*/
@@ -50,6 +51,12 @@ class EntityManagerEditView extends View {
*/
enumFieldList
/**
* @private
* @type {string|null}
*/
scope
data() {
return {
isNew: this.isNew,
@@ -77,66 +84,9 @@ class EntityManagerEditView extends View {
this.hasColorField = !this.getConfig().get('scopeColorsDisabled');
if (scope) {
this.additionalParams = Espo.Utils.cloneDeep({
...this.getMetadata().get(['app', 'entityManagerParams', 'Global']),
...this.getMetadata().get(['app', 'entityManagerParams', '@' + (templateType || '_')]),
...this.getMetadata().get(['app', 'entityManagerParams', scope]),
});
this.setupAdditionalParams(templateType, scope);
this.setupModelValues(scope);
this.model.set('name', scope);
this.model.set('labelSingular', this.translate(scope, 'scopeNames'));
this.model.set('labelPlural', this.translate(scope, 'scopeNamesPlural'));
this.model.set('type', this.getMetadata().get('scopes.' + scope + '.type') || '');
this.model.set('stream', this.getMetadata().get('scopes.' + scope + '.stream') || false);
this.model.set('disabled', this.getMetadata().get('scopes.' + scope + '.disabled') || false);
this.model.set('sortBy', this.getMetadata().get('entityDefs.' + scope + '.collection.orderBy'));
this.model.set('sortDirection', this.getMetadata().get('entityDefs.' + scope + '.collection.order'));
this.model.set('textFilterFields',
this.getMetadata().get(['entityDefs', scope, 'collection', 'textFilterFields']) || ['name']
);
this.model.set('fullTextSearch',
this.getMetadata().get(['entityDefs', scope, 'collection', 'fullTextSearch']) || false
);
this.model.set('countDisabled',
this.getMetadata().get(['entityDefs', scope, 'collection', 'countDisabled']) || false
);
this.model.set('statusField', this.getMetadata().get('scopes.' + scope + '.statusField') || null);
if (this.hasColorField) {
this.model.set('color', this.getMetadata().get(['clientDefs', scope, 'color']) || null);
}
this.model.set('iconClass', this.getMetadata().get(['clientDefs', scope, 'iconClass']) || null);
this.model.set(
'kanbanViewMode',
this.getMetadata().get(['clientDefs', scope, 'kanbanViewMode']) || false
);
this.model.set(
'kanbanStatusIgnoreList',
this.getMetadata().get(['scopes', scope, 'kanbanStatusIgnoreList']) || []
);
for (const param in this.additionalParams) {
/** @type {{fieldDefs: Object, location?: string, param?: string}} */
const defs = this.additionalParams[param];
const location = defs.location || this.defaultParamLocation;
const defaultValue = defs.fieldDefs.type === 'bool' ? false : null;
const actualParam = defs.param || param;
const value = this.getMetadata().get([location, scope, actualParam]) || defaultValue;
this.model.set(param, value);
}
}
if (scope) {
/** @type {Record.<string, Record>} */
const fieldDefs = this.getMetadata().get(`entityDefs.${scope}.fields`) || {};
@@ -221,6 +171,13 @@ class EntityManagerEditView extends View {
this.translatedStatusOptions = {};
}
this.setupDetailLayout();
}
/**
* @private
*/
setupDetailLayout() {
this.detailLayout = [
{
rows: [
@@ -307,50 +264,146 @@ class EntityManagerEditView extends View {
},
];
if (this.scope) {
const rows1 = [];
const rows2 = [];
if (!this.scope) {
return;
}
const paramList1 = Object.keys(this.additionalParams)
.filter(item => !!this.getMetadata().get(['app', 'entityManagerParams', 'Global', item]));
/** @var {string[][]}*/
const groups = [];
const paramList2 = Object.keys(this.additionalParams)
.filter(item => !paramList1.includes(item));
for (const [param, it] of Object.entries(this.additionalParams)) {
const index = (it.groupIndex === undefined ? 9999 : it.groupIndex) + 100;
const add = function (rows, list) {
list.forEach((param, i) => {
if (i % 2 === 0) {
rows.push([]);
}
const row = rows[rows.length - 1];
row.push({name: param});
if (
i === list.length - 1 &&
row.length === 1
) {
row.push(false);
}
});
};
add(rows1, paramList1);
add(rows2, paramList2);
if (rows1.length) {
this.detailLayout.push({rows: rows1});
if (groups[index] === undefined) {
groups[index] = [];
}
if (rows2.length) {
this.detailLayout.push({rows: rows2});
groups[index] ??= [];
groups[index].push(param);
}
const add = function (rows, list) {
list.forEach((param, i) => {
if (i % 2 === 0) {
rows.push([]);
}
const row = rows[rows.length - 1];
row.push({name: param});
if (
i === list.length - 1 &&
row.length === 1
) {
row.push(false);
}
});
};
groups.forEach(paramList => {
const rows = [];
add(rows, paramList);
if (rows.length) {
this.detailLayout.push({rows: rows});
}
});
}
/**
* @private
*/
setupModelValues() {
const scope = this.scope;
this.model.set('name', scope);
this.model.set('labelSingular', this.translate(scope, 'scopeNames'));
this.model.set('labelPlural', this.translate(scope, 'scopeNamesPlural'));
this.model.set('type', this.getMetadata().get(`scopes.${scope}.type`) || '');
this.model.set('stream', this.getMetadata().get(`scopes.${scope}.stream`) || false);
this.model.set('disabled', this.getMetadata().get(`scopes.${scope}.disabled`) || false);
this.model.set('sortBy', this.getMetadata().get(`entityDefs.${scope}.collection.orderBy`));
this.model.set('sortDirection', this.getMetadata().get(`entityDefs.${scope}.collection.order`));
this.model.set('textFilterFields',
this.getMetadata().get(['entityDefs', scope, 'collection', 'textFilterFields']) || ['name']
);
this.model.set('fullTextSearch',
this.getMetadata().get(['entityDefs', scope, 'collection', 'fullTextSearch']) || false
);
this.model.set('countDisabled',
this.getMetadata().get(['entityDefs', scope, 'collection', 'countDisabled']) || false
);
this.model.set('statusField', this.getMetadata().get(`scopes.${scope}.statusField`) || null);
if (this.hasColorField) {
this.model.set('color', this.getMetadata().get(['clientDefs', scope, 'color']) || null);
}
this.model.set('iconClass', this.getMetadata().get(['clientDefs', scope, 'iconClass']) || null);
this.model.set(
'kanbanViewMode',
this.getMetadata().get(['clientDefs', scope, 'kanbanViewMode']) || false
);
this.model.set(
'kanbanStatusIgnoreList',
this.getMetadata().get(['scopes', scope, 'kanbanStatusIgnoreList']) || []
);
for (const param in this.additionalParams) {
/** @type {{fieldDefs: Object, location?: string, param?: string}} */
const defs = this.additionalParams[param];
const location = defs.location || this.defaultParamLocation;
const defaultValue = defs.fieldDefs.type === 'bool' ? false : null;
const actualParam = defs.param || param;
const value = this.getMetadata().get([location, scope, actualParam]) || defaultValue;
this.model.set(param, value);
}
}
/**
* @private
*/
setupAdditionalParams() {
const scope = this.scope;
const templateType = this.getMetadata().get(`scopes.${this.scope}.type`) ?? null;
const tKey = '@' + (templateType ?? '_');
/** @var {Record.<string, *>} */
const globalParams = Espo.Utils.cloneDeep(this.getMetadata().get('app.entityManagerParams.Global', {}));
/** @var {Record.<string, *>} */
const templateParams = Espo.Utils.cloneDeep(this.getMetadata().get(`app.entityManagerParams.${tKey}`, {}));
/** @var {Record.<string, *>} */
const scopeParams = Espo.Utils.cloneDeep(this.getMetadata().get(`app.entityManagerParams.${scope}`, {}));
for (const [, it] of Object.entries(globalParams)) {
it.groupIndex ??= -100;
}
for (const [, it] of Object.entries(templateParams)) {
it.groupIndex ??= 50;
}
for (const [, it] of Object.entries(scopeParams)) {
it.groupIndex ??= 100;
}
this.additionalParams = {...globalParams, ...templateParams, ...scopeParams};
}
setup() {
const scope = this.scope = this.options.scope || false;
const scope = this.scope = this.options.scope ?? null;
this.isNew = !scope;
this.model = new Model();
@@ -34,6 +34,10 @@
"fieldDefs": {
"description": "Field definitions. The defined field will be rendered on the entity manager edit view.",
"$ref": "./../entityDefs.json#/definitions/fieldDefs"
},
"groupIndex": {
"type": "integer",
"description": "An index to group related parameters into panels. As of v9.4."
}
}
}