detail modal actions in clientDefs
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user