PHP Classes

File: client/modules/pim/src/views/product/record/panels/product-attribute-values.js

Recommend this page to a friend!
  Classes of alex nov   KennerPIM   client/modules/pim/src/views/product/record/panels/product-attribute-values.js   Download  
File: client/modules/pim/src/views/product/record/panels/product-attribute-values.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: KennerPIM
Product information management application
Author: By
Last change:
Date: 1 year ago
Size: 32,466 bytes
 

Contents

Class file image Download
/* * Pim * Free Extension * Copyright (c) TreoLabs GmbH * Copyright (c) Kenner Soft Service GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ Espo.define('pim:views/product/record/panels/product-attribute-values', ['views/record/panels/relationship', 'views/record/panels/bottom', 'search-manager'], (Dep, BottomPanel, SearchManager) => Dep.extend({ template: 'pim:product/record/panels/product-attribute-values', baseSelectFields: [ 'channelsIds', 'channelsNames', 'data', 'attributeGroupId', 'attributeGroupName', 'attributeId', 'attributeName', 'isRequired', 'productFamilyAttributeId', 'scope', 'value' ], groupKey: 'attributeGroupId', groupLabel: 'attributeGroupName', groupScope: 'AttributeGroup', groupsWithoutId: ['no_group'], noGroup: { key: 'no_group', label: 'No Group' }, initialAttributes: null, boolFilterData: { notLinkedProductAttributeValues() { return { productId: this.model.id, scope: 'Global' } } }, events: _.extend({ 'click [data-action="unlinkAttributeGroup"]': function (e) { e.preventDefault(); e.stopPropagation(); let data = $(e.currentTarget).data(); this.unlinkAttributeGroup(data); } }, Dep.prototype.events), data() { return _.extend({ groups: this.groups, groupScope: this.groupScope }, Dep.prototype.data.call(this)); }, setup() { let bottomPanel = new BottomPanel(); bottomPanel.setup.call(this); this.link = this.link || this.defs.link || this.panelName; if (!this.scope && !(this.link in this.model.defs.links)) { throw new Error('Link \'' + this.link + '\' is not defined in model \'' + this.model.name + '\''); } this.title = this.title || this.translate(this.link, 'links', this.model.name); this.scope = this.scope || this.model.defs.links[this.link].entity; if (!this.getConfig().get('scopeColorsDisabled')) { var iconHtml = this.getHelper().getScopeColorIconHtml(this.scope); if (iconHtml) { if (this.defs.label) { this.titleHtml = iconHtml + this.translate(this.defs.label, 'labels', this.scope); } else { this.titleHtml = iconHtml + this.title; } } } var url = this.url || this.model.name + '/' + this.model.id + '/' + this.link; if (!this.readOnly && !this.defs.readOnly) { if (!('create' in this.defs)) { this.defs.create = true; } if (!('select' in this.defs)) { this.defs.select = true; } } this.filterList = this.defs.filterList || this.filterList || null; if (this.filterList && this.filterList.length) { this.filter = this.getStoredFilter(); } if (this.defs.create && this.getAcl().check('ProductAttributeValue', 'create')) { this.buttonList.push({ title: 'Create', action: this.defs.createAction || 'createRelated', link: this.link, acl: 'create', aclScope: this.scope, html: '<span class="fas fa-plus"></span>', data: { link: this.link, } }); } if (this.defs.select && this.getAcl().check('ProductAttributeValue', 'create')) { var data = {link: this.link}; if (this.defs.selectPrimaryFilterName) { data.primaryFilterName = this.defs.selectPrimaryFilterName; } if (this.defs.selectBoolFilterList) { data.boolFilterList = this.defs.selectBoolFilterList; } data.boolFilterListCallback = 'getSelectBoolFilterList'; data.boolFilterDataCallback = 'getSelectBoolFilterData'; data.afterSelectCallback = 'createProductAttributeValue'; data.scope = 'Attribute'; this.actionList.unshift({ label: 'Select', action: this.defs.selectAction || 'selectRelated', data: data, acl: 'edit', aclScope: this.model.name }); if (this.getAcl().check('AttributeGroup', 'read')) { this.actionList.push({ label: 'Select Attribute Group', action: 'selectAttributeGroup' }); } } this.setupActions(); var layoutName = 'listSmall'; this.setupListLayout(); if (this.listLayoutName) { layoutName = this.listLayoutName; } var listLayout = null; var layout = this.defs.layout || null; if (layout) { if (typeof layout == 'string') { layoutName = layout; } else { layoutName = 'listRelationshipCustom'; listLayout = layout; } } this.layoutName = layoutName; this.listLayout = listLayout; var sortBy = this.defs.sortBy || null; var asc = this.defs.asc || null; if (this.defs.orderBy) { sortBy = this.defs.orderBy; asc = true; if (this.defs.orderDirection) { if (this.defs.orderDirection && (this.defs.orderDirection === true || this.defs.orderDirection.toLowerCase() === 'DESC')) { asc = false; } } } this.wait(true); this.getCollectionFactory().create(this.scope, function (collection) { collection.maxSize = 200; if (this.defs.filters) { var searchManager = new SearchManager(collection, 'listRelationship', false, this.getDateTime()); searchManager.setAdvanced(this.defs.filters); collection.where = searchManager.getWhere(); } collection.url = collection.urlRoot = url; if (sortBy) { collection.sortBy = sortBy; } if (asc) { collection.asc = asc; } this.collection = collection; this.setFilter(this.filter); this.updateBaseSelectFields(); this.listenTo(this.model, 'updateAttributes change:productFamilyId update-all after:relate after:unrelate after:attributesSave', link => { if (!link || link === 'productAttributeValues') { this.actionRefresh(); } }); if (this.getMetadata().get(['scopes', this.model.name, 'advancedFilters'])) { this.listenTo(this.model, 'overview-filters-changed', () => { this.applyOverviewFilters(); }); } this.getMetadata().fetch(); this.fetchCollectionGroups(() => this.wait(false)); }, this); this.setupFilterActions(); }, updateBaseSelectFields() { (this.defs.baseSelectFields || []).forEach(field => { if (!this.baseSelectFields.includes(field)) { this.baseSelectFields.push(field); } }); let inputLanguageList = this.getConfig().get('inputLanguageList') || []; if (this.getConfig().get('isMultilangActive') && inputLanguageList.length) { inputLanguageList.forEach(lang => { let field = lang.split('_').reduce((prev, curr) => prev + Espo.Utils.upperCaseFirst(curr.toLocaleLowerCase()), 'value'); if (!this.baseSelectFields.includes(field)) { this.baseSelectFields.push(field); } }); } }, createProductAttributeValue(selectObj) { let promises = []; selectObj.forEach(attributeModel => { this.getModelFactory().create(this.scope, model => { model.setRelate({ model: this.model, link: this.model.defs.links[this.link].foreign }); model.setRelate({ model: attributeModel, link: attributeModel.defs.links[this.link].foreign }); let attributes = { assignedUserId: this.getUser().id, assignedUserName: this.getUser().get('name'), scope: 'Global' }; model.set(attributes); promises.push(model.save()); }); }); Promise.all(promises).then(() => { this.notify('Linked', 'success'); this.model.trigger('after:relate', 'productAttributeValues'); }); }, actionSelectAttributeGroup() { const scope = 'AttributeGroup'; const viewName = this.getMetadata().get(['clientDefs', scope, 'modalViews', 'select']) || 'views/modals/select-records'; this.notify('Loading...'); this.createView('dialog', viewName, { scope: scope, multiple: true, createButton: false, massRelateEnabled: false, boolFilterList: ['withNotLinkedAttributesToProduct'], boolFilterData: {withNotLinkedAttributesToProduct: this.model.id}, whereAdditional: [ { type: 'isLinked', attribute: 'attributes' } ] }, dialog => { dialog.render(); this.notify(false); dialog.once('select', selectObj => { this.notify('Loading...'); if (!Array.isArray(selectObj)) { return; } let boolFilterList = this.getSelectBoolFilterList() || []; this.getFullEntityList('Attribute', { where: [ { type: 'bool', value: boolFilterList, data: this.getSelectBoolFilterData(boolFilterList) }, { attribute: 'attributeGroupId', type: 'in', value: selectObj.map(model => model.id) } ] }, list => { let models = []; list.forEach(attributes => { this.getModelFactory().create('Attribute', model => { model.set(attributes); models.push(model); }); }); this.createProductAttributeValue(models); }); }); }); }, getFullEntityList(url, params, callback, container) { if (url) { container = container || []; let options = params || {}; options.maxSize = options.maxSize || 200; options.offset = options.offset || 0; this.ajaxGetRequest(url, options).then(response => { container = container.concat(response.list || []); options.offset = container.length; if (response.total > container.length || response.total === -1) { this.getFullEntity(url, options, callback, container); } else { callback(container); } }); } }, afterRender() { Dep.prototype.afterRender.call(this); this.buildGroups(); if (this.mode === 'edit') { this.setEditMode(); } }, fetchCollectionGroups(callback) { this.collection.data.select = this.getSelectFields().join(','); this.collection.reset(); this.fetchCollectionPart(() => { this.groups = []; this.groups = this.getGroupsFromCollection(); let valueKeys = this.groups.map(group => group.key); this.getCollectionFactory().create('AttributeGroup', collection => { this.attributeGroupCollection = collection; collection.select = 'sortOrder'; collection.maxSize = 200; collection.offset = 0; collection.whereAdditional = [ { attribute: 'id', type: 'in', value: valueKeys } ]; collection.fetch().then(() => { this.applySortingForAttributeGroups(); if (callback) { callback(); } }); }); }); }, applySortingForAttributeGroups() { this.groups.forEach(item => { let sortOder = 0; let attributeGroup = this.attributeGroupCollection.find(model => model.id === item.key); if (attributeGroup) { sortOder = attributeGroup.get('sortOrder'); } item.sortOrder = item.sortOrder || sortOder; }); let noGroup = this.groups.find(item => item.key === 'no_group'); if (noGroup) { noGroup.sortOrder = Math.max(...this.groups.map(group => group.sortOrder)) + 1; } this.groups.sort(function (a, b) { return a.sortOrder - b.sortOrder; }); }, getSelectFields() { return this.baseSelectFields || []; }, fetchCollectionPart(callback) { this.collection.fetch({remove: false, more: true}).then((response) => { if (this.collection.total > this.collection.length) { this.fetchCollectionPart(callback); } else if (callback) { callback(); } }); }, getGroupsFromCollection() { let groups = []; this.collection.forEach(model => { let params = this.getGroupParams(model); this.setGroup(params, model, groups); }); return groups; }, getGroupParams(model) { let key = model.get(this.groupKey); if (!key) { key = this.noGroup.key; } let label = model.get(this.groupLabel); if (!label) { label = this.translate(this.noGroup.label, 'labels', 'Product'); } return { key: key, label: label }; }, setGroup(params, model, groups) { let group = groups.find(item => item.key === params.key); if (group) { group.editable = group.editable && model.get('isCustom'); group.rowList.push(model.id); group.rowList.sort((a, b) => this.collection.get(a).get('sortOrder') - this.collection.get(b).get('sortOrder')); } else { groups.push({ key: params.key, id: !this.groupsWithoutId.includes(params.key) ? params.key : null, label: params.label, rowList: [model.id], editable: model.get('isCustom') }); } }, buildGroups() { let count = 0; this.groups.forEach(group => { this.getCollectionFactory().create(this.scope, collection => { group.rowList.forEach(id => { collection.add(this.collection.get(id)); }); this.setGroupCollectionDefs(group, collection); this.listenTo(collection, 'sync', () => { this.initialAttributes = this.getInitialAttributes(); this.model.trigger('attributes-updated'); collection.models.sort((a, b) => a.get('sortOrder') - b.get('sortOrder')); if (this.getMetadata().get(['scopes', this.model.name, 'advancedFilters'])) { this.applyOverviewFilters(); } }); let viewName = this.defs.recordListView || this.getMetadata().get('clientDefs.' + this.scope + '.recordViews.list') || 'Record.List'; let options = { collection: collection, layoutName: this.layoutName, listLayout: this.listLayout, checkboxes: false, rowActionsView: this.defs.readOnly ? false : (this.defs.rowActionsView || this.rowActionsView), buttonsDisabled: true, el: `${this.options.el} .group[data-name="${group.key}"] .list-container`, showMore: false }; this.createView(group.key, viewName, this.modifyListOptions(options), view => { if (this.getMetadata().get(['scopes', this.model.name, 'advancedFilters'])) { view.listenTo(view, 'after:render', () => this.applyOverviewFilters()); } view.render(() => { count++; if (count === this.groups.length) { this.trigger('groups-rendered'); } }); }); }); }); }, setGroupCollectionDefs(group, collection) { collection.url = `Product/${this.model.id}/productAttributeValues`; collection.where = [ { type: 'bool', value: ['linkedWithAttributeGroup'], data: { linkedWithAttributeGroup: { productId: this.model.id, attributeGroupId: group.key !== 'no_group' ? group.key : null } } } ]; collection.data.select = this.getSelectFields().join(','); }, modifyListOptions(options) { return options; }, applyOverviewFilters() { let currentFieldFilter = (this.model.advancedEntityView || {}).fieldsFilter; let attributesWithChannelScope = []; let fields = this.getValueFields(); Object.keys(fields).forEach(name => { let fieldView = fields[name]; let hide = !this.checkFieldValue(currentFieldFilter, fieldView.model.get(fieldView.name), fieldView.model.get('isRequired')); if (!hide) { hide = this.updateCheckByChannelFilter(fieldView, attributesWithChannelScope); } if (!hide && this.getConfig().get('isMultilangActive') && (this.getConfig().get('inputLanguageList') || []).length) { hide = this.updateCheckByLocaleFilter(fieldView, currentFieldFilter); } this.controlRowVisibility(fieldView, name, hide); }); this.hideChannelAttributesWithGlobalScope(fields, attributesWithChannelScope); }, updateCheckByChannelFilter(fieldView, attributesWithChannelScope) { let hide = false; let currentChannelFilter = (this.model.advancedEntityView || {}).channelsFilter; if (currentChannelFilter) { if (currentChannelFilter === 'onlyGlobalScope') { hide = fieldView.model.get('scope') !== 'Global'; } else { hide = (fieldView.model.get('scope') === 'Channel' && !(fieldView.model.get('channelsIds') || []).includes(currentChannelFilter)); if ((fieldView.model.get('channelsIds') || []).includes(currentChannelFilter)) { attributesWithChannelScope.push(fieldView.model.get('attributeId')); } } } return hide; }, updateCheckByLocaleFilter(fieldView, currentFieldFilter) { let isShowGeneric = (this.model.advancedEntityView || {}).showGenericFields; if (!isShowGeneric && fieldView.model.get('locale') === null) { return true; } let localeFilter = (this.model.advancedEntityView || {}).localesFilter; let fieldLocale = fieldView.model.get('locale'); if (localeFilter !== null && localeFilter !== '' && localeFilter !== fieldLocale && fieldLocale !== null) { return true; } return false; }, getValueFields() { let fields = {}; this.groups.forEach(group => { let groupView = this.getView(group.key); if (groupView) { groupView.rowList.forEach(row => { let rowView = groupView.getView(row); if (rowView) { let containerView = rowView.getView('valueField'); if (containerView) { let fieldView = containerView.getView('valueField'); fieldView.groupKey = group.key; fields[row] = fieldView; } } }); } }); return fields; }, checkFieldValue(currentFieldFilter, value, required) { let check = !currentFieldFilter; if (currentFieldFilter === 'empty') { check = value === null || value === '' || (Array.isArray(value) && !value.length); } if (currentFieldFilter === 'emptyAndRequired') { check = (value === null || value === '' || (Array.isArray(value) && !value.length)) && required; } return check; }, controlRowVisibility(fieldView, rowId, hide) { let groupView = this.getView(fieldView.groupKey); let rowView = groupView.getView(rowId); if (hide) { rowView.$el.addClass('hidden'); } else { rowView.$el.removeClass('hidden'); } this.controlGroupVisibility(groupView); }, controlGroupVisibility(groupView) { if (groupView.$el.find('.list-row.hidden').size() === (groupView.rowList || []).length) { groupView.$el.parent().addClass('hidden'); } else { groupView.$el.parent().removeClass('hidden'); } }, hideChannelAttributesWithGlobalScope(fields, attributesWithChannelScope) { Object.keys(fields).forEach(name => { let fieldView = fields[name]; if (attributesWithChannelScope.includes(fieldView.model.get('attributeId')) && fieldView.model.get('scope') === 'Global') { this.controlRowVisibility(fieldView, name, true); } }); }, getSelectBoolFilterData(boolFilterList) { let data = {}; if (Array.isArray(boolFilterList)) { boolFilterList.forEach(item => { if (this.boolFilterData && typeof this.boolFilterData[item] === 'function') { data[item] = this.boolFilterData[item].call(this); } }); } return data; }, getSelectBoolFilterList() { return this.defs.selectBoolFilterList || null }, actionRefresh() { Object.keys(this.nestedViews).forEach(view => this.clearView(view)); this.getMetadata().fetch(); this.fetchCollectionGroups(() => { this.reRender(); }); }, unlinkAttributeGroup(data) { let id = data.id; if (!id) { return; } let group = this.groups.find(group => group.id == id); if (!group || !group.rowList) { return; } this.confirm({ message: this.translate('unlinkAttributeGroupConfirmation', 'messages', 'AttributeGroup'), confirmText: this.translate('Unlink') }, function () { this.notify('Unlinking...'); $.ajax({ url: `${this.model.name}/${this.link}/relation`, data: JSON.stringify({ ids: [this.model.id], foreignIds: group.rowList }), type: 'DELETE', contentType: 'application/json', success: function () { this.notify('Unlinked', 'success'); this.model.trigger('after:unrelate'); this.actionRefresh(); }.bind(this), error: function () { this.notify('Error occurred', 'error'); }.bind(this), }); }, this); }, setListMode() { this.mode = 'list'; this.groups.forEach(group => { let groupView = this.getView(group.key); if (groupView) { groupView.setListMode(); } }); this.reRender(); }, setEditMode() { this.initialAttributes = this.getInitialAttributes(); const groupsRendered = this.groups.every(group => { const groupView = this.getView(group.key); return groupView && groupView.isRendered(); }); const updateMode = () => { this.mode = 'edit'; this.groups.forEach(group => { let groupView = this.getView(group.key); if (groupView) { groupView.setEditMode(); } }); }; if (groupsRendered) { updateMode(); } else { this.listenToOnce(this, 'groups-rendered', () => updateMode()); } }, cancelEdit() { this.actionRefresh(); }, getInitialAttributes() { const data = {}; this.collection.forEach(model => { const modelData = { value: model.get('value') }; const actualFields = this.getFieldManager().getActualAttributeList(model.get('attributeType'), 'value'); actualFields.forEach(field => { if (model.has(field)) { _.extend(modelData, {[field]: model.get(field)}); } }); const additionalData = model.get('data'); if (additionalData) { modelData.data = additionalData; } data[model.id] = Espo.Utils.cloneDeep(modelData); }); return data; }, panelFetch() { let data = false; this.groups.forEach(group => { const groupView = this.getView(group.key); (groupView.rowList || []).forEach(id => { const row = groupView.getView(id); const value = row.getView('valueField'); if (value.mode === 'edit') { const fetchedData = value.fetch(); const initialData = this.initialAttributes[id]; value.model.set(fetchedData); if (this.equalityValueCheck(fetchedData, initialData)) { data = _.extend(data || {}, {[id]: fetchedData}); } } }); }); return data; }, equalityValueCheck(fetchedData, initialData) { return !_.isEqual(initialData, fetchedData) && (Object.keys(fetchedData).every(key => { const initial = initialData[key]; const fetched = fetchedData[key]; return (Array.isArray(initial) ? initial.length : initial) || (Array.isArray(fetched) ? fetched.length : fetched); })); }, save() { const data = this.panelFetch(); if (data) { const promises = []; $.each(data, (id, attrs) => { this.collection.get(id).set(attrs, {silent: true}); promises.push(this.ajaxPutRequest(`${this.collection.name}/${id}`, attrs)) }); this.notify('Saving...'); Promise.all(promises) .then(response => { this.notify('Saved', 'success'); this.model.trigger('after:attributesSave'); }, error => { this.actionRefresh(); }); } }, validate() { this.trigger('collapsePanel', 'show'); let notValid = false; this.groups.forEach(group => { const groupView = this.getView(group.key); (groupView.rowList || []).forEach(id => { const row = groupView.getView(id); const value = row.getView('valueField'); if (value.mode === 'edit' && !value.disabled && !value.readOnly) { notValid = value.validate() || notValid; } }); }); return notValid; } }) );