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 @@
+
+
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');