From f1f0f3ea9a78521695dda7050c71f99edfdcd3cf Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 7 Nov 2025 16:00:16 +0200 Subject: [PATCH 01/13] process dynamic logic if model default preparator is used --- client/src/views/record/edit.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/views/record/edit.js b/client/src/views/record/edit.js index af561549c9..6497d588f6 100644 --- a/client/src/views/record/edit.js +++ b/client/src/views/record/edit.js @@ -148,7 +148,11 @@ class EditRecordView extends DetailRecordView { this.wait(promise); // @todo Revise. Possible race condition issues. - promise.then(() => super.setupBeforeFinal()); + promise.then(() => { + super.setupBeforeFinal(); + + this.processDynamicLogic(); + }); } if (this.model.isNew()) { From fc7c949cf3eefb5bc64c488163f27a272c2797ea Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sat, 8 Nov 2025 20:31:46 +0200 Subject: [PATCH 02/13] link field: foreign name attribute --- client/src/views/fields/link.js | 37 +++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/client/src/views/fields/link.js b/client/src/views/fields/link.js index ba583787f1..a0b72af4d4 100644 --- a/client/src/views/fields/link.js +++ b/client/src/views/fields/link.js @@ -217,6 +217,13 @@ class LinkFieldView extends BaseFieldView { */ linkClass + /** + * @protected + * @type {string} + * @since 9.2.5 + */ + foreignNameAttribute + /** @inheritDoc */ events = { /** @this LinkFieldView */ @@ -364,6 +371,10 @@ class LinkFieldView extends BaseFieldView { this.model.getFieldParam(this.name, 'entity') || this.model.getLinkParam(this.name, 'entity'); + this.foreignNameAttribute = this.model.getLinkParam(this.name, 'foreignName') ?? + this.getMetadata().get(`clientDefs.${this.foreignScope}.nameAttribute`) ?? + 'name'; + if ('createDisabled' in this.options) { this.createDisabled = this.options.createDisabled; } @@ -407,12 +418,12 @@ class LinkFieldView extends BaseFieldView { * @return {Promise|void} */ select(model) { - this.$elementName.val(model.get('name') || model.id); - this.$elementId.val(model.get('id')); + this.$elementName.val(model.get(this.foreignNameAttribute) || model.id); + this.$elementId.val(model.id); if (this.mode === this.MODE_SEARCH) { - this.searchData.idValue = model.get('id'); - this.searchData.nameValue = model.get('name') || model.id; + this.searchData.idValue = model.id; + this.searchData.nameValue = model.get(this.foreignNameAttribute) || model.id; } this.trigger('change'); @@ -611,7 +622,7 @@ class LinkFieldView extends BaseFieldView { if (!this.forceSelectAllAttributes) { const mandatorySelectAttributeList = this.getMandatorySelectAttributeList(); - let select = ['id', 'name']; + let select = ['id', this.foreignNameAttribute]; if (mandatorySelectAttributeList) { select = select.concat(mandatorySelectAttributeList); @@ -824,12 +835,20 @@ class LinkFieldView extends BaseFieldView { const list = []; response.list.forEach(item => { + const name = item[this.foreignNameAttribute] || item.name || item.id; + + const attributes = item; + + if (this.foreignNameAttribute !== 'name') { + attributes[this.foreignNameAttribute] = name; + } + list.push({ id: item.id, - name: item.name || item.id, + name: name, data: item.id, - value: item.name || item.id, - attributes: item, + value: name, + attributes: attributes, }); }); @@ -1365,7 +1384,7 @@ class LinkFieldView extends BaseFieldView { */ selectOneOf(models) { models.forEach(model => { - this.addLinkOneOf(model.id, model.get('name')); + this.addLinkOneOf(model.id, model.get(this.foreignNameAttribute)); }); } } From 379a2d22f31685212428498c0dc2257b0091ebc0 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sat, 8 Nov 2025 20:53:02 +0200 Subject: [PATCH 03/13] autocomplete suggestion min width --- frontend/less/espo/elements/dropdown.less | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/less/espo/elements/dropdown.less b/frontend/less/espo/elements/dropdown.less index ea8e183178..2bf7935278 100644 --- a/frontend/less/espo/elements/dropdown.less +++ b/frontend/less/espo/elements/dropdown.less @@ -8,6 +8,8 @@ padding: var(--5px) 0; user-select: none; + min-width: calc(var(--50px) + var(--10px)); + .autocomplete-suggestion.autocomplete-selected { background-color: var(--dropdown-link-hover-bg) !important; color: var(--dropdown-link-hover-color) !important; From 9901070fb1702d150695b2d343a9f86802f3c664 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 11 Nov 2025 08:14:35 +0200 Subject: [PATCH 04/13] fix layout --- .../layouts/LeadCaptureLogRecord/listForLeadCapture.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/Espo/Resources/layouts/LeadCaptureLogRecord/listForLeadCapture.json b/application/Espo/Resources/layouts/LeadCaptureLogRecord/listForLeadCapture.json index 55ede72410..13222d6cb8 100644 --- a/application/Espo/Resources/layouts/LeadCaptureLogRecord/listForLeadCapture.json +++ b/application/Espo/Resources/layouts/LeadCaptureLogRecord/listForLeadCapture.json @@ -1,5 +1,5 @@ [ {"name":"target", "notSortable": true}, - {"name":"isCreated", "width": "25", "notSortable": true}, - {"name":"createdAt", "width": "30", "notSortable": true} + {"name":"isCreated", "width": 25, "notSortable": true}, + {"name":"createdAt", "width": 30, "notSortable": true} ] From e311ac6dbb4a2ad5bdfc6fddb1d90210fa349a3c Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Tue, 11 Nov 2025 22:00:27 +0200 Subject: [PATCH 05/13] fix width in layouts --- .../Modules/Crm/Resources/layouts/Contact/listSelect.json | 2 +- .../Resources/layouts/ActionHistoryRecord/listSmall.json | 8 ++++---- application/Espo/Resources/layouts/AuthToken/list.json | 8 ++++---- .../Espo/Resources/layouts/AuthToken/listSmall.json | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/application/Espo/Modules/Crm/Resources/layouts/Contact/listSelect.json b/application/Espo/Modules/Crm/Resources/layouts/Contact/listSelect.json index 54d4fb3c2f..e0d4263ae7 100644 --- a/application/Espo/Modules/Crm/Resources/layouts/Contact/listSelect.json +++ b/application/Espo/Modules/Crm/Resources/layouts/Contact/listSelect.json @@ -1,5 +1,5 @@ [ - {"name":"name","link":true, "width": "40"}, + {"name":"name", "link":true, "width": 40}, {"name":"account"}, {"name":"emailAddress", "notSortable": true} ] diff --git a/application/Espo/Resources/layouts/ActionHistoryRecord/listSmall.json b/application/Espo/Resources/layouts/ActionHistoryRecord/listSmall.json index bcadcb596e..1137059292 100644 --- a/application/Espo/Resources/layouts/ActionHistoryRecord/listSmall.json +++ b/application/Espo/Resources/layouts/ActionHistoryRecord/listSmall.json @@ -1,6 +1,6 @@ [ - {"name":"action", "width": "18", "notSortable": true}, - {"name":"targetType", "width": "20", "notSortable": true}, + {"name":"action", "width": 18, "notSortable": true}, + {"name":"targetType", "width": 20, "notSortable": true}, {"name":"target", "notSortable": true}, - {"name":"createdAt", "width": "18", "align": "right", "notSortable": true} -] \ No newline at end of file + {"name":"createdAt", "width": 18, "align": "right", "notSortable": true} +] diff --git a/application/Espo/Resources/layouts/AuthToken/list.json b/application/Espo/Resources/layouts/AuthToken/list.json index e24851b115..de70a1b06d 100644 --- a/application/Espo/Resources/layouts/AuthToken/list.json +++ b/application/Espo/Resources/layouts/AuthToken/list.json @@ -1,7 +1,7 @@ [ {"name":"user"}, - {"name":"isActive", "widthPx": "100"}, - {"name":"ipAddress", "width": "17"}, - {"name":"createdAt", "width": "19"}, - {"name":"lastAccess", "width": "19"} + {"name":"isActive", "widthPx": 100}, + {"name":"ipAddress", "width": 17}, + {"name":"createdAt", "width": 19}, + {"name":"lastAccess", "width": 19} ] diff --git a/application/Espo/Resources/layouts/AuthToken/listSmall.json b/application/Espo/Resources/layouts/AuthToken/listSmall.json index e24851b115..de70a1b06d 100644 --- a/application/Espo/Resources/layouts/AuthToken/listSmall.json +++ b/application/Espo/Resources/layouts/AuthToken/listSmall.json @@ -1,7 +1,7 @@ [ {"name":"user"}, - {"name":"isActive", "widthPx": "100"}, - {"name":"ipAddress", "width": "17"}, - {"name":"createdAt", "width": "19"}, - {"name":"lastAccess", "width": "19"} + {"name":"isActive", "widthPx": 100}, + {"name":"ipAddress", "width": 17}, + {"name":"createdAt", "width": 19}, + {"name":"lastAccess", "width": 19} ] From 26ee35cb7dfb4c48b55c28d79752a31b392bc610 Mon Sep 17 00:00:00 2001 From: Shaikh Naasir <166585409+ShaikhNaasir@users.noreply.github.com> Date: Thu, 13 Nov 2025 19:37:22 +0530 Subject: [PATCH 06/13] Fix typo in accessCheckCommand description (#3519) This pull request fixes a minor typo in the WebSocket schema description: Changed 'patameter' to 'parameter'. No functional changes were made. Purely a documentation correction. --- schema/metadata/app/webSocket.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/schema/metadata/app/webSocket.json b/schema/metadata/app/webSocket.json index 17c0204051..d0e1443177 100644 --- a/schema/metadata/app/webSocket.json +++ b/schema/metadata/app/webSocket.json @@ -19,7 +19,7 @@ }, "accessCheckCommand": { "type": "string", - "description": "A console command that will be used to check whether a topic is allowed for a user when they attempting to subscribe. Patameter placeholders starts with the colon :. The userId parameter contains a user ID. If access checking is not needed, omit this parameter." + "description": "A console command that will be used to check whether a topic is allowed for a user when they attempting to subscribe. Parameter placeholders starts with the colon :. The userId parameter contains a user ID. If access checking is not needed, omit this parameter." } } } From 610c1004aa5b6720d1a2c9c738bb855663edddbd Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 13 Nov 2025 17:25:10 +0200 Subject: [PATCH 07/13] jsdoc fix --- client/src/collection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/collection.js b/client/src/collection.js index 1f2bbbed24..8d3deed2af 100644 --- a/client/src/collection.js +++ b/client/src/collection.js @@ -174,7 +174,7 @@ class Collection { parentModel /** - * @param {Model[]|null} [models] Models. + * @param {Model[]|Record[]|null} [models] Models. * @param {{ * entityType?: string, * model?: Model.prototype, From 08fecd2dc05474b31e058c3e6dfa404af15fc097 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 13 Nov 2025 17:56:06 +0200 Subject: [PATCH 08/13] search menu check icon fix --- client/res/templates/record/search.tpl | 2 +- client/src/views/record/search.js | 2 +- frontend/less/espo/custom.less | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/res/templates/record/search.tpl b/client/res/templates/record/search.tpl index 9d3162e9e8..f936a3e8d0 100644 --- a/client/res/templates/record/search.tpl +++ b/client/res/templates/record/search.tpl @@ -34,7 +34,7 @@ data-action="selectPreset" >
- {{#if label}}{{label}}{{else}}{{translate name category='presetFilters' scope=../entityType}}{{/if}} + {{~#if label}}{{label}}{{else}}{{translate name category='presetFilters' scope=../entityType}}{{/if~}}
diff --git a/client/src/views/record/search.js b/client/src/views/record/search.js index 2191791a1c..ffa2f69d6b 100644 --- a/client/src/views/record/search.js +++ b/client/src/views/record/search.js @@ -938,7 +938,7 @@ class SearchView extends View { this.$el .find('ul.filter-menu a.preset[data-name="'+presetName+'"]') - .prepend(''); + .prepend(''); } manageBoolFilters() { diff --git a/frontend/less/espo/custom.less b/frontend/less/espo/custom.less index eb2a271486..576ce8e477 100644 --- a/frontend/less/espo/custom.less +++ b/frontend/less/espo/custom.less @@ -112,7 +112,7 @@ img.image-preview { .preset { text-overflow: ellipsis; - overflow: hidden !important; + //overflow: hidden !important; } .preset > div{ From 9e78d4cad30d99b6b79bee07f04aa1c3d01242d2 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 13 Nov 2025 18:03:00 +0200 Subject: [PATCH 09/13] no-select --- client/src/views/email/fields/email-address-varchar.js | 4 ++-- frontend/less/espo/elements/type.less | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/views/email/fields/email-address-varchar.js b/client/src/views/email/fields/email-address-varchar.js index 8b952a1191..3c8be77ecc 100644 --- a/client/src/views/email/fields/email-address-varchar.js +++ b/client/src/views/email/fields/email-address-varchar.js @@ -482,9 +482,9 @@ class EmailAddressVarcharFieldView extends BaseFieldView { $text.append( $('').text(name), - ' ', + ' ', $('').addClass('text-muted middle-dot'), - ' ' + ' ' ); } diff --git a/frontend/less/espo/elements/type.less b/frontend/less/espo/elements/type.less index 3dab594ba0..d6cce12513 100644 --- a/frontend/less/espo/elements/type.less +++ b/frontend/less/espo/elements/type.less @@ -213,6 +213,10 @@ small, top: var(--minus-1px); } +.no-select { + user-select: none; +} + a[role="button"], a[href="javascript:"] { &:not(.selectable) { From c426a637feac4d9111c09a725029e151a7b52414 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 13 Nov 2025 18:11:02 +0200 Subject: [PATCH 10/13] email address add impr --- .../email/fields/email-address-varchar.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/client/src/views/email/fields/email-address-varchar.js b/client/src/views/email/fields/email-address-varchar.js index 3c8be77ecc..ba1b0a609c 100644 --- a/client/src/views/email/fields/email-address-varchar.js +++ b/client/src/views/email/fields/email-address-varchar.js @@ -420,7 +420,38 @@ class EmailAddressVarcharFieldView extends BaseFieldView { return true; } + /** + * + * @param {string} address + * @param {string} name + * @param {string} [type] + * @param {string} [id] + */ addAddress(address, name, type, id) { + if (name === '') { + const nameHash = this.model.attributes.nameHash ?? {}; + + if (address in nameHash) { + name = nameHash[address]; + } + } + + if (type === undefined) { + const typeHash = this.model.attributes.typeHash ?? {}; + + if (address in typeHash) { + type = typeHash[address]; + } + } + + if (id === undefined) { + const idHash = this.model.attributes.idHash ?? {}; + + if (address in idHash) { + id = idHash[address]; + } + } + if (this.justAddedAddress) { this.deleteAddress(this.justAddedAddress); } From 94d2f6aabb58a34dcd6f0740d9ab4870eac91a86 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Thu, 13 Nov 2025 18:12:26 +0200 Subject: [PATCH 11/13] array field: override allowCustomOptions false --- client/src/views/fields/array.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/views/fields/array.js b/client/src/views/fields/array.js index fee07fe20e..432767bbbe 100644 --- a/client/src/views/fields/array.js +++ b/client/src/views/fields/array.js @@ -256,6 +256,10 @@ class ArrayFieldView extends BaseFieldView { this.allowCustomOptions = true; } + if (this.params.allowCustomOptions === false) { + this.allowCustomOptions = false; + } + if (this.type === 'array') { this.validations.push('noInputValue') } From 445ea1f240e10b5cf54783b10655cb44713f5bc1 Mon Sep 17 00:00:00 2001 From: Anton Slyzhko <88829366+antonslyzhko@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:51:47 +0200 Subject: [PATCH 12/13] Fix incorrect alias in subscriptionExclude join (#3520) --- application/Espo/Tools/Stream/UserRecordService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/Espo/Tools/Stream/UserRecordService.php b/application/Espo/Tools/Stream/UserRecordService.php index b347464891..22949f78ca 100644 --- a/application/Espo/Tools/Stream/UserRecordService.php +++ b/application/Espo/Tools/Stream/UserRecordService.php @@ -389,7 +389,7 @@ class UserRecordService [ 'entityType:' => 'parentType', 'entityId:' => 'parentId', - 'subscription.userId' => $user->getId(), + 'subscriptionExclude.userId' => $user->getId(), ] ) ->where([ From 5ce2e0b6dc65cadec945e2d442c9c5b8d9801fe3 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Fri, 14 Nov 2025 15:16:05 +0200 Subject: [PATCH 13/13] 9.2.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e121b6643b..00b7b40fca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "espocrm", - "version": "9.2.4", + "version": "9.2.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "espocrm", - "version": "9.2.4", + "version": "9.2.5", "hasInstallScript": true, "license": "AGPL-3.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 321e22f45d..cfcfa3dcb9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "espocrm", - "version": "9.2.4", + "version": "9.2.5", "description": "Open-source CRM.", "repository": { "type": "git",