diff --git a/client/src/views/fields/link-multiple.js b/client/src/views/fields/link-multiple.js index 88f8fedfdf..8e7e54c04b 100644 --- a/client/src/views/fields/link-multiple.js +++ b/client/src/views/fields/link-multiple.js @@ -331,6 +331,10 @@ class LinkMultipleFieldView extends BaseFieldView { this.$element.get(0).focus({preventScroll: true}); }; } + + /** @type {Object.} */ + this.panelDefs = this.getMetadata() + .get(['clientDefs', this.entityType, 'relationshipPanels', this.name]) || {}; } /** @@ -385,7 +389,7 @@ class LinkMultipleFieldView extends BaseFieldView { * Compose an autocomplete URL. Can be extended. * * @protected - * @return {string} + * @return {string|Promise} */ getAutocompleteUrl() { let url = this.foreignScope + '?&maxSize=' + this.getAutocompleteMaxCount(); @@ -407,20 +411,36 @@ class LinkMultipleFieldView extends BaseFieldView { url += '&select=' + select.join(',') } - /** @var {Object.} */ - const panelDefs = this.getMetadata() - .get(['clientDefs', this.entityType, 'relationshipPanels', this.name]) || {}; + if (this.panelDefs.selectHandler) { + return new Promise(resolve => { + this._getSelectFilters().then(filters => { + if (filters.bool) { + url += '&' + $.param({'boolFilterList': filters.bool}); + } + + if (filters.primary) { + url += '&' + $.param({'primaryFilter': filters.primary}); + } + + if (filters.advanced) { + url += '&' + $.param({'advanced': filters.advanced}); + } + + resolve(url); + }); + }); + } const boolList = [ ...(this.getSelectBoolFilterList() || []), - ...(panelDefs.selectBoolFilterList || []), + ...(this.panelDefs.selectBoolFilterList || []), ]; if (boolList.length) { url += '&' + $.param({'boolFilterList': boolList}); } - const primary = this.getSelectPrimaryFilterName() || panelDefs.selectPrimaryFilterName; + const primary = this.getSelectPrimaryFilterName() || this.panelDefs.selectPrimaryFilterName; if (primary) { url += '&' + $.param({'primaryFilter': primary}); @@ -444,8 +464,15 @@ class LinkMultipleFieldView extends BaseFieldView { const minChar = this.autocompleteOnEmpty ? 0 : 1; this.$element.autocomplete({ - serviceUrl: () => { - return this.getAutocompleteUrl(); + lookup: (q, callback) => { + Promise.resolve(this.getAutocompleteUrl(q)) + .then(url => { + Espo.Ajax + .getRequest(url, {q: q}) + .then(response => { + callback(this._transformAutocompleteResult(response)); + }); + }); }, minChars: minChar, paramName: 'q', @@ -876,9 +903,7 @@ class LinkMultipleFieldView extends BaseFieldView { actionSelect() { Espo.Ui.notify(' ... '); - /** @var {Object.} */ - const panelDefs = this.getMetadata() - .get(['clientDefs', this.entityType, 'relationshipPanels', this.name]) || {}; + const panelDefs = this.panelDefs; const viewName = panelDefs.selectModalView || this.getMetadata().get(`clientDefs.${this.foreignScope}.modalViews.select`) || @@ -887,9 +912,7 @@ class LinkMultipleFieldView extends BaseFieldView { const mandatorySelectAttributeList = this.mandatorySelectAttributeList || panelDefs.selectMandatoryAttributeList; - const handler = panelDefs.selectHandler || null; - - let createButton = this.isEditMode() && + const createButton = this.isEditMode() && (!this.createDisabled && !panelDefs.createDisabled || this.forceCreateButton); let createAttributesProvider = null; @@ -918,40 +941,13 @@ class LinkMultipleFieldView extends BaseFieldView { }; } - new Promise(resolve => { - if (!handler || this.isSearchMode()) { - resolve({}); - - return; - } - - Espo.loader.requirePromise(handler) - .then(Handler => new Handler(this.getHelper())) - .then(/** module:handlers/select-related */handler => { - handler.getFilters(this.model) - .then(filters => resolve(filters)); - }); - }).then(filters => { - const advanced = {...(this.getSelectFilters() || {}), ...(filters.advanced || {})}; - const primaryFilter = this.getSelectPrimaryFilterName() || - filters.primary || panelDefs.selectPrimaryFilterName; - - const localBoolFilterList = this.getSelectBoolFilterList(); - - const boolFilterList = (localBoolFilterList || filters.bool || panelDefs.selectBoolFilterList) ? - [ - ...(localBoolFilterList || []), - ...(filters.bool || []), - ...(panelDefs.selectBoolFilterList || []), - ] : - undefined; - + this._getSelectFilters().then(filters => { this.createView('dialog', viewName, { scope: this.foreignScope, createButton: createButton, - filters: advanced, - boolFilterList: boolFilterList, - primaryFilterName: primaryFilter, + filters: filters.advanced, + boolFilterList: filters.bool, + primaryFilterName: filters.primary, filterList: this.getSelectFilterList(), multiple: true, mandatorySelectAttributeList: mandatorySelectAttributeList, @@ -976,6 +972,66 @@ class LinkMultipleFieldView extends BaseFieldView { }); }); } + + /** + * @private + * @return {Promise<{bool?: string[], advanced?: Object, primary?: string}>} + */ + _getSelectFilters() { + const handler = this.panelDefs.selectHandler; + + if (!handler || this.isSearchMode()) { + return Promise.resolve({}); + } + + return new Promise(resolve => { + Espo.loader.requirePromise(handler) + .then(Handler => new Handler(this.getHelper())) + .then(/** module:handlers/select-related */handler => { + return handler.getFilters(this.model); + }) + .then(filters => { + const advanced = {...(this.getSelectFilters() || {}), ...(filters.advanced || {})}; + const primaryFilter = this.getSelectPrimaryFilterName() || + filters.primary || this.panelDefs.selectPrimaryFilterName; + + const localBoolFilterList = this.getSelectBoolFilterList(); + + const boolFilterList = (localBoolFilterList || filters.bool || this.panelDefs.selectBoolFilterList) ? + [ + ...(localBoolFilterList || []), + ...(filters.bool || []), + ...(this.panelDefs.selectBoolFilterList || []), + ] : + undefined; + + resolve({ + bool: boolFilterList, + primary: primaryFilter, + advanced: advanced, + }); + }); + }); + } + + /** + * @private + */ + _transformAutocompleteResult(response) { + const list = []; + + response.list.forEach(item => { + list.push({ + id: item.id, + name: item.name || item.id, + data: item.id, + value: item.name || item.id, + attributes: item, + }); + }); + + return {suggestions: list}; + } } export default LinkMultipleFieldView; diff --git a/client/src/views/fields/link.js b/client/src/views/fields/link.js index df21a10e3a..73042d5ed7 100644 --- a/client/src/views/fields/link.js +++ b/client/src/views/fields/link.js @@ -162,8 +162,6 @@ class LinkFieldView extends BaseFieldView { */ mandatorySelectAttributeList = null - getEmptyAutocompleteResult = null - /** * Trigger autocomplete on empty input. * @@ -464,7 +462,7 @@ class LinkFieldView extends BaseFieldView { * Compose an autocomplete URL. Can be extended. * * @protected - * @return {string} + * @return {string|Promise} */ getAutocompleteUrl() { let url = this.foreignScope + '?maxSize=' + this.getAutocompleteMaxCount(); @@ -482,13 +480,36 @@ class LinkFieldView extends BaseFieldView { url += '&select=' + select.join(','); } - const boolList = this.getSelectBoolFilterList(); + if (this.panelDefs.selectHandler) { + return new Promise(resolve => { + this._getSelectFilters().then(filters => { + if (filters.bool) { + url += '&' + $.param({'boolFilterList': filters.bool}); + } - if (boolList) { - url += '&' + $.param({'boolFilterList': boolList}); + if (filters.primary) { + url += '&' + $.param({'primaryFilter': filters.primary}); + } + + if (filters.advanced) { + url += '&' + $.param({'advanced': filters.advanced}); + } + + resolve(url); + }); + }); } - const primary = this.getSelectPrimaryFilterName(); + const boolList = [ + ...(this.getSelectBoolFilterList() || []), + ...(this.panelDefs.selectBoolFilterList || []), + ]; + + const primary = this.getSelectPrimaryFilterName() || this.panelDefs.selectPrimaryFilterName; + + if (boolList.length) { + url += '&' + $.param({'boolFilterList': boolList}); + } if (primary) { url += '&' + $.param({'primaryFilter': primary}); @@ -526,7 +547,7 @@ class LinkFieldView extends BaseFieldView { if (!this.autocompleteDisabled) { let isEmptyQueryResult = false; - if (this.getEmptyAutocompleteResult) { + if (this.getEmptyAutocompleteResult()) { this.$elementName.on('keydown', e => { if (e.code === 'Tab' && isEmptyQueryResult) { e.stopImmediatePropagation(); @@ -540,17 +561,14 @@ class LinkFieldView extends BaseFieldView { $c.addClass('small'); } }, - serviceUrl: q => { - return this.getAutocompleteUrl(q); - }, lookup: (q, callback) => { if (!this.autocompleteOnEmpty && q.length === 0) { isEmptyQueryResult = true; - if (this.getEmptyAutocompleteResult) { - callback( - this._transformAutocompleteResult(this.getEmptyAutocompleteResult()) - ); + const emptyResult = this.getEmptyAutocompleteResult(); + + if (emptyResult) { + callback(this._transformAutocompleteResult(emptyResult)); } return; @@ -558,10 +576,13 @@ class LinkFieldView extends BaseFieldView { isEmptyQueryResult = false; - Espo.Ajax - .getRequest(this.getAutocompleteUrl(q), {q: q}) - .then(response => { - callback(this._transformAutocompleteResult(response)); + Promise.resolve(this.getAutocompleteUrl(q)) + .then(url => { + Espo.Ajax + .getRequest(url, {q: q}) + .then(response => { + callback(this._transformAutocompleteResult(response)); + }); }); }, minChars: 0, @@ -670,7 +691,7 @@ class LinkFieldView extends BaseFieldView { * @private */ _transformAutocompleteResult(response) { - let list = []; + const list = []; response.list.forEach(item => { list.push({ @@ -978,8 +999,6 @@ class LinkFieldView extends BaseFieldView { const mandatorySelectAttributeList = this.mandatorySelectAttributeList || panelDefs.selectMandatoryAttributeList; - const handler = panelDefs.selectHandler || null; - const createButton = this.isEditMode() && (!this.createDisabled && !panelDefs.createDisabled || this.forceCreateButton); @@ -1009,40 +1028,13 @@ class LinkFieldView extends BaseFieldView { }; } - new Promise(resolve => { - if (!handler || this.isSearchMode()) { - resolve({}); - - return; - } - - Espo.loader.requirePromise(handler) - .then(Handler => new Handler(this.getHelper())) - .then(/** module:handlers/select-related */handler => { - handler.getFilters(this.model) - .then(filters => resolve(filters)); - }); - }).then(filters => { - const advanced = {...(this.getSelectFilters() || {}), ...(filters.advanced || {})}; - const primaryFilter = this.getSelectPrimaryFilterName() || - filters.primary || panelDefs.selectPrimaryFilterName; - - const localBoolFilterList = this.getSelectBoolFilterList(); - - const boolFilterList = (localBoolFilterList || filters.bool || panelDefs.selectBoolFilterList) ? - [ - ...(localBoolFilterList || []), - ...(filters.bool || []), - ...(panelDefs.selectBoolFilterList || []), - ] : - undefined; - + this._getSelectFilters().then(filters => { this.createView('dialog', viewName, { scope: this.foreignScope, createButton: createButton, - filters: advanced, - boolFilterList: boolFilterList, - primaryFilterName: primaryFilter, + filters: filters.advanced, + boolFilterList: filters.bool, + primaryFilterName: filters.primary, mandatorySelectAttributeList: mandatorySelectAttributeList, forceSelectAllAttributes: this.forceSelectAllAttributes, filterList: this.getSelectFilterList(), @@ -1061,6 +1053,47 @@ class LinkFieldView extends BaseFieldView { }); } + /** + * @private + * @return {Promise<{bool?: string[], advanced?: Object, primary?: string}>} + */ + _getSelectFilters() { + const handler = this.panelDefs.selectHandler; + + if (!handler || this.isSearchMode()) { + return Promise.resolve({}); + } + + return new Promise(resolve => { + Espo.loader.requirePromise(handler) + .then(Handler => new Handler(this.getHelper())) + .then(/** module:handlers/select-related */handler => { + return handler.getFilters(this.model); + }) + .then(filters => { + const advanced = {...(this.getSelectFilters() || {}), ...(filters.advanced || {})}; + const primaryFilter = this.getSelectPrimaryFilterName() || + filters.primary || this.panelDefs.selectPrimaryFilterName; + + const localBoolFilterList = this.getSelectBoolFilterList(); + + const boolFilterList = (localBoolFilterList || filters.bool || this.panelDefs.selectBoolFilterList) ? + [ + ...(localBoolFilterList || []), + ...(filters.bool || []), + ...(this.panelDefs.selectBoolFilterList || []), + ] : + undefined; + + resolve({ + bool: boolFilterList, + primary: primaryFilter, + advanced: advanced, + }); + }); + }); + } + actionSelectOneOf() { Espo.Ui.notify(' ... '); @@ -1093,6 +1126,10 @@ class LinkFieldView extends BaseFieldView { }); }); } + + getEmptyAutocompleteResult() { + return undefined; + } } export default LinkFieldView;