detail modal actions in clientDefs

This commit is contained in:
Yuri Kuznetsov
2022-06-27 18:54:36 +03:00
parent 72cf250afe
commit f9e30b778d
6 changed files with 96 additions and 34 deletions
+17 -7
View File
@@ -55,9 +55,11 @@ define(() => {
* @param {function(Object): void} addFunc
* @param {function(string): void} showFunc
* @param {function(string): void} hideFunc
* @param {{listenToViewModelSync?: boolean}} options
*/
setup(view, type, waitFunc, addFunc, showFunc, hideFunc) {
let additionalActionList = [];
setup(view, type, waitFunc, addFunc, showFunc, hideFunc, options) {
options = options || {};
let actionList = [];
let scope = view.scope || view.model.entityType;
@@ -92,7 +94,7 @@ define(() => {
item.hidden = true;
}
additionalActionList.push(item);
actionList.push(item);
let data = item.data || {};
let handlerName = item.handler || data.handler;
@@ -128,12 +130,12 @@ define(() => {
}));
});
if (!additionalActionList.length) {
if (!actionList.length) {
return;
}
view.listenTo(view.model, 'sync', () => {
additionalActionList.forEach(item => {
let onSync = () => {
actionList.forEach(item => {
if (item.handlerInstance && item.checkVisibilityFunction) {
let isNotVisible = !item.handlerInstance[item.checkVisibilityFunction]
.call(item.handlerInstance);
@@ -153,7 +155,15 @@ define(() => {
hideFunc(item.name);
});
});
};
if (options.listenToViewModelSync) {
view.listenTo(view, 'model-sync', () => onSync());
return;
}
view.listenTo(view.model, 'sync', () => onSync());
}
}
+6 -5
View File
@@ -346,8 +346,8 @@ define('ui', [], function () {
this.buttonList.forEach(o => {
if (typeof o.onClick === 'function') {
$('#' + this.id + ' .modal-footer button[data-name="' + o.name + '"]')
.on('click', () => {
o.onClick(this);
.on('click', (e) => {
o.onClick(this, e);
});
}
});
@@ -355,8 +355,8 @@ define('ui', [], function () {
this.dropdownItemList.forEach(o => {
if (typeof o.onClick === 'function') {
$('#' + this.id + ' .modal-footer a[data-name="' + o.name + '"]')
.on('click', () => {
o.onClick(this);
.on('click', (e) => {
o.onClick(this, e);
});
}
});
@@ -436,7 +436,8 @@ define('ui', [], function () {
this.dropdownItemList.forEach(o => {
rightPart +=
'<li class="'+(o.hidden ? ' hidden' : '')+'">' +
'<a href="javascript:" data-name="'+o.name+'">'+(o.html || o.text)+'</a></li>';
'<a href="javascript:" ' +
'data-name="'+o.name+'">'+(o.html || o.text)+'</a></li>';
});
rightPart += '</ul>';
+7 -4
View File
@@ -41,10 +41,12 @@ define('utils', [], function () {
*
* @param {module:view.Class} viewObject A view.
* @param {Event} e An event.
* @param {string} [action] An action. If not specified, will be fetched from a target element.
* @param {string} [handler] A handler name.
*/
handleAction: function (viewObject, e) {
handleAction: function (viewObject, e, action, handler) {
let $target = $(e.currentTarget);
let action = $target.data('action');
action = action || $target.data('action');
let fired = false;
if (!action) {
@@ -53,6 +55,7 @@ define('utils', [], function () {
let data = $target.data();
let method = 'action' + Espo.Utils.upperCaseFirst(action);
handler = handler || data.handler;
if (typeof viewObject[method] === 'function') {
viewObject[method].call(viewObject, data, e);
@@ -62,13 +65,13 @@ define('utils', [], function () {
fired = true;
}
else if (data.handler) {
else if (handler) {
e.preventDefault();
e.stopPropagation();
fired = true;
require(data.handler, function (Handler) {
require(handler, function (Handler) {
let handler = new Handler(viewObject);
handler[method].call(handler, data, e);
+10 -10
View File
@@ -348,8 +348,6 @@ define('views/modal', ['view'], function (Dep) {
return;
}
var text = o.text;
if (!o.text) {
if ('label' in o) {
o.text = this.translate(o.label, 'labels', this.scope);
@@ -358,9 +356,11 @@ define('views/modal', ['view'], function (Dep) {
}
}
o.onClick = o.onClick || (
this['action' + Espo.Utils.upperCaseFirst(o.name)] || function () {}
).bind(this);
o.onClick = o.onClick || ((d, e) => {
let handler = o.handler || (o.data || {}).handler;
Espo.Utils.handleAction(this, e, o.name, handler);
});
buttonListExt.push(o);
});
@@ -388,8 +388,6 @@ define('views/modal', ['view'], function (Dep) {
return;
}
var text = o.text;
if (!o.text) {
if ('label' in o) {
o.text = this.translate(o.label, 'labels', this.scope)
@@ -398,9 +396,11 @@ define('views/modal', ['view'], function (Dep) {
}
}
o.onClick = o.onClick || (
this['action' + Espo.Utils.upperCaseFirst(o.name)] || function () {}
).bind(this);
o.onClick = o.onClick || ((d, e) => {
let handler = o.handler || (o.data || {}).handler;
Espo.Utils.handleAction(this, e, o.name, handler);
});
dropdownItemListExt.push(o);
});
+55 -8
View File
@@ -26,7 +26,7 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/detail', ['views/modal'], function (Dep) {
define('views/modals/detail', ['views/modal', 'helpers/action-item-setup'], function (Dep, ActionItemSetup) {
/**
* A quick view modal.
@@ -145,7 +145,12 @@ define('views/modals/detail', ['views/modal'], function (Dep) {
this.setupAfterModelCreated();
this.listenTo(this.model, 'sync', () => this.controlRecordButtonsVisibility());
this.listenTo(this.model, 'sync', () => {
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
this.listenToOnce(this.model, 'sync', () => this.createRecordView());
this.model.fetch();
@@ -162,12 +167,17 @@ define('views/modals/detail', ['views/modal'], function (Dep) {
this.sourceModel.set(this.model.getClonedAttributes());
});
this.listenTo(this.model, 'sync', () => this.controlRecordButtonsVisibility());
this.listenTo(this.model, 'sync', () => {
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
this.once('after:render', () => {
this.model.fetch();
});
this.setupActionItems();
this.createRecordView();
});
@@ -183,8 +193,37 @@ define('views/modals/detail', ['views/modal'], function (Dep) {
}
},
/**
* @private
*/
setupActionItems: function () {
/** @var {module:helpers/action-item-setup.Class} */
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: function () {},
/**
* @protected
*/
setupRecordButtons: function () {
if (!this.removeDisabled) {
this.addRemoveButton();
@@ -375,7 +414,7 @@ define('views/modals/detail', ['views/modal'], function (Dep) {
return;
}
var previousModel = this.model;
let previousModel = this.model;
this.sourceModel = this.model.collection.at(indexOfRecord);
@@ -391,18 +430,24 @@ define('views/modals/detail', ['views/modal'], function (Dep) {
this.model = this.sourceModel.clone();
this.model.collection = this.sourceModel.collection;
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.listenTo(this.model, 'sync', () => {
this.controlRecordButtonsVisibility();
this.once('after:render', () => {
this.model.fetch();
this.trigger('model-sync');
});
this.createRecordView(() => {
this.reRender();
this.reRender()
.then(() => {
this.model.fetch();
})
});
this.controlNavigationButtons();
@@ -504,6 +549,8 @@ define('views/modals/detail', ['views/modal'], function (Dep) {
this.trigger('after:save', model);
this.controlRecordButtonsVisibility();
this.trigger('model-sync');
});
view.render();
+1
View File
@@ -131,6 +131,7 @@ function (Dep, ViewRecordHelper, ActionItemSetup) {
* @property {string} [label] A label.
* @property {string} [html] An HTML.
* @property {boolean} [hidden] Hidden.
* @property {Object.<string,string>} [data] Data attributes.
*/
/**