소재지 ₍₍◝(・'ω'・)◟⁾⁾ 🐟️?看XM(^_−)☆哈先看看刚看过卡卡国看过了回来冷藏柜好极过估计
PNG %k25u25%fgd5n!/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM - Open Source CRM application.
* Copyright (C) 2014-2023 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* EspoCRM 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.
*
* EspoCRM 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 EspoCRM. If not, see http://www.gnu.org/licenses/.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU General Public License version 3.
*
* In accordance with Section 7(b) of the GNU General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
/** @module views/modals/detail */
import ModalView from 'views/modal';
import ActionItemSetup from 'helpers/action-item-setup';
import Backbone from 'backbone';
/**
* A quick view modal.
*/
class DetailModalView extends ModalView {
template = 'modals/detail'
cssName = 'detail-modal'
className = 'dialog dialog-record'
editDisabled = false
fullFormDisabled = false
detailView = null
removeDisabled = true
backdrop = true
fitHeight = true
sideDisabled = false
bottomDisabled = false
fixedHeaderHeight = true
flexibleHeaderFontSize = true
duplicateAction = false
shortcutKeys = {
/** @this DetailModalView */
'Control+Space': function (e) {
if (this.editDisabled) {
return;
}
if (e.target.tagName === 'TEXTAREA' || e.target.tagName === 'INPUT') {
return;
}
if (this.buttonList.findIndex(item => item.name === 'edit') === -1) {
return;
}
e.stopPropagation();
e.preventDefault();
this.actionEdit()
.then(view => {
view.$el
.find('.form-control:not([disabled])')
.first()
.focus();
});
},
/** @this DetailModalView */
'Control+Backslash': function (e) {
this.getRecordView().handleShortcutKeyControlBackslash(e);
},
/** @this DetailModalView */
'Control+ArrowLeft': function (e) {
this.handleShortcutKeyControlArrowLeft(e);
},
/** @this DetailModalView */
'Control+ArrowRight': function (e) {
this.handleShortcutKeyControlArrowRight(e);
},
}
setup() {
this.scope = this.scope || this.options.scope;
this.id = this.options.id;
this.buttonList = [];
if ('editDisabled' in this.options) {
this.editDisabled = this.options.editDisabled;
}
if ('removeDisabled' in this.options) {
this.removeDisabled = this.options.removeDisabled;
}
this.editDisabled = this.getMetadata().get(['clientDefs', this.scope, 'editDisabled']) ||
this.editDisabled;
this.removeDisabled = this.getMetadata().get(['clientDefs', this.scope, 'removeDisabled']) ||
this.removeDisabled;
this.fullFormDisabled = this.options.fullFormDisabled || this.fullFormDisabled;
this.layoutName = this.options.layoutName || this.layoutName;
this.setupRecordButtons();
if (this.model) {
this.controlRecordButtonsVisibility();
}
if (!this.fullFormDisabled) {
this.buttonList.push({
name: 'fullForm',
label: 'Full Form',
});
}
this.buttonList.push({
name: 'cancel',
label: 'Close',
title: 'Esc',
});
if (this.model && this.model.collection && !this.navigateButtonsDisabled) {
this.buttonList.push({
name: 'previous',
html: '',
title: this.translate('Previous Entry'),
position: 'right',
className: 'btn-icon',
style: 'text',
disabled: true,
});
this.buttonList.push({
name: 'next',
html: '',
title: this.translate('Next Entry'),
position: 'right',
className: 'btn-icon',
style: 'text',
disabled: true,
});
this.indexOfRecord = this.model.collection.indexOf(this.model);
}
else {
this.navigateButtonsDisabled = true;
}
this.waitForView('record');
this.sourceModel = this.model;
this.getModelFactory().create(this.scope).then(model => {
if (!this.sourceModel) {
this.model = model;
this.model.id = this.id;
this.setupAfterModelCreated();
this.listenTo(this.model, 'sync', () => {
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
this.listenToOnce(this.model, 'sync', () => {
this.setupActionItems();
this.createRecordView();
});
this.model.fetch();
return;
}
this.model = this.sourceModel.clone();
this.model.collection = this.sourceModel.collection.clone();
this.setupAfterModelCreated();
this.listenTo(this.model, 'change', () => {
this.sourceModel.set(this.model.getClonedAttributes());
});
this.listenTo(this.model, 'sync', () => {
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
this.once('after:render', () => {
this.model.fetch();
});
this.setupActionItems();
this.createRecordView();
});
this.listenToOnce(this.getRouter(), 'routed', () => {
this.remove();
});
if (this.duplicateAction && this.getAcl().checkScope(this.scope, 'create')) {
this.addDropdownItem({
name: 'duplicate',
label: 'Duplicate',
});
}
}
/** @private */
setupActionItems() {
let actionItemSetup = new ActionItemSetup(
this.getMetadata(),
this.getHelper(),
this.getAcl(),
this.getLanguage()
);
actionItemSetup.setup(
this,
'modalDetail',
promise => this.wait(promise),
item => this.addDropdownItem(item),
name => this.showActionItem(name),
name => this.hideActionItem(name),
{listenToViewModelSync: true}
);
}
/**
* @protected
*/
setupAfterModelCreated() {}
/**
* @protected
*/
setupRecordButtons() {
if (!this.removeDisabled) {
this.addRemoveButton();
}
if (!this.editDisabled) {
this.addEditButton();
}
}
controlRecordButtonsVisibility() {
if (this.getAcl().check(this.model, 'edit')) {
this.showButton('edit');
} else {
this.hideButton('edit');
}
if (this.getAcl().check(this.model, 'delete')) {
this.showActionItem('remove');
} else {
this.hideActionItem('remove');
}
}
addEditButton() {
this.addButton({
name: 'edit',
label: 'Edit',
title: 'Ctrl+Space',
}, true);
}
removeEditButton() {
this.removeButton('edit');
}
addRemoveButton() {
this.addDropdownItem({
name: 'remove',
label: 'Remove',
});
}
removeRemoveButton() {
this.removeButton('remove');
}
getScope() {
return this.scope;
}
createRecordView(callback) {
let model = this.model;
let scope = this.getScope();
this.headerHtml = '';
this.headerHtml += $('')
.text(this.getLanguage().translate(scope, 'scopeNames'))
.get(0).outerHTML;
if (model.get('name')) {
this.headerHtml += ' ' +
$('')
.addClass('chevron-right')
.get(0).outerHTML;
this.headerHtml += ' ' +
$('')
.text(model.get('name'))
.get(0).outerHTML;
}
if (!this.fullFormDisabled) {
let url = '#' + scope + '/view/' + this.id;
this.headerHtml =
$('')
.attr('href', url)
.addClass('action font-size-flexible')
.attr('title', this.translate('Full Form'))
.attr('data-action', 'fullForm')
.append(this.headerHtml)
.get(0).outerHTML;
}
this.headerHtml = this.getHelper().getScopeColorIconHtml(this.scope) + this.headerHtml;
if (!this.editDisabled) {
let editAccess = this.getAcl().check(model, 'edit', true);
if (editAccess) {
this.showButton('edit');
} else {
this.hideButton('edit');
if (editAccess === null) {
this.listenToOnce(model, 'sync', () => {
if (this.getAcl().check(model, 'edit')) {
this.showButton('edit');
}
});
}
}
}
if (!this.removeDisabled) {
var removeAccess = this.getAcl().check(model, 'delete', true);
if (removeAccess) {
this.showButton('remove');
}
else {
this.hideButton('remove');
if (removeAccess === null) {
this.listenToOnce(model, 'sync', () => {
if (this.getAcl().check(model, 'delete')) {
this.showButton('remove');
}
});
}
}
}
let viewName =
this.detailViewName ||
this.detailView ||
this.getMetadata().get(['clientDefs', model.entityType, 'recordViews', 'detailSmall']) ||
this.getMetadata().get(['clientDefs', model.entityType, 'recordViews', 'detailQuick']) ||
'views/record/detail-small';
let options = {
model: model,
fullSelector: this.containerSelector + ' .record-container',
type: 'detailSmall',
layoutName: this.layoutName || 'detailSmall',
buttonsDisabled: true,
inlineEditDisabled: true,
sideDisabled: this.sideDisabled,
bottomDisabled: this.bottomDisabled,
exit: function () {},
};
this.createView('record', viewName, options, callback);
}
/**
* @return {module:views/record/detail}
*/
getRecordView() {
return this.getView('record');
}
afterRender() {
super.afterRender();
setTimeout(() => {
this.$el.children(0).scrollTop(0);
}, 50);
if (!this.navigateButtonsDisabled) {
this.controlNavigationButtons();
}
}
controlNavigationButtons() {
let recordView = this.getRecordView();
if (!recordView) {
return;
}
let indexOfRecord = this.indexOfRecord;
let previousButtonEnabled = false;
let nextButtonEnabled = false;
if (indexOfRecord > 0) {
previousButtonEnabled = true;
}
if (indexOfRecord < this.model.collection.total - 1) {
nextButtonEnabled = true;
}
else {
if (this.model.collection.total === -1) {
nextButtonEnabled = true;
} else if (this.model.collection.total === -2) {
if (indexOfRecord < this.model.collection.length - 1) {
nextButtonEnabled = true;
}
}
}
if (previousButtonEnabled) {
this.enableButton('previous');
} else {
this.disableButton('previous');
}
if (nextButtonEnabled) {
this.enableButton('next');
} else {
this.disableButton('next');
}
}
switchToModelByIndex(indexOfRecord) {
if (!this.model.collection) {
return;
}
let previousModel = this.model;
this.sourceModel = this.model.collection.at(indexOfRecord);
if (!this.sourceModel) {
throw new Error("Model is not found in collection by index.");
}
this.indexOfRecord = indexOfRecord;
this.id = this.sourceModel.id;
this.scope = this.sourceModel.entityType;
this.model = this.sourceModel.clone();
this.model.collection = this.sourceModel.collection.clone();
this.stopListening(previousModel, 'change');
this.stopListening(previousModel, 'sync');
this.listenTo(this.model, 'change', () => {
this.sourceModel.set(this.model.getClonedAttributes());
});
this.listenTo(this.model, 'sync', () => {
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
this.createRecordView(() => {
this.reRender()
.then(() => {
this.model.fetch();
})
});
this.controlNavigationButtons();
this.trigger('switch-model', this.model, previousModel);
}
actionPrevious() {
if (!this.model.collection) {
return;
}
if (!(this.indexOfRecord > 0)) {
return;
}
let indexOfRecord = this.indexOfRecord - 1;
this.switchToModelByIndex(indexOfRecord);
}
actionNext() {
if (!this.model.collection) {
return;
}
if (!(this.indexOfRecord < this.model.collection.total - 1) && this.model.collection.total >= 0) {
return;
}
if (this.model.collection.total === -2 && this.indexOfRecord >= this.model.collection.length - 1) {
return;
}
let collection = this.model.collection;
let indexOfRecord = this.indexOfRecord + 1;
if (indexOfRecord <= collection.length - 1) {
this.switchToModelByIndex(indexOfRecord);
return;
}
collection
.fetch({
more: true,
remove: false,
})
.then(() => {
this.switchToModelByIndex(indexOfRecord);
});
}
/**
* @return {Promise}
*/
actionEdit() {
if (this.options.quickEditDisabled) {
let options = {
id: this.id,
model: this.model,
returnUrl: this.getRouter().getCurrentUrl(),
};
if (this.options.rootUrl) {
options.rootUrl = this.options.rootUrl;
}
this.getRouter().navigate('#' + this.scope + '/edit/' + this.id, {trigger: false});
this.getRouter().dispatch(this.scope, 'edit', options);
return Promise.reject();
}
let viewName = this.getMetadata().get(['clientDefs', this.scope, 'modalViews', 'edit']) ||
'views/modals/edit';
Espo.Ui.notify(' ... ');
return new Promise(resolve => {
this.createView('quickEdit', viewName, {
scope: this.scope,
entityType: this.model.entityType,
id: this.id,
fullFormDisabled: this.fullFormDisabled
}, view => {
this.listenToOnce(view, 'remove', () => {
this.dialog.show();
});
this.listenToOnce(view, 'leave', () => {
this.remove();
});
this.listenTo(view, 'after:save', (model, o) => {
this.model.set(model.getClonedAttributes());
this.trigger('after:save', model, o);
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
view.render()
.then(() => {
Espo.Ui.notify(false);
this.dialog.hide();
resolve(view);
});
});
});
}
actionRemove() {
let model = this.getRecordView().model;
this.confirm(this.translate('removeRecordConfirmation', 'messages'), () => {
let $buttons = this.dialog.$el.find('.modal-footer button');
$buttons.addClass('disabled').attr('disabled', 'disabled');
model.destroy()
.then(() => {
this.trigger('after:destroy', model);
this.dialog.close();
})
.catch(() => {
$buttons.removeClass('disabled').removeAttr('disabled');
});
});
}
actionFullForm() {
let url;
let router = this.getRouter();
let scope = this.getScope();
url = '#' + scope + '/view/' + this.id;
let attributes = this.getRecordView().fetch();
let model = this.getRecordView().model;
attributes = _.extend(attributes, model.getClonedAttributes());
let options = {
attributes: attributes,
returnUrl: Backbone.history.fragment,
model: this.sourceModel || this.model,
id: this.id,
};
if (this.options.rootUrl) {
options.rootUrl = this.options.rootUrl;
}
setTimeout(() => {
router.dispatch(scope, 'view', options);
router.navigate(url, {trigger: false});
}, 10);
this.trigger('leave');
this.dialog.close();
}
actionDuplicate() {
Espo.Ui.notify(' ... ');
Espo.Ajax
.postRequest(this.scope + '/action/getDuplicateAttributes', {id: this.model.id})
.then(attributes => {
Espo.Ui.notify(false);
let url = '#' + this.scope + '/create';
this.getRouter().dispatch(this.scope, 'create', {
attributes: attributes,
returnUrl: this.getRouter().getCurrentUrl(),
options: {
duplicateSourceId: this.model.id,
returnAfterCreate: true,
},
});
this.getRouter().navigate(url, {trigger: false});
});
}
/**
* @protected
* @param {JQueryKeyEventObject} e
*/
handleShortcutKeyControlArrowLeft(e) {
if (!this.model.collection) {
return;
}
if (this.buttonList.findIndex(item => item.name === 'previous' && !item.disabled) === -1) {
return;
}
if (e.target.tagName === 'TEXTAREA' || e.target.tagName === 'INPUT') {
return;
}
e.preventDefault();
e.stopPropagation();
this.actionPrevious();
}
/**
* @protected
* @param {JQueryKeyEventObject} e
*/
handleShortcutKeyControlArrowRight(e) {
if (!this.model.collection) {
return;
}
if (this.buttonList.findIndex(item => item.name === 'next' && !item.disabled) === -1) {
return;
}
if (e.target.tagName === 'TEXTAREA' || e.target.tagName === 'INPUT') {
return;
}
e.preventDefault();
e.stopPropagation();
this.actionNext();
}
}
export default DetailModalView;