From 8aa7236dd6fb85c9ed3ce9ded507292063cfca68 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Mon, 4 Mar 2024 12:56:07 +0200 Subject: [PATCH] link select filter --- .../Espo/Controllers/EntityManager.php | 78 ++++++---- .../Resources/i18n/en_US/EntityManager.json | 2 + .../Espo/Tools/LinkManager/LinkManager.php | 74 ++++++++-- .../admin/link-manager/modals/edit.tpl | 16 +++ .../views/admin/link-manager/modals/edit.js | 135 +++++++++++++++++- 5 files changed, 261 insertions(+), 44 deletions(-) diff --git a/application/Espo/Controllers/EntityManager.php b/application/Espo/Controllers/EntityManager.php index 25f6252ea8..e019e2d951 100644 --- a/application/Espo/Controllers/EntityManager.php +++ b/application/Espo/Controllers/EntityManager.php @@ -270,21 +270,31 @@ class EntityManager $params['layoutForeign'] = $data['layoutForeign']; } + if (array_key_exists('selectFilter', $data)) { + $params['selectFilter'] = $data['selectFilter']; + } + + if (array_key_exists('selectFilterForeign', $data)) { + $params['selectFilterForeign'] = $data['selectFilterForeign']; + } + /** @var array{ - * linkType: string, - * entity: string, - * link: string, - * entityForeign: string, - * linkForeign: string, - * label: string, - * labelForeign: string, - * relationName?: ?string, - * linkMultipleField?: bool, - * linkMultipleFieldForeign?: bool, - * audited?: bool, - * auditedForeign?: bool, - * layout?: string, - * layoutForeign?: string, + * linkType: string, + * entity: string, + * link: string, + * entityForeign: string, + * linkForeign: string, + * label: string, + * labelForeign: string, + * relationName?: ?string, + * linkMultipleField?: bool, + * linkMultipleFieldForeign?: bool, + * audited?: bool, + * auditedForeign?: bool, + * layout?: string, + * layoutForeign?: string, + * selectFilter?: string, + * selectFilterForeign?: string, * } $params */ @@ -347,26 +357,36 @@ class EntityManager $params['layout'] = $data['layout']; } - if (array_key_exists('auditedForeign', $data)) { + if (array_key_exists('layoutForeign', $data)) { $params['layoutForeign'] = $data['layoutForeign']; } + if (array_key_exists('selectFilter', $data)) { + $params['selectFilter'] = $data['selectFilter']; + } + + if (array_key_exists('selectFilterForeign', $data)) { + $params['selectFilterForeign'] = $data['selectFilterForeign']; + } + /** * @var array{ - * entity: string, - * link: string, - * entityForeign?: ?string, - * linkForeign?: ?string, - * label?: string, - * labelForeign?: string, - * linkMultipleField?: bool, - * linkMultipleFieldForeign?: bool, - * audited?: bool, - * auditedForeign?: bool, - * parentEntityTypeList?: string[], - * foreignLinkEntityTypeList?: string[], - * layout?: string, - * layoutForeign?: string, + * entity: string, + * link: string, + * entityForeign?: ?string, + * linkForeign?: ?string, + * label?: string, + * labelForeign?: string, + * linkMultipleField?: bool, + * linkMultipleFieldForeign?: bool, + * audited?: bool, + * auditedForeign?: bool, + * parentEntityTypeList?: string[], + * foreignLinkEntityTypeList?: string[], + * layout?: string, + * layoutForeign?: string, + * selectFilter?: string, + * selectFilterForeign?: string, * } $params */ diff --git a/application/Espo/Resources/i18n/en_US/EntityManager.json b/application/Espo/Resources/i18n/en_US/EntityManager.json index 4075a8c423..ce6405dc4b 100644 --- a/application/Espo/Resources/i18n/en_US/EntityManager.json +++ b/application/Espo/Resources/i18n/en_US/EntityManager.json @@ -44,6 +44,7 @@ "updateDuplicateCheck": "Duplicate check on update", "duplicateCheckFieldList": "Duplicate check fields", "layout": "Layout", + "selectFilter": "Select Filter", "author": "Author", "module": "Module", "version": "Version", @@ -99,6 +100,7 @@ "disabled": "Check if you don't need this entity in your system.", "linkAudited": "Creating related record and linking with existing record will be logged in Stream.", "linkMultipleField": "Link Multiple field provides a handy way to edit relations. Don't use it if you can have a large number of related records.", + "linkSelectFilter": "A primary filter to apply by default when selecting a record.", "entityType": "Base Plus - has Activities, History and Tasks panels.\n\nEvent - available in Calendar and Activities panel.", "countDisabled": "Total number won't be displayed on the list view. Can decrease loading time when the DB table is big.", "fullTextSearch": "Running rebuild is required." diff --git a/application/Espo/Tools/LinkManager/LinkManager.php b/application/Espo/Tools/LinkManager/LinkManager.php index 9e692cdf9d..d185079634 100644 --- a/application/Espo/Tools/LinkManager/LinkManager.php +++ b/application/Espo/Tools/LinkManager/LinkManager.php @@ -84,6 +84,8 @@ class LinkManager * auditedForeign?: bool, * layout?: string, * layoutForeign?: string, + * selectFilter?: string, + * selectFilterForeign?: string, * parentEntityTypeList?: string[], * foreignLinkEntityTypeList?: string[], * } $params @@ -550,6 +552,10 @@ class LinkManager $this->setLayouts($params); + if ($linkType !== self::CHILDREN_TO_PARENT) { + $this->setSelectFilters($params); + } + $this->metadata->save(); $this->language->set($entity, 'fields', $link, $label); @@ -589,20 +595,22 @@ class LinkManager /** * @param array{ - * entity: string, - * link: string, - * entityForeign?: ?string, - * linkForeign?: ?string, - * label?: string, - * labelForeign?: string, - * linkMultipleField?: bool, - * linkMultipleFieldForeign?: bool, - * audited?: bool, - * auditedForeign?: bool, - * parentEntityTypeList?: string[], - * foreignLinkEntityTypeList?: string[], - * layout?: string, - * layoutForeign?: string, + * entity: string, + * link: string, + * entityForeign?: ?string, + * linkForeign?: ?string, + * label?: string, + * labelForeign?: string, + * linkMultipleField?: bool, + * linkMultipleFieldForeign?: bool, + * audited?: bool, + * auditedForeign?: bool, + * parentEntityTypeList?: string[], + * foreignLinkEntityTypeList?: string[], + * layout?: string, + * layoutForeign?: string, + * selectFilter?: string, + * selectFilterForeign?: string, * } $params * @throws BadRequest * @throws Error @@ -767,6 +775,11 @@ class LinkManager } $this->setLayouts($params); + + if ($linkType !== self::CHILDREN_TO_PARENT) { + $this->setSelectFilters($params); + } + $this->metadata->save(); $label = null; @@ -983,6 +996,39 @@ class LinkManager ]); } + /** + * @param array{ + * entity: string, + * link: string, + * entityForeign?: ?string, + * linkForeign?: ?string, + * selectFilter?: string, + * selectFilterForeign?: string, + * } $params + */ + private function setSelectFilters(array $params): void + { + $this->setSelectFilter($params['entity'], $params['link'], $params['selectFilter'] ?? null); + + if (!isset($params['entityForeign']) || !isset($params['linkForeign'])) { + return; + } + + $this->setSelectFilter( + $params['entityForeign'], $params['linkForeign'], $params['selectFilterForeign'] ?? null); + } + + private function setSelectFilter(string $entityType, string $link, ?string $selectFilter): void + { + $this->metadata->set('clientDefs', $entityType, [ + 'relationshipPanels' => [ + $link => [ + 'selectPrimaryFilterName' => $selectFilter, + ] + ] + ]); + } + /** * @param string[] $foreignLinkEntityTypeList */ diff --git a/client/res/templates/admin/link-manager/modals/edit.tpl b/client/res/templates/admin/link-manager/modals/edit.tpl index f61646bc69..95b774f9e5 100644 --- a/client/res/templates/admin/link-manager/modals/edit.tpl +++ b/client/res/templates/admin/link-manager/modals/edit.tpl @@ -100,6 +100,22 @@ +
+
+ +
+ {{{selectFilterForeign}}} +
+
+
+
+ +
+ {{{selectFilter}}} +
+
+
+
diff --git a/client/src/views/admin/link-manager/modals/edit.js b/client/src/views/admin/link-manager/modals/edit.js index 20bd2d6c1c..afd25dd807 100644 --- a/client/src/views/admin/link-manager/modals/edit.js +++ b/client/src/views/admin/link-manager/modals/edit.js @@ -182,6 +182,13 @@ class LinkManagerEditModalView extends ModalView { this.model.set('layout', layout); this.model.set('layoutForeign', layoutForeign); + const selectFilter = this.getRelationshipPanelParam(scope, link, 'selectPrimaryFilterName'); + const selectFilterForeign = + this.getRelationshipPanelParam(entityForeign, linkForeign, 'selectPrimaryFilterName'); + + this.model.set('selectFilter', selectFilter); + this.model.set('selectFilterForeign', selectFilterForeign); + isCustom = this.getMetadata().get(`entityDefs.${entity}.links.${link}.isCustom`); } @@ -374,6 +381,7 @@ class LinkManagerEditModalView extends ModalView { params: { options: [''], }, + translatedOptions: {'': this.translate('Default')}, }); this.layoutForeignFieldView = new EnumFieldView({ @@ -392,6 +400,40 @@ class LinkManagerEditModalView extends ModalView { this.assignView('layout', this.layoutFieldView, '.field[data-name="layout"]'); this.assignView('layoutForeign', this.layoutForeignFieldView, '.field[data-name="layoutForeign"]'); + this.selectFilterFieldView = new EnumFieldView({ + name: 'selectFilter', + model: model, + mode: 'edit', + defs: { + name: 'selectFilter', + }, + params: { + options: [''], + }, + translatedOptions: {'': this.translate('all', 'presetFilters')}, + tooltip: true, + tooltipText: this.translate('linkSelectFilter', 'tooltips', 'EntityManager'), + }); + + this.selectFilterForeignFieldView = new EnumFieldView({ + name: 'selectFilterForeign', + model: model, + mode: 'edit', + defs: { + name: 'selectFilterForeign', + }, + params: { + options: ['', ...this.getEntityTypeFilters(this.scope)], + }, + translatedOptions: this.getEntityTypeFiltersTranslations(this.scope), + tooltip: true, + tooltipText: this.translate('linkSelectFilter', 'tooltips', 'EntityManager'), + }); + + this.assignView('selectFilter', this.selectFilterFieldView, '.field[data-name="selectFilter"]'); + this.assignView('selectFilterForeign', this.selectFilterForeignFieldView, + '.field[data-name="selectFilterForeign"]'); + this.createView('parentEntityTypeList', 'views/fields/entity-type-list', { model: model, mode: 'edit', @@ -450,6 +492,9 @@ class LinkManagerEditModalView extends ModalView { this.controlLayoutField(); this.listenTo(this.model, 'change:entityForeign', () => this.controlLayoutField()); + + this.controlFilterField(); + this.listenTo(this.model, 'change:entityForeign', () => this.controlFilterField()); } getEntityTypeLayouts(entityType) { @@ -473,6 +518,32 @@ class LinkManagerEditModalView extends ModalView { return map; } + getEntityTypeFiltersTranslations(entityType) { + const map = {}; + + this.getEntityTypeFilters(entityType).forEach(item => { + map[item] = this.getLanguage().translate(item, 'presetFilters', entityType); + }); + + map[''] = this.translate('all', 'presetFilters'); + + return map; + } + + /** + * @param {string} entityType + * @return {string[]} + */ + getEntityTypeFilters(entityType) { + return this.getMetadata().get(`clientDefs.${entityType}.filterList`, []).map(item => { + if (typeof item === 'string') { + return item; + } + + return item.name; + }); + } + controlLayoutField() { const foreignEntityType = this.model.get('entityForeign'); @@ -484,7 +555,23 @@ class LinkManagerEditModalView extends ModalView { this.getEntityTypeLayoutsTranslations(foreignEntityType) : {}; - this.layoutFieldView.setOptionList(layouts); + this.layoutFieldView.setOptionList(layouts) + .then(() => this.layoutFieldView.reRender()); + } + + controlFilterField() { + const foreignEntityType = this.model.get('entityForeign'); + + const layouts = foreignEntityType ? + ['', ...this.getEntityTypeFilters(foreignEntityType)] : + ['']; + + this.selectFilterFieldView.translatedOptions = foreignEntityType ? + this.getEntityTypeFiltersTranslations(foreignEntityType) : + {}; + + this.selectFilterFieldView.setOptionList(layouts) + .then(() => this.selectFilterFieldView.reRender()); } toPlural(string) { @@ -694,6 +781,9 @@ class LinkManagerEditModalView extends ModalView { this.showField('layout'); this.showField('layoutForeign'); + + this.showField('selectFilter'); + this.showField('selectFilterForeign'); } else { this.hideField('relationName'); @@ -707,6 +797,9 @@ class LinkManagerEditModalView extends ModalView { this.showField('layout'); this.hideField('layoutForeign'); + + this.showField('selectFilter'); + this.showField('selectFilterForeign'); } else if (linkType === 'manyToOne') { this.hideField('linkMultipleField'); @@ -717,6 +810,9 @@ class LinkManagerEditModalView extends ModalView { this.hideField('layout'); this.showField('layoutForeign'); + + this.showField('selectFilter'); + this.showField('selectFilterForeign'); } else { this.hideField('linkMultipleField'); @@ -734,6 +830,9 @@ class LinkManagerEditModalView extends ModalView { this.showField('layout'); this.hideField('layoutForeign'); + + this.hideField('selectFilter'); + this.hideField('selectFilterForeign'); } else if (linkType === 'childrenToParent') { this.hideField('audited'); @@ -745,6 +844,9 @@ class LinkManagerEditModalView extends ModalView { this.hideField('entityForeign'); this.hideField('labelForeign'); + this.hideField('selectFilter'); + this.hideField('selectFilterForeign'); + if (!this.noParentEntityTypeList) { this.showField('parentEntityTypeList'); } @@ -761,6 +863,15 @@ class LinkManagerEditModalView extends ModalView { this.hideField('layout'); this.hideField('layoutForeign'); + + if (linkType) { + this.showField('selectFilter'); + this.showField('selectFilterForeign'); + } + else { + this.hideField('selectFilter'); + this.hideField('selectFilterForeign'); + } } } } @@ -815,6 +926,8 @@ class LinkManagerEditModalView extends ModalView { 'auditedForeign', 'layout', 'layoutForeign', + 'selectFilter', + 'selectFilterForeign', 'parentEntityTypeList', 'foreignLinkEntityTypeList', ]; @@ -899,6 +1012,8 @@ class LinkManagerEditModalView extends ModalView { auditedForeign: auditedForeign, layout: layout, layoutForeign: layoutForeign, + selectFilter: this.model.get('selectFilter'), + selectFilterForeign: this.model.get('selectFilterForeign'), }; if (!this.isNew) { @@ -921,6 +1036,14 @@ class LinkManagerEditModalView extends ModalView { if (this.noParentEntityTypeList) { attributes.parentEntityTypeList = null; } + + delete attributes.selectFilter; + delete attributes.selectFilterForeign; + } + + if (linkType === 'parentToChildren') { + delete attributes.selectFilter; + delete attributes.selectFilterForeign; } Espo.Ajax @@ -1006,6 +1129,16 @@ class LinkManagerEditModalView extends ModalView { return list; } + /** + * @param {string} entityType + * @param {string} link + * @param {string} param + * @return {*} + */ + getRelationshipPanelParam(entityType, link, param) { + return this.getMetadata().get(`clientDefs.${entityType}.relationshipPanels.${link}.${param}`); + } + broadcastUpdate() { this.getHelper().broadcastChannel.postMessage('update:metadata'); this.getHelper().broadcastChannel.postMessage('update:language');