/*
* 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/detail', 'pim:views/record/detail',
Dep => Dep.extend({
template: 'pim:product/record/detail',
catalogTreeData: null,
notSavedFields: ['image'],
isCatalogTreePanel: false,
setup() {
Dep.prototype.setup.call(this);
if (!this.model.isNew() && (this.type === 'detail' || this.type === 'edit') && this.getMetadata().get(['scopes', this.scope, 'advancedFilters'])) {
this.listenTo(this.model, 'main-image-updated', () => {
this.applyOverviewFilters();
});
}
if (!this.isWide && this.type !== 'editSmall' && this.type !== 'detailSmall'
&& this.getAcl().check('Catalog', 'read') && this.getAcl().check('Category', 'read')
&& this.getMetadata().get(['scopes', 'Product', 'catalogTreePanelActive'])) {
this.isCatalogTreePanel = true;
this.setupCatalogTreePanel();
}
},
setupCatalogTreePanel() {
this.createView('catalogTreePanel', 'pim:views/product/record/catalog-tree-panel', {
el: `${this.options.el} .catalog-tree-panel`,
scope: this.scope,
model: this.model
}, view => {
view.listenTo(view, 'select-category', data => this.navigateToList(data));
});
},
navigateToList(data) {
this.catalogTreeData = Espo.Utils.cloneDeep(data || {});
const options = {
isReturn: true,
callback: this.expandCatalogTree.bind(this)
};
this.getRouter().navigate(`#${this.scope}`);
this.getRouter().dispatch(this.scope, null, options);
},
expandCatalogTree(list) {
list.sortCollectionWithCatalogTree(this.catalogTreeData);
list.render();
},
data() {
return _.extend({
isCatalogTreePanel: this.isCatalogTreePanel
}, Dep.prototype.data.call(this))
},
applyOverviewFilters() {
// fields filter
this.fieldsFilter();
// multi-language fields filter
this.multiLangFieldsFilter();
// hide generic fields
this.genericFieldsFilter();
// trigger
this.model.trigger('overview-filters-applied');
},
getFilterFieldViews: function () {
let fields = {};
$.each(this.getFieldViews(), function (name, fieldView) {
if (!fieldView.model.getFieldParam(name, 'advancedFilterDisabled')) {
fields[name] = fieldView;
}
});
return fields;
},
fieldsFilter: function () {
// get filter param
let filter = (this.model.advancedEntityView || {}).fieldsFilter;
$.each(this.getFilterFieldViews(), (name, fieldView) => {
let actualFields = this.getFieldManager().getActualAttributeList(fieldView.model.getFieldType(name), name);
let actualFieldValues = actualFields.map(field => fieldView.model.get(field));
actualFieldValues = actualFieldValues.concat(this.getAlternativeValues(fieldView));
let hide = !actualFieldValues.every(value => this.checkFieldValue(filter, value, fieldView.isRequired()));
this.controlFieldVisibility(fieldView, hide);
});
},
multiLangFieldsFilter: function () {
// get locale
let locale = (this.model.advancedEntityView || {}).localesFilter;
$.each(this.getFilterFieldViews(), function (name, fieldView) {
let multilangLocale = fieldView.model.getFieldParam(name, 'multilangLocale');
if (multilangLocale !== null) {
if (locale !== null && locale !== '' && multilangLocale !== locale) {
fieldView.hide();
} else if (!fieldView.$el.hasClass('hidden')) {
fieldView.show();
}
}
});
},
genericFieldsFilter: function () {
// prepare is show param
let isShow = (this.model.advancedEntityView || {}).showGenericFields;
$.each(this.getFilterFieldViews(), (name, fieldView) => {
let field = fieldView.model.getFieldParam(name, 'multilangField');
const view = this.getFieldView(field);
if (field !== null && view) {
if (isShow && !view.$el.hasClass('hidden')) {
view.show();
} else {
view.hide();
}
}
});
},
hotKeySave: function (e) {
e.preventDefault();
if (this.mode === 'edit') {
this.actionSave();
} else {
let viewsFields = this.getFieldViews();
Object.keys(viewsFields).forEach(item => {
if (viewsFields[item].mode === "edit" ) {
viewsFields[item].inlineEditSave();
}
});
}
},
afterNotModified(notShow) {
if (!notShow) {
let msg = this.translate('notModified', 'messages');
Espo.Ui.warning(msg, 'warning');
}
this.enableButtons();
},
getBottomPanels() {
let bottomView = this.getView('bottom');
if (bottomView) {
return bottomView.nestedViews;
}
return null;
},
setDetailMode() {
let panels = this.getBottomPanels();
if (panels) {
for (let panel in panels) {
const view = panels[panel];
if (typeof view.setListMode === 'function' && (!view.mode || view.mode === 'edit')) {
view.setListMode();
}
}
}
Dep.prototype.setDetailMode.call(this);
},
setEditMode() {
let panels = this.getBottomPanels();
if (panels) {
for (let panel in panels) {
const view = panels[panel];
if (typeof view.setEditMode === 'function' && view.mode !== 'edit') {
view.setEditMode();
}
}
}
Dep.prototype.setEditMode.call(this);
},
cancelEdit() {
let panels = this.getBottomPanels();
if (panels) {
for (let panel in panels) {
const view = panels[panel];
if (typeof view.cancelEdit === 'function' && view.mode === 'edit') {
view.cancelEdit();
}
}
}
Dep.prototype.cancelEdit.call(this);
},
handlePanelsFetch() {
let changes = false;
let panels = this.getBottomPanels();
if (panels) {
for (let panel in panels) {
const view = panels[panel];
if (typeof view.panelFetch === 'function' && view.mode === 'edit') {
changes = view.panelFetch() || changes;
}
}
}
return changes;
},
validatePanels() {
let notValid = false;
let panels = this.getBottomPanels();
if (panels) {
for (let panel in panels) {
const view = panels[panel];
if (typeof view.validate === 'function' && view.mode === 'edit') {
notValid = view.validate() || notValid;
}
}
}
return notValid
},
handlePanelsSave() {
let panels = this.getBottomPanels();
if (panels) {
for (let panel in panels) {
const view = panels[panel];
if (typeof view.save === 'function' && view.mode === 'edit') {
view.save();
}
}
}
},
save(callback, skipExit) {
(this.notSavedFields || []).forEach(field => {
const keys = this.getFieldManager().getAttributeList(this.model.getFieldType(field), field);
keys.forEach(key => delete this.model.attributes[key]);
});
this.beforeBeforeSave();
let data = this.fetch();
let self = this;
let model = this.model;
let initialAttributes = this.attributes;
let beforeSaveAttributes = this.model.getClonedAttributes();
data = _.extend(Espo.Utils.cloneDeep(beforeSaveAttributes), data);
let gridInitPackages = false;
let packageView = false;
let bottomView = this.getView('bottom');
if (bottomView) {
packageView = bottomView.getView('productTypePackages');
if (packageView) {
gridInitPackages = packageView.getInitAttributes();
}
}
let attrs = false;
let gridPackages = false;
if (model.isNew()) {
attrs = data;
} else {
for (let name in data) {
if (name !== 'id'&& gridInitPackages && Object.keys(gridInitPackages).indexOf(name) > -1) {
if (!_.isEqual(gridInitPackages[name], data[name])) {
(gridPackages || (gridPackages = {}))[name] = data[name];
}
continue;
}
if (_.isEqual(initialAttributes[name], data[name])) {
continue;
}
(attrs || (attrs = {}))[name] = data[name];
}
}
let beforeSaveGridPackages = false;
if (gridPackages && packageView) {
let gridModel = packageView.getView('grid').model;
beforeSaveGridPackages = gridModel.getClonedAttributes();
gridModel.set(gridPackages, {silent: true})
}
if (attrs) {
model.set(attrs, {silent: true});
}
const panelsChanges = this.handlePanelsFetch();
const overviewValidation = this.validate();
const panelValidation = this.validatePanels();
if (overviewValidation || panelValidation) {
if (gridPackages && packageView && beforeSaveGridPackages) {
packageView.getView('grid').model.attributes = beforeSaveGridPackages;
}
model.attributes = beforeSaveAttributes;
this.trigger('cancel:save');
this.afterNotValid();
return;
}
if (gridPackages && packageView) {
packageView.save();
}
if (panelsChanges) {
this.handlePanelsSave();
}
if (!attrs) {
this.afterNotModified(gridPackages || panelsChanges);
this.trigger('cancel:save');
return true;
}
this.beforeSave();
this.trigger('before:save');
model.trigger('before:save');
model.save(attrs, {
success: function () {
this.afterSave();
if (self.isNew) {
self.isNew = false;
}
this.trigger('after:save');
model.trigger('after:save');
if (!callback) {
if (!skipExit) {
if (self.isNew) {
this.exit('create');
} else {
this.exit('save');
}
}
} else {
callback(this);
}
}.bind(this),
error: function (e, xhr) {
let r = xhr.getAllResponseHeaders();
let response = null;
if (xhr.status == 409) {
let header = xhr.getResponseHeader('X-Status-Reason');
try {
let response = JSON.parse(header);
} catch (e) {
console.error('Error while parsing response');
}
}
if (xhr.status == 400) {
if (!this.isNew) {
this.model.set(this.attributes);
}
}
if (response) {
if (response.reason == 'Duplicate') {
xhr.errorIsHandled = true;
self.showDuplicate(response.data);
}
}
this.afterSaveError();
model.attributes = beforeSaveAttributes;
self.trigger('cancel:save');
}.bind(this),
patch: !model.isNew()
});
return true;
}
})
);
|