This commit is contained in:
Yuri Kuznetsov
2023-07-01 14:18:08 +03:00
parent 3c8bdeb539
commit 6063a295a0
14 changed files with 987 additions and 974 deletions
+3 -3
View File
@@ -57,9 +57,9 @@
* @typedef {Object} module:search-manager~advancedFilter
*
* @property {string} type A type. E.g. `equals`.
* @property {string} attribute An attribute.
* @property {string} [attribute] An attribute.
* @property {*} [value] A value.
* @property {Object.<string,*>} [data] Additional data for UI.
* @property {Object.<string, *>} [data] Additional data for UI.
*/
/**
@@ -306,7 +306,7 @@ class SearchManager {
/**
* Set advanced filters.
*
* @param {{string: module:search-manager~advancedFilter}} advanced Advanced filters.
* @param {Object.<string, module:search-manager~advancedFilter>} advanced Advanced filters.
* Pairs of field => advancedFilter.
*/
setAdvanced(advanced) {
+1 -1
View File
@@ -64,7 +64,7 @@ class ModalView extends View {
* @property {'default'|'danger'|'success'|'warning'} [style='default'] A style.
* @property {boolean} [hidden=false] Is hidden.
* @property {boolean} [disabled=false] Disabled.
* @property {function():void} [onClick] Called on click. If not defined, then
* @property {function(module:ui.Dialog): void} [onClick] Called on click. If not defined, then
* the `action<Name>` class method will be called.
* @property {string} [className] An additional class name.
*/
+72 -62
View File
@@ -26,83 +26,93 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/kanban-move-over', ['views/modal'], function (Dep) {
import ModalView from 'views/modal';
return Dep.extend({
class KanbanMoveOverModalView extends ModalView {
template: 'modals/kanban-move-over',
template = 'modals/kanban-move-over'
data: function () {
return {
optionDataList: this.optionDataList
};
/** @inheritDoc */
backdrop = true
data() {
return {
optionDataList: this.optionDataList,
};
}
events = {
/** @this KanbanMoveOverModalView */
'click [data-action="move"]': function (e) {
let value = $(e.currentTarget).data('value');
this.moveTo(value);
},
}
events: {
'click [data-action="move"]': function (e) {
var value = $(e.currentTarget).data('value');
this.moveTo(value);
}
},
setup() {
this.scope = this.model.name;
setup: function () {
this.scope = this.model.name;
var iconHtml = this.getHelper().getScopeColorIconHtml(this.scope);
let iconHtml = this.getHelper().getScopeColorIconHtml(this.scope);
this.statusField = this.options.statusField;
this.statusField = this.options.statusField;
this.$header = $('<span>');
this.$header = $('<span>');
this.$header.append(
$('<span>').text(this.getLanguage().translate(this.scope, 'scopeNames'))
);
if (this.model.get('name')) {
this.$header.append(' <span class="chevron-right"></span> ');
this.$header.append(
$('<span>').text(this.getLanguage().translate(this.scope, 'scopeNames'))
);
$('<span>').text(this.model.get('name'))
)
}
if (this.model.get('name')) {
this.$header.append(' <span class="chevron-right"></span> ');
this.$header.append(
$('<span>').text(this.model.get('name'))
)
this.$header.prepend(iconHtml);
this.buttonList = [
{
name: 'cancel',
label: 'Cancel'
}
];
this.$header.prepend(iconHtml);
this.optionDataList = [];
this.buttonList = [
(
this.getMetadata()
.get(['entityDefs', this.scope, 'fields', this.statusField, 'options']) || []
)
.forEach((item) => {
this.optionDataList.push({
value: item,
label: this.getLanguage().translateOption(item, this.statusField, this.scope),
});
});
}
moveTo(status) {
var attributes = {};
attributes[this.statusField] = status;
this.model
.save(
attributes,
{
name: 'cancel',
label: 'Cancel'
patch: true,
isMoveTo: true,
}
];
)
.then(() => {
Espo.Ui.success(this.translate('Done'));
});
this.optionDataList = [];
this.close();
}
}
(this.getMetadata()
.get(['entityDefs', this.scope, 'fields', this.statusField, 'options']) || [])
.forEach((item) => {
this.optionDataList.push({
value: item,
label: this.getLanguage().translateOption(item, this.statusField, this.scope),
});
});
},
moveTo: function (status) {
var attributes = {};
attributes[this.statusField] = status;
this.model
.save(
attributes,
{
patch: true,
isMoveTo: true,
}
)
.then(() => {
Espo.Ui.success(this.translate('Done'));
});
this.close();
},
});
});
// noinspection JSUnusedGlobalSymbols
export default KanbanMoveOverModalView;
+61 -60
View File
@@ -26,69 +26,70 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/last-viewed', ['views/modal', 'search-manager'], function (Dep) {
import ModalView from 'views/modal';
return Dep.extend({
class LastViewedModalView extends ModalView {
header: false,
scope: 'ActionHistoryRecord',
className: 'dialog dialog-record',
template: 'modals/last-viewed',
backdrop: true,
setup: function () {
Dep.prototype.setup.call(this);
this.events['click .list .cell > a'] = () => {
this.close();
};
this.$header = $('<a>')
.attr('href', '#LastViewed')
.attr('data-action', 'listView')
.addClass('action')
.text(this.getLanguage().translate('LastViewed', 'scopeNamesPlural'));
this.waitForView('list');
this.getCollectionFactory().create(this.scope, (collection) => {
collection.maxSize = this.getConfig().get('recordsPerPage');
this.collection = collection;
collection.url = 'LastViewed';
this.loadList();
collection.fetch();
});
},
actionListView: function () {
this.getRouter().navigate('#LastViewed', {trigger: true});
scope = 'ActionHistoryRecord'
className = 'dialog dialog-record'
template = 'modals/last-viewed'
backdrop = true
setup() {
this.events['click .list .cell > a'] = () => {
this.close();
},
};
loadList: function () {
var viewName =
this.getMetadata().get('clientDefs.' + this.scope + '.recordViews.listLastViewed') ||
'views/record/list';
this.$header = $('<a>')
.attr('href', '#LastViewed')
.attr('data-action', 'listView')
.addClass('action')
.text(this.getLanguage().translate('LastViewed', 'scopeNamesPlural'));
this.listenToOnce(this.collection, 'sync', function () {
this.createView('list', viewName, {
collection: this.collection,
el: this.containerSelector + ' .list-container',
selectable: false,
checkboxes: false,
massActionsDisabled: true,
rowActionsView: false,
searchManager: this.searchManager,
checkAllResultDisabled: true,
buttonsDisabled: true,
headerDisabled: true,
layoutName: 'listForLastViewed',
layoutAclDisabled: true,
});
}, this);
},
});
});
this.waitForView('list');
this.getCollectionFactory().create(this.scope, collection => {
collection.maxSize = this.getConfig().get('recordsPerPage');
collection.url = 'LastViewed';
this.collection = collection;
this.loadList();
collection.fetch();
});
}
// noinspection JSUnusedGlobalSymbols
actionListView() {
this.getRouter().navigate('#LastViewed', {trigger: true});
this.close();
}
loadList() {
let viewName =
this.getMetadata().get('clientDefs.' + this.scope + '.recordViews.listLastViewed') ||
'views/record/list';
this.listenToOnce(this.collection, 'sync', () => {
this.createView('list', viewName, {
collection: this.collection,
el: this.containerSelector + ' .list-container',
selectable: false,
checkboxes: false,
massActionsDisabled: true,
rowActionsView: false,
searchManager: this.searchManager,
checkAllResultDisabled: true,
buttonsDisabled: true,
headerDisabled: true,
layoutName: 'listForLastViewed',
layoutAclDisabled: true,
});
});
}
}
// noinspection JSUnusedGlobalSymbols
export default LastViewedModalView;
+107 -107
View File
@@ -26,129 +26,129 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/mass-action', ['views/modal', 'model'], function (Dep, Model) {
import ModalView from 'views/modal';
import Model from 'model';
return Dep.extend({
class MassActionModalView extends ModalView {
className: 'dialog dialog-record',
template = 'modals/mass-action'
template: 'modals/mass-action',
className = 'dialog dialog-record'
checkInterval = 4000
checkInterval: 4000,
data() {
return {
infoText: this.translate('infoText', 'messages', 'MassAction'),
};
}
data: function () {
return {
infoText: this.translate('infoText', 'messages', 'MassAction'),
};
},
setup() {
this.action = this.options.action;
this.id = this.options.id;
this.status = 'Pending';
setup: function () {
this.action = this.options.action;
this.id = this.options.id;
this.status = 'Pending';
this.headerText =
this.translate('Mass Action', 'scopeNames') + ': ' +
this.translate(this.action, 'massActions', this.options.scope);
this.headerText =
this.translate('Mass Action', 'scopeNames') + ': ' +
this.translate(this.action, 'massActions', this.options.scope);
this.model = new Model();
this.model.name = 'MassAction';
this.model = new Model();
this.model.name = 'MassAction';
this.model.setDefs({
fields: {
'status': {
type: 'enum',
readOnly: true,
options: [
'Pending',
'Running',
'Success',
'Failed',
],
style: {
'Success': 'success',
'Failed': 'danger',
},
},
'processedCount': {
type: 'int',
readOnly: true,
},
}
});
this.model.setDefs({
fields: {
'status': {
type: 'enum',
readOnly: true,
options: [
'Pending',
'Running',
'Success',
'Failed',
this.model.set({
status: this.status,
processedCount: null,
});
this.createView('record', 'views/record/edit-for-modal', {
scope: 'None',
model: this.model,
el: this.getSelector() + ' .record',
detailLayout: [
{
rows: [
[
{
name: 'status',
labelText: this.translate('status', 'fields', 'MassAction'),
},
{
name: 'processedCount',
labelText: this.translate('processedCount', 'fields', 'MassAction'),
},
],
style: {
'Success': 'success',
'Failed': 'danger',
},
},
'processedCount': {
type: 'int',
readOnly: true,
},
}
});
],
},
],
});
this.model.set({
status: this.status,
processedCount: null,
});
this.on('close', () => {
let status = this.model.get('status');
this.createView('record', 'views/record/edit-for-modal', {
scope: 'None',
model: this.model,
el: this.getSelector() + ' .record',
detailLayout: [
{
rows: [
[
{
name: 'status',
labelText: this.translate('status', 'fields', 'MassAction'),
},
{
name: 'processedCount',
labelText: this.translate('processedCount', 'fields', 'MassAction'),
}
]
]
}
],
});
if (
status !== 'Pending' &&
status !== 'Running'
) {
return;
}
this.on('close', () => {
let status = this.model.get('status');
Espo.Ajax.postRequest(`MassAction/${this.id}/subscribe`);
});
this.checkStatus();
}
checkStatus() {
Espo.Ajax
.getRequest(`MassAction/${this.id}/status`)
.then(response => {
let status = response.status;
this.model.set('status', status);
if (status === 'Pending' || status === 'Running') {
setTimeout(() => this.checkStatus(), this.checkInterval);
if (
status !== 'Pending' &&
status !== 'Running'
) {
return;
}
Espo.Ajax.postRequest(`MassAction/${this.id}/subscribe`);
});
this.checkStatus();
},
checkStatus: function () {
Espo.Ajax
.getRequest(`MassAction/${this.id}/status`)
.then(response => {
let status = response.status;
this.model.set('status', status);
if (status === 'Pending' || status === 'Running') {
setTimeout(() => this.checkStatus(), this.checkInterval);
return;
}
this.model.set({
processedCount: response.processedCount,
});
if (status === 'Success') {
this.trigger('success', {
count: response.processedCount,
});
}
if (this.$el) {
this.$el.find('.info-text').addClass('hidden');
}
this.model.set({
processedCount: response.processedCount,
});
},
});
});
if (status === 'Success') {
this.trigger('success', {
count: response.processedCount,
});
}
if (this.$el) {
this.$el.find('.info-text').addClass('hidden');
}
});
}
}
export default MassActionModalView;
+259 -251
View File
@@ -26,323 +26,331 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/mass-update', ['views/modal', 'helpers/mass-action'], function (Dep, MassActionHelper) {
import ModalView from 'views/modal';
import MassActionHelper from 'helpers/mass-action';
return Dep.extend({
class MassUpdateModalView extends ModalView {
cssName: 'mass-update',
template = 'modals/mass-update'
className: 'dialog dialog-record',
cssName = 'mass-update'
className = 'dialog dialog-record'
layoutName = 'massUpdate'
template: 'modals/mass-update',
ACTION_UPDATE = 'update'
//ACTION_ADD = 'add'
//ACTION_REMOVE = 'remove'
layoutName: 'massUpdate',
data() {
return {
scope: this.scope,
fieldList: this.fieldList,
entityType: this.entityType,
};
}
ACTION_UPDATE: 'update',
events = {
/** @this MassUpdateModalView */
'click a[data-action="add-field"]': function (e) {
let field = $(e.currentTarget).data('name');
ACTION_ADD: 'add',
ACTION_REMOVE: 'remove',
data: function () {
return {
scope: this.scope,
fieldList: this.fieldList,
entityType: this.entityType,
};
this.addField(field);
},
/** @this MassUpdateModalView */
'click button[data-action="reset"]': function () {
this.reset();
}
}
events: {
'click button[data-action="update"]': function () {
this.update();
setup() {
this.buttonList = [
{
name: 'update',
label: 'Update',
style: 'danger',
disabled: true,
},
'click a[data-action="add-field"]': function (e) {
var field = $(e.currentTarget).data('name');
this.addField(field);
},
'click button[data-action="reset"]': function (e) {
this.reset();
{
name: 'cancel',
label: 'Cancel',
}
},
];
setup: function () {
this.buttonList = [
{
name: 'update',
label: 'Update',
style: 'danger',
disabled: true,
},
{
name: 'cancel',
label: 'Cancel',
}
];
this.entityType = this.options.entityType || this.options.scope;
this.scope = this.options.scope || this.entityType;
this.entityType = this.options.entityType || this.options.scope;
this.scope = this.options.scope || this.entityType;
this.ids = this.options.ids;
this.where = this.options.where;
this.searchParams = this.options.searchParams;
this.byWhere = this.options.byWhere;
this.ids = this.options.ids;
this.where = this.options.where;
this.searchParams = this.options.searchParams;
this.byWhere = this.options.byWhere;
this.hasActionMap = {};
this.hasActionMap = {};
let totalCount = this.options.totalCount;
let totalCount = this.options.totalCount;
this.helper = new MassActionHelper(this);
this.helper = new MassActionHelper(this);
this.idle = this.byWhere && this.helper.checkIsIdle(totalCount);
this.idle = this.byWhere && this.helper.checkIsIdle(totalCount);
this.$header = $('<span>')
.append(
$('<span>').text(this.translate(this.scope, 'scopeNamesPlural')),
' <span class="chevron-right"></span> ',
$('<span>').text(this.translate('Mass Update'))
)
this.$header = $('<span>')
.append(
$('<span>').text(this.translate(this.scope, 'scopeNamesPlural')),
' <span class="chevron-right"></span> ',
$('<span>').text(this.translate('Mass Update'))
)
var forbiddenList = this.getAcl().getScopeForbiddenFieldList(this.entityType, 'edit') || [];
var forbiddenList = this.getAcl().getScopeForbiddenFieldList(this.entityType, 'edit') || [];
this.wait(true);
this.wait(true);
this.getModelFactory().create(this.entityType, (model) => {
this.model = model;
this.getModelFactory().create(this.entityType, (model) => {
this.model = model;
this.getHelper().layoutManager.get(this.entityType, this.layoutName, (layout) => {
layout = layout || [];
this.getHelper().layoutManager.get(this.entityType, this.layoutName, (layout) => {
layout = layout || [];
this.fieldList = [];
this.fieldList = [];
layout.forEach((field) => {
if (~forbiddenList.indexOf(field)) {
return;
}
layout.forEach((field) => {
if (~forbiddenList.indexOf(field)) {
return;
}
if (model.hasField(field)) {
this.fieldList.push(field);
}
});
this.wait(false);
if (model.hasField(field)) {
this.fieldList.push(field);
}
});
this.wait(false);
});
});
this.addedFieldList = [];
}
addField(name) {
this.$el.find('[data-action="reset"]').removeClass('hidden');
this.$el.find('ul.filter-list li[data-name="'+name+'"]').addClass('hidden');
if (this.$el.find('ul.filter-list li:not(.hidden)').length === 0) {
this.$el.find('button.select-field').addClass('disabled').attr('disabled', 'disabled');
}
this.addedFieldList.push(name);
let label = this.getHelper().escapeString(
this.translate(name, 'fields', this.entityType)
);
let $cell =
$('<div>')
.addClass('cell form-group')
.attr('data-name', name)
.append(
$('<label>')
.addClass('control-label')
.text(label)
)
.append(
$('<div>')
.addClass('field')
.attr('data-name', name)
);
let $row =
$('<div>')
.addClass('item grid-auto-fill-md')
.attr('data-name', name)
.append($cell);
this.$el.find('.fields-container').append($row);
let type = this.model.getFieldType(name);
let viewName = this.model.getFieldParam(name, 'view') || this.getFieldManager().getViewName(type);
let actionList = this.getMetadata().get(['entityDefs', this.entityType, name, 'massUpdateActionList']) ||
this.getMetadata().get(['fields', type, 'massUpdateActionList']);
let hasActionDropdown = actionList !== null;
this.hasActionMap[name] = hasActionDropdown;
this.disableButton('update');
this.createView(name, viewName, {
model: this.model,
el: this.getSelector() + ' .field[data-name="' + name + '"]',
defs: {
name: name,
},
mode: 'edit',
}, view => {
this.enableButton('update');
view.render();
});
if (hasActionDropdown) {
let $select =
$('<select>')
.addClass('item-action form-control')
.attr('data-name', name);
actionList.forEach(action => {
let label = this.translate(Espo.Utils.upperCaseFirst(action));
$select.append(
$('<option>')
.text(label)
.val(action)
);
});
this.addedFieldList = [];
},
addField: function (name) {
this.$el.find('[data-action="reset"]').removeClass('hidden');
this.$el.find('ul.filter-list li[data-name="'+name+'"]').addClass('hidden');
if (this.$el.find('ul.filter-list li:not(.hidden)').length === 0) {
this.$el.find('button.select-field').addClass('disabled').attr('disabled', 'disabled');
}
this.addedFieldList.push(name);
let label = this.getHelper().escapeString(
this.translate(name, 'fields', this.entityType)
);
let $cell =
let $cellAction =
$('<div>')
.addClass('cell form-group')
.addClass('cell call-action form-group')
.attr('data-name', name)
.append(
$('<label>')
.addClass('control-label')
.text(label)
.addClass('control-label hidden-xs')
.html('&nbsp;')
)
.append(
$('<div>')
.addClass('field')
.attr('data-name', name)
.append($select)
);
let $row =
$('<div>')
.addClass('item grid-auto-fill-md')
.attr('data-name', name)
.append($cell);
$row.append($cellAction);
}
}
this.$el.find('.fields-container').append($row);
/**
* @param {string} field
* @return {module:views/fields/base}
*/
getFieldView(field) {
return this.getView(field);
}
let type = this.model.getFieldType(name);
let viewName = this.model.getFieldParam(name, 'view') || this.getFieldManager().getViewName(type);
// noinspection JSUnusedGlobalSymbols
actionUpdate() {
this.disableButton('update');
let actionList = this.getMetadata().get(['entityDefs', this.entityType, name, 'massUpdateActionList']) ||
this.getMetadata().get(['fields', type, 'massUpdateActionList']);
let attributes = {};
let actions = {};
let hasActionDropdown = actionList !== null;
this.addedFieldList.forEach(field => {
let action = this.fetchAction(field);
let itemAttributes = this.getFieldView(field).fetch();
this.hasActionMap[name] = hasActionDropdown;
let itemActualAttributes = {};
this.disableButton('update');
this.getFieldManager()
.getEntityTypeFieldActualAttributeList(this.entityType, field)
.forEach(attribute => {
actions[attribute] = action;
this.createView(name, viewName, {
model: this.model,
el: this.getSelector() + ' .field[data-name="' + name + '"]',
defs: {
name: name,
},
mode: 'edit',
}, view => {
this.enableButton('update');
view.render();
});
if (hasActionDropdown) {
let $select =
$('<select>')
.addClass('item-action form-control')
.attr('data-name', name);
actionList.forEach(action => {
let label = this.translate(Espo.Utils.upperCaseFirst(action));
$select.append(
$('<option>')
.text(label)
.val(action)
);
itemActualAttributes[attribute] = itemAttributes[attribute];
});
let $cellAction =
$('<div>')
.addClass('cell call-action form-group')
.attr('data-name', name)
.append(
$('<label>')
.addClass('control-label hidden-xs')
.html('&nbsp;')
)
.append(
$('<div>')
.addClass('field')
.attr('data-name', name)
.append($select)
);
_.extend(attributes, itemActualAttributes);
});
$row.append($cellAction);
}
},
this.model.set(attributes);
actionUpdate: function () {
this.disableButton('update');
let notValid = false;
let attributes = {};
let actions = {};
this.addedFieldList.forEach(field => {
let view = this.getFieldView(field);
this.addedFieldList.forEach(field => {
let action = this.fetchAction(field);
let itemAttributes = this.getView(field).fetch();
notValid = view.validate() || notValid;
});
let itemActualAttributes = {};
if (notValid) {
Espo.Ui.error(this.translate('Not valid'))
this.getFieldManager()
.getEntityTypeFieldActualAttributeList(this.entityType, field)
.forEach(attribute => {
actions[attribute] = action;
this.enableButton('update');
itemActualAttributes[attribute] = itemAttributes[attribute];
});
return;
}
_.extend(attributes, itemActualAttributes);
});
Espo.Ui.notify(this.translate('saving', 'messages'));
this.model.set(attributes);
Espo.Ajax
.postRequest('MassAction', {
action: 'update',
entityType: this.entityType,
params: {
ids: this.ids || null,
where: (!this.ids || this.ids.length === 0) ? this.options.where : null,
searchParams: (!this.ids || this.ids.length === 0) ? this.options.searchParams : null,
},
data: {
values: attributes,
actions: actions,
},
idle: this.idle,
})
.then(result => {
result = result || {};
let notValid = false;
if (result.id) {
this.helper
.process(result.id, 'update')
.then(view => {
this.listenToOnce(view, 'close', () => this.close());
this.addedFieldList.forEach(field => {
let view = this.getView(field);
notValid = view.validate() || notValid;
});
if (notValid) {
this.notify('Not valid', 'error');
this.enableButton('update');
return;
}
Espo.Ui.notify(this.translate('saving', 'messages'));
Espo.Ajax
.postRequest('MassAction', {
action: 'update',
entityType: this.entityType,
params: {
ids: this.ids || null,
where: (!this.ids || this.ids.length === 0) ? this.options.where : null,
searchParams: (!this.ids || this.ids.length === 0) ? this.options.searchParams : null,
},
data: {
values: attributes,
actions: actions,
},
idle: this.idle,
})
.then(result => {
result = result || {};
if (result.id) {
this.helper
.process(result.id, 'update')
.then(view => {
this.listenToOnce(view, 'close', () => this.close());
this.listenToOnce(view, 'success', result => {
this.trigger('after:update', {
count: result.count,
idle: true,
});
this.listenToOnce(view, 'success', result => {
this.trigger('after:update', {
count: result.count,
idle: true,
});
});
});
return;
}
return;
}
this.trigger('after:update', {
count: result.count,
});
})
.catch(() => {
this.enableButton('update');
this.trigger('after:update', {
count: result.count,
});
},
fetchAction: function (name) {
if (!this.hasActionMap[name]) {
return this.ACTION_UPDATE;
}
let $dropdown = this.$el.find('select.item-action[data-name="'+name+'"]');
return $dropdown.val() || this.ACTION_UPDATE;
},
reset: function () {
this.addedFieldList.forEach(field => {
this.clearView(field);
this.$el.find('.item[data-name="'+field+'"]').remove();
})
.catch(() => {
this.enableButton('update');
});
}
this.addedFieldList = [];
this.hasActionMap = {};
fetchAction(name) {
if (!this.hasActionMap[name]) {
return this.ACTION_UPDATE;
}
this.model.clear();
let $dropdown = this.$el.find('select.item-action[data-name="' + name + '"]');
this.$el.find('[data-action="reset"]').addClass('hidden');
this.$el.find('button.select-field').removeClass('disabled').removeAttr('disabled');
this.$el.find('ul.filter-list').find('li').removeClass('hidden');
return $dropdown.val() || this.ACTION_UPDATE;
}
this.disableButton('update');
},
});
});
reset() {
this.addedFieldList.forEach(field => {
this.clearView(field);
this.$el.find('.item[data-name="'+field+'"]').remove();
});
this.addedFieldList = [];
this.hasActionMap = {};
this.model.clear();
this.$el.find('[data-action="reset"]').addClass('hidden');
this.$el.find('button.select-field').removeClass('disabled').removeAttr('disabled');
this.$el.find('ul.filter-list').find('li').removeClass('hidden');
this.disableButton('update');
}
}
export default MassUpdateModalView;
+128 -129
View File
@@ -26,170 +26,169 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/password-change-request', ['views/modal'], function (Dep) {
import ModalView from 'views/modal';
return Dep.extend({
class PasswordChangeRequestModalView extends ModalView {
cssName: 'password-change-request',
template = 'modals/password-change-request'
className: 'dialog dialog-centered',
cssName = 'password-change-request'
className = 'dialog dialog-centered'
noFullHeight = true
footerAtTheTop = false
template: 'modals/password-change-request',
setup() {
this.buttonList = [
{
name: 'submit',
label: 'Submit',
style: 'danger',
className: 'btn-s-wide',
},
{
name: 'cancel',
label: 'Close',
pullLeft: true,
className: 'btn-s-wide',
}
];
noFullHeight: true,
this.headerText = this.translate('Password Change Request', 'labels', 'User');
footerAtTheTop: false,
this.once('close remove', () => {
if (this.$userName) {
this.$userName.popover('destroy');
}
setup: function () {
if (this.$emailAddress) {
this.$emailAddress.popover('destroy');
}
});
}
this.buttonList = [
{
name: 'submit',
label: 'Submit',
style: 'danger',
className: 'btn-s-wide',
},
{
name: 'cancel',
label: 'Close',
pullLeft: true,
className: 'btn-s-wide',
}
];
afterRender() {
this.$userName = this.$el.find('input[name="username"]');
this.$emailAddress = this.$el.find('input[name="emailAddress"]');
}
this.headerText = this.translate('Password Change Request', 'labels', 'User');
// noinspection JSUnusedGlobalSymbols
actionSubmit() {
let $userName = this.$userName;
let $emailAddress = this.$emailAddress;
this.once('close remove', () => {
if (this.$userName) {
this.$userName.popover('destroy');
let userName = $userName.val();
let emailAddress = $emailAddress.val();
let isValid = true;
if (userName === '') {
isValid = false;
var message = this.getLanguage().translate('userCantBeEmpty', 'messages', 'User');
this.isPopoverUserNameDestroyed = false;
$userName.popover({
container: 'body',
placement: 'bottom',
content: message,
trigger: 'manual',
}).popover('show');
let $cellUserName = $userName.closest('.form-group');
$cellUserName.addClass('has-error');
$userName.one('mousedown click', () => {
$cellUserName.removeClass('has-error');
if (this.isPopoverUserNameDestroyed) {
return;
}
if (this.$emailAddress) {
this.$emailAddress.popover('destroy');
}
$userName.popover('destroy');
this.isPopoverUserNameDestroyed = true;
});
},
}
afterRender: function () {
this.$userName = this.$el.find('input[name="username"]');
this.$emailAddress = this.$el.find('input[name="emailAddress"]');
},
if (emailAddress === '') {
isValid = false;
actionSubmit: function () {
let $userName = this.$userName;
let $emailAddress = this.$emailAddress;
let message = this.getLanguage().translate('emailAddressCantBeEmpty', 'messages', 'User');
let userName = $userName.val();
let emailAddress = $emailAddress.val();
this.isPopoverEmailAddressDestroyed = false;
let isValid = true;
$emailAddress.popover({
container: 'body',
placement: 'bottom',
content: message,
trigger: 'manual',
}).popover('show');
if (userName === '') {
isValid = false;
let $cellEmailAddress = $emailAddress.closest('.form-group');
var message = this.getLanguage().translate('userCantBeEmpty', 'messages', 'User');
$cellEmailAddress.addClass('has-error');
this.isPopoverUserNameDestroyed = false;
$emailAddress.one('mousedown click', () => {
$cellEmailAddress.removeClass('has-error');
$userName.popover({
container: 'body',
placement: 'bottom',
content: message,
trigger: 'manual',
}).popover('show');
if (this.isPopoverEmailAddressDestroyed) {
return;
}
let $cellUserName = $userName.closest('.form-group');
$emailAddress.popover('destroy');
$cellUserName.addClass('has-error');
this.isPopoverEmailAddressDestroyed = true;
});
}
$userName.one('mousedown click', () => {
$cellUserName.removeClass('has-error');
if (!isValid) {
return;
}
if (this.isPopoverUserNameDestroyed) {
return;
}
let $submit = this.$el.find('button[data-name="submit"]');
$userName.popover('destroy');
this.isPopoverUserNameDestroyed = true;
});
}
$submit.addClass('disabled');
if (emailAddress === '') {
isValid = false;
Espo.Ui.notify(this.translate('pleaseWait', 'messages'));
let message = this.getLanguage().translate('emailAddressCantBeEmpty', 'messages', 'User');
Espo.Ajax
.postRequest('User/passwordChangeRequest', {
userName: userName,
emailAddress: emailAddress,
url: this.options.url,
})
.then(() => {
Espo.Ui.notify(false);
this.isPopoverEmailAddressDestroyed = false;
let msg = this.translate('uniqueLinkHasBeenSent', 'messages', 'User');
$emailAddress.popover({
container: 'body',
placement: 'bottom',
content: message,
trigger: 'manual',
}).popover('show');
msg += ' ' + this.translate('passwordRecoverySentIfMatched', 'messages', 'User');
let $cellEmailAddress = $emailAddress.closest('.form-group');
this.$el.find('.cell-userName').addClass('hidden');
this.$el.find('.cell-emailAddress').addClass('hidden');
$cellEmailAddress.addClass('has-error');
$submit.addClass('hidden');
$emailAddress.one('mousedown click', () => {
$cellEmailAddress.removeClass('has-error');
this.$el.find('.msg-box').removeClass('hidden');
this.$el.find('.msg-box').html('<span class="text-success">' + msg + '</span>');
})
.catch(xhr => {
if (xhr.status === 404) {
Espo.Ui.error(this.translate('userNameEmailAddressNotFound', 'messages', 'User'));
if (this.isPopoverEmailAddressDestroyed) {
return;
}
xhr.errorIsHandled = true;
}
$emailAddress.popover('destroy');
this.isPopoverEmailAddressDestroyed = true;
});
}
if (xhr.status === 403 && xhr.getResponseHeader('X-Status-Reason') === 'Already-Sent') {
Espo.Ui.error(this.translate('forbidden', 'messages', 'User'), true);
if (!isValid) {
return;
}
xhr.errorIsHandled = true;
}
let $submit = this.$el.find('button[data-name="submit"]');
$submit.removeClass('disabled');
});
}
}
$submit.addClass('disabled');
Espo.Ui.notify(this.translate('pleaseWait', 'messages'));
Espo.Ajax
.postRequest('User/passwordChangeRequest', {
userName: userName,
emailAddress: emailAddress,
url: this.options.url,
})
.then(() => {
Espo.Ui.notify(false);
let msg = this.translate('uniqueLinkHasBeenSent', 'messages', 'User');
msg += ' ' + this.translate('passwordRecoverySentIfMatched', 'messages', 'User');
this.$el.find('.cell-userName').addClass('hidden');
this.$el.find('.cell-emailAddress').addClass('hidden');
$submit.addClass('hidden');
this.$el.find('.msg-box').removeClass('hidden');
this.$el.find('.msg-box').html('<span class="text-success">' + msg + '</span>');
})
.catch(xhr => {
if (xhr.status === 404) {
Espo.Ui.error(this.translate('userNameEmailAddressNotFound', 'messages', 'User'));
xhr.errorIsHandled = true;
}
if (xhr.status === 403 && xhr.getResponseHeader('X-Status-Reason') === 'Already-Sent') {
Espo.Ui.error(this.translate('forbidden', 'messages', 'User'), true);
xhr.errorIsHandled = true;
}
$submit.removeClass('disabled');
});
},
});
});
export default PasswordChangeRequestModalView;
+128 -128
View File
@@ -26,158 +26,158 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/resolve-save-conflict', ['views/modal'], function (Dep) {
import ModalView from 'views/modal';
return Dep.extend({
class ResolveSaveConflictModalView extends ModalView {
backdrop: true,
template = 'modals/resolve-save-conflict'
fitHeight: true,
backdrop = true
template: 'modals/resolve-save-conflict',
resolutionList = [
'current',
'actual',
'original',
]
resolutionList: [
'current',
'actual',
'original',
],
defaultResolution = 'current'
defaultResolution: 'current',
data() {
let dataList = [];
data: function () {
var dataList = [];
this.fieldList.forEach(item => {
var o = {
field: item,
viewKey: item + 'Field',
resolution: this.defaultResolution,
};
dataList.push(o);
});
return {
dataList: dataList,
entityType: this.entityType,
resolutionList: this.resolutionList,
this.fieldList.forEach(item => {
let o = {
field: item,
viewKey: item + 'Field',
resolution: this.defaultResolution,
};
},
setup: function () {
this.headerText = this.translate('Resolve Conflict');
dataList.push(o);
});
this.buttonList = [
{
name: 'apply',
label: 'Apply',
style: 'danger',
},
{
name: 'cancel',
label: 'Cancel',
},
];
return {
dataList: dataList,
entityType: this.entityType,
resolutionList: this.resolutionList,
};
}
this.entityType = this.model.entityType;
setup() {
this.headerText = this.translate('Resolve Conflict');
this.originalModel = this.model;
this.buttonList = [
{
name: 'apply',
label: 'Apply',
style: 'danger',
},
{
name: 'cancel',
label: 'Cancel',
},
];
this.originalAttributes = Espo.Utils.cloneDeep(this.options.originalAttributes);
this.currentAttributes = Espo.Utils.cloneDeep(this.options.currentAttributes);
this.actualAttributes = Espo.Utils.cloneDeep(this.options.actualAttributes);
this.entityType = this.model.entityType;
var attributeList = this.options.attributeList;
this.originalModel = this.model;
var fieldList = [];
this.originalAttributes = Espo.Utils.cloneDeep(this.options.originalAttributes);
this.currentAttributes = Espo.Utils.cloneDeep(this.options.currentAttributes);
this.actualAttributes = Espo.Utils.cloneDeep(this.options.actualAttributes);
this.getFieldManager()
.getEntityTypeFieldList(this.entityType)
.forEach(field => {
var fieldAttributeList = this.getFieldManager()
.getEntityTypeFieldAttributeList(this.entityType, field);
let attributeList = this.options.attributeList;
var intersect = attributeList.filter(value => fieldAttributeList.includes(value));
let fieldList = [];
if (intersect.length) {
fieldList.push(field);
}
});
this.getFieldManager()
.getEntityTypeFieldList(this.entityType)
.forEach(field => {
let fieldAttributeList = this.getFieldManager()
.getEntityTypeFieldAttributeList(this.entityType, field);
this.fieldList = fieldList;
let intersect = attributeList.filter(value => fieldAttributeList.includes(value));
this.wait(
this.getModelFactory().create(this.entityType)
.then(model => {
this.model = model;
this.fieldList.forEach(field => {
this.setResolution(field, this.defaultResolution);
});
this.fieldList.forEach(field => {
this.createField(field);
});
})
);
},
setResolution: function (field, resolution) {
let attributeList = this.getFieldManager()
.getEntityTypeFieldAttributeList(this.entityType, field);
let values = {};
let source = this.currentAttributes;
if (resolution === 'actual') {
source = this.actualAttributes;
}
else if (resolution === 'original') {
source = this.originalAttributes;
}
for (let attribute of attributeList) {
values[attribute] = source[attribute] || null;
}
this.model.set(values);
},
createField: function (field) {
let type = this.model.getFieldType(field);
let viewName =
this.model.getFieldParam(field, 'view') ||
this.getFieldManager().getViewName(type);
this.createView(field + 'Field', viewName, {
readOnly: true,
model: this.model,
name: field,
el: this.getSelector() + ' [data-name="field"][data-field="' + field + '"]',
mode: 'list',
if (intersect.length) {
fieldList.push(field);
}
});
},
afterRender: function () {
this.$el.find('[data-name="resolution"]').on('change', e => {
let $el = $(e.currentTarget);
this.fieldList = fieldList;
let field = $el.attr('data-field');
let resolution = $el.val();
this.wait(
this.getModelFactory().create(this.entityType)
.then(model => {
this.model = model;
this.setResolution(field, resolution);
});
},
this.fieldList.forEach(field => {
this.setResolution(field, this.defaultResolution);
});
actionApply: function () {
let attributes = this.model.attributes;
this.fieldList.forEach(field => {
this.createField(field);
});
})
);
}
this.originalModel.set(attributes);
setResolution(field, resolution) {
let attributeList = this.getFieldManager()
.getEntityTypeFieldAttributeList(this.entityType, field);
this.trigger('resolve');
this.close();
},
});
});
let values = {};
let source = this.currentAttributes;
if (resolution === 'actual') {
source = this.actualAttributes;
}
else if (resolution === 'original') {
source = this.originalAttributes;
}
for (let attribute of attributeList) {
values[attribute] = source[attribute] || null;
}
this.model.set(values);
}
createField(field) {
let type = this.model.getFieldType(field);
let viewName =
this.model.getFieldParam(field, 'view') ||
this.getFieldManager().getViewName(type);
this.createView(field + 'Field', viewName, {
readOnly: true,
model: this.model,
name: field,
el: this.getSelector() + ' [data-name="field"][data-field="' + field + '"]',
mode: 'list',
});
}
afterRender() {
this.$el.find('[data-name="resolution"]').on('change', e => {
let $el = $(e.currentTarget);
let field = $el.attr('data-field');
let resolution = $el.val();
this.setResolution(field, resolution);
});
}
// noinspection JSUnusedGlobalSymbols
actionApply() {
let attributes = this.model.attributes;
this.originalModel.set(attributes);
this.trigger('resolve');
this.close();
}
}
export default ResolveSaveConflictModalView;
+56 -47
View File
@@ -26,63 +26,72 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/save-filters', ['views/modal', 'model'], function (Dep, Model) {
import ModalView from 'views/modal';
import Model from 'model';
return Dep.extend({
class SaveFiltersModalView extends ModalView {
cssName: 'save-filters',
template = 'modals/save-filters'
template: 'modals/save-filters',
cssName = 'save-filters'
data: function () {
return {
dashletList: this.dashletList,
};
},
data() {
return {
dashletList: this.dashletList,
};
}
setup: function () {
this.buttonList = [
{
name: 'save',
label: 'Save',
style: 'primary'
},
{
name: 'cancel',
label: 'Cancel'
setup() {
this.buttonList = [
{
name: 'save',
label: 'Save',
style: 'primary',
},
{
name: 'cancel',
label: 'Cancel',
},
];
this.headerText = this.translate('Save Filter');
let model = new Model();
this.createView('name', 'views/fields/varchar', {
el: this.options.el + ' .field[data-name="name"]',
defs: {
name: 'name',
params: {
required: true
}
];
},
mode: 'edit',
model: model,
});
}
this.headerText = this.translate('Save Filter');
/**
* @param {string} field
* @return {module:views/fields/base}
*/
getFieldView(field) {
return this.getView(field);
}
var model = new Model();
actionSave() {
let nameView = this.getFieldView('name');
this.createView('name', 'views/fields/varchar', {
el: this.options.el + ' .field[data-name="name"]',
defs: {
name: 'name',
params: {
required: true
}
},
mode: 'edit',
model: model,
});
},
nameView.fetchToModel();
actionSave: function () {
var nameView = this.getView('name');
nameView.fetchToModel();
if (nameView.validate()) {
return;
}
if (nameView.validate()) {
return;
}
this.trigger('save', nameView.model.get('name'));
return true;
},
});
});
this.trigger('save', nameView.model.get('name'));
return true;
}
}
export default SaveFiltersModalView;
@@ -26,124 +26,126 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/select-category-tree-records', ['views/modals/select-records'], function (Dep) {
import SelectRecordsModalView from 'views/modals/select-records';
return Dep.extend({
class SelectCategoryTreeRecordsModalView extends SelectRecordsModalView {
setup: function () {
this.filters = this.options.filters || {};
this.boolFilterList = this.options.boolFilterList || {};
this.primaryFilterName = this.options.primaryFilterName || null;
setup() {
this.filters = this.options.filters || {};
this.boolFilterList = this.options.boolFilterList || {};
this.primaryFilterName = this.options.primaryFilterName || null;
if ('multiple' in this.options) {
this.multiple = this.options.multiple;
if ('multiple' in this.options) {
this.multiple = this.options.multiple;
}
this.createButton = false;
this.massRelateEnabled = this.options.massRelateEnabled;
this.buttonList = [
{
name: 'cancel',
label: 'Cancel'
}
];
this.createButton = false;
this.massRelateEnabled = this.options.massRelateEnabled;
if (this.multiple) {
this.buttonList.unshift({
name: 'select',
style: 'danger',
label: 'Select',
onClick: dialog => {
let listView = this.getRecordView();
this.buttonList = [
{
name: 'cancel',
label: 'Cancel'
if (listView.allResultIsChecked) {
this.trigger('select', {
massRelate: true,
where: this.collection.getWhere(),
searchParams: this.collection.data,
});
}
else {
var list = listView.getSelected();
if (list.length) {
this.trigger('select', list);
}
}
dialog.close();
},
});
}
this.scope = this.options.scope;
this.$header = $('<span>');
this.$header.append(
$('<span>').text(
this.translate('Select') + ': ' +
this.getLanguage().translate(this.scope, 'scopeNamesPlural')
)
);
this.$header.prepend(
this.getHelper().getScopeColorIconHtml(this.scope)
);
this.waitForView('list');
Espo.loader.require('search-manager', SearchManager => {
this.getCollectionFactory().create(this.scope, collection => {
collection.maxSize = this.getConfig().get('recordsPerPageSelect') || 5;
this.collection = collection;
var searchManager = new SearchManager(collection, 'listSelect', null, this.getDateTime());
searchManager.emptyOnReset = true;
if (this.filters) {
searchManager.setAdvanced(this.filters);
}
];
if (this.multiple) {
this.buttonList.unshift({
name: 'select',
style: 'danger',
label: 'Select',
onClick: (dialog) => {
var listView = this.getView('list');
if (this.boolFilterList) {
searchManager.setBool(this.boolFilterList);
}
if (listView.allResultIsChecked) {
this.trigger('select', {
massRelate: true,
where: this.collection.getWhere(),
searchParams: this.collection.data,
});
}
else {
var list = listView.getSelected();
if (list.length) {
this.trigger('select', list);
}
}
if (this.primaryFilterName) {
searchManager.setPrimary(this.primaryFilterName);
}
dialog.close();
},
});
}
collection.where = searchManager.getWhere();
collection.url = collection.entityType + '/action/listTree';
this.scope = this.options.scope;
var viewName = this.getMetadata()
.get('clientDefs.' + this.scope + '.recordViews.listSelectCategoryTree') ||
'views/record/list-tree';
this.$header = $('<span>');
this.$header.append(
$('<span>').text(
this.translate('Select') + ': ' +
this.getLanguage().translate(this.scope, 'scopeNamesPlural')
)
);
this.$header.prepend(
this.getHelper().getScopeColorIconHtml(this.scope)
);
this.waitForView('list');
Espo.loader.require('search-manager', SearchManager => {
this.getCollectionFactory().create(this.scope, collection => {
collection.maxSize = this.getConfig().get('recordsPerPageSelect') || 5;
this.collection = collection;
var searchManager = new SearchManager(collection, 'listSelect', null, this.getDateTime());
searchManager.emptyOnReset = true;
if (this.filters) {
searchManager.setAdvanced(this.filters);
}
if (this.boolFilterList) {
searchManager.setBool(this.boolFilterList);
}
if (this.primaryFilterName) {
searchManager.setPrimary(this.primaryFilterName);
}
collection.where = searchManager.getWhere();
collection.url = collection.entityType + '/action/listTree';
var viewName = this.getMetadata()
.get('clientDefs.' + this.scope + '.recordViews.listSelectCategoryTree') ||
'views/record/list-tree';
this.listenToOnce(collection, 'sync', () => {
this.createView('list', viewName, {
collection: collection,
el: this.containerSelector + ' .list-container',
readOnly: true,
selectable: true,
checkboxes: this.multiple,
massActionsDisabled: true,
searchManager: searchManager,
checkAllResultDisabled: true,
buttonsDisabled: true,
}, listView => {
listView.once('select', model => {
this.trigger('select', model);
this.close();
});
this.listenToOnce(collection, 'sync', () => {
this.createView('list', viewName, {
collection: collection,
el: this.containerSelector + ' .list-container',
readOnly: true,
selectable: true,
checkboxes: this.multiple,
massActionsDisabled: true,
searchManager: searchManager,
checkAllResultDisabled: true,
buttonsDisabled: true,
}, listView => {
listView.once('select', model => {
this.trigger('select', model);
this.close();
});
});
collection.fetch();
});
collection.fetch();
});
},
});
});
});
}
}
// noinspection JSUnusedGlobalSymbols
export default SelectCategoryTreeRecordsModalView;
@@ -29,7 +29,7 @@
import SelectRecordsModal from 'views/modals/select-records';
import ListWithCategories from 'views/list-with-categories';
class SelectRecordsWithCategoriesModal extends SelectRecordsModal {
class SelectRecordsWithCategoriesModalView extends SelectRecordsModal {
template = 'modals/select-records-with-categories'
@@ -117,9 +117,11 @@ class SelectRecordsWithCategoriesModal extends SelectRecordsModal {
ListWithCategories.prototype.applyCategoryToCollection.call(this);
}
// noinspection JSUnusedGlobalSymbols
isCategoryMultiple() {
ListWithCategories.prototype.isCategoryMultiple.call(this);
}
}
export default SelectRecordsWithCategoriesModal;
// noinspection JSUnusedGlobalSymbols
export default SelectRecordsWithCategoriesModalView;
+11 -14
View File
@@ -34,14 +34,13 @@ import SearchManager from 'search-manager';
/**
* A select-records modal.
*/
class SelectRecordsModal extends ModalView {
class SelectRecordsModalView extends ModalView {
template = 'modals/select-records'
cssName = 'select-modal'
className = 'dialog dialog-record'
multiple = false
header = false
createButton = true
searchPanel = true
scope = ''
@@ -49,34 +48,34 @@ class SelectRecordsModal extends ModalView {
/** @inheritDoc */
shortcutKeys = {
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'Control+Enter': function (e) {
this.handleShortcutKeyCtrlEnter(e);
},
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'Control+Space': function (e) {
this.handleShortcutKeyCtrlSpace(e);
},
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'Control+Slash': function (e) {
this.handleShortcutKeyCtrlSlash(e);
},
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'Control+Comma': function (e) {
this.handleShortcutKeyCtrlComma(e);
},
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'Control+Period': function (e) {
this.handleShortcutKeyCtrlPeriod(e);
},
}
events = {
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'click button[data-action="create"]': function () {
this.create();
},
/** @this SelectRecordsModal */
/** @this SelectRecordsModalView */
'click .list a': function (e) {
e.preventDefault();
},
@@ -459,9 +458,8 @@ class SelectRecordsModal extends ModalView {
/**
* @protected
* @param {JQueryKeyEventObject} e
*/
handleShortcutKeyCtrlComma(e) {
handleShortcutKeyCtrlComma() {
if (!this.getSearchView()) {
return;
}
@@ -471,9 +469,8 @@ class SelectRecordsModal extends ModalView {
/**
* @protected
* @param {JQueryKeyEventObject} e
*/
handleShortcutKeyCtrlPeriod(e) {
handleShortcutKeyCtrlPeriod() {
if (!this.getSearchView()) {
return;
}
@@ -482,4 +479,4 @@ class SelectRecordsModal extends ModalView {
}
}
export default SelectRecordsModal;
export default SelectRecordsModalView;
+26 -31
View File
@@ -26,43 +26,38 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/select-template', ['views/modals/select-records'], function (Dep) {
import SelectRecordsModalView from 'views/modals/select-records';
return Dep.extend({
class SelectTemplateModalView extends SelectRecordsModalView {
multiple: false,
multiple = false
createButton = false
searchPanel = false
scope = 'Template'
createButton: false,
loadSearch() {
super.loadSearch();
searchPanel: false,
this.searchManager.setAdvanced({
entityType: {
type: 'equals',
value: this.options.entityType,
},
});
scope: 'Template',
this.collection.where = this.searchManager.getWhere();
}
setup: function () {
Dep.prototype.setup.call(this);
},
afterRender() {
super.afterRender();
loadSearch: function () {
Dep.prototype.loadSearch.call(this);
let firstLinkElement = this.$el.find('a.link').first().get(0);
this.searchManager.setAdvanced({
entityType: {
type: 'equals',
value: this.options.entityType,
}
});
if (firstLinkElement) {
// noinspection JSUnresolvedReference
setTimeout(() => firstLinkElement.focus({preventScroll: true}), 10);
}
}
}
this.collection.where = this.searchManager.getWhere();
},
afterRender: function () {
Dep.prototype.afterRender.call(this);
let firstLinkElement = this.$el.find('a.link').first().get(0);
if (firstLinkElement) {
setTimeout(() => firstLinkElement.focus({preventScroll: true}), 10);
}
},
});
});
export default SelectTemplateModalView;
+24 -34
View File
@@ -26,46 +26,36 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/modals/view-map', ['views/modal'], function (Dep) {
import ModalView from 'views/modal';
return Dep.extend({
class ViewMapModalView extends ModalView {
backdrop: true,
templateContent = `<div class="map-container no-side-margin">{{{map}}}</div>`
fitHeight: true,
backdrop = true
templateContent: '<div class="map-container no-side-margin">{{{map}}}</div>',
setup() {
let field = this.options.field;
setup: function () {
this.buttonList = [
{
name: 'close',
label: 'Close',
}
];
},
let url = '#AddressMap/view/' + this.model.entityType + '/' + this.model.id + '/' + field;
let fieldLabel = this.translate(field, 'fields', this.model.entityType);
setup: function () {
let field = this.options.field;
this.headerElement =
$('<a>')
.attr('href', '#' + url)
.text(fieldLabel)
.get(0);
let url = '#AddressMap/view/' + this.model.entityType + '/' + this.model.id + '/' + field;
let fieldLabel = this.translate(field, 'fields', this.model.entityType);
let viewName = this.model.getFieldParam(field + 'Map', 'view') ||
this.getFieldManager().getViewName('map');
this.headerElement =
$('<a>')
.attr('href', '#' + url)
.text(fieldLabel)
.get(0);
this.createView('map', viewName, {
model: this.model,
name: field + 'Map',
el: this.getSelector() + ' .map-container',
height: 'auto',
});
}
}
let viewName = this.model.getFieldParam(field + 'Map', 'view') ||
this.getFieldManager().getViewName('map');
this.createView('map', viewName, {
model: this.model,
name: field + 'Map',
el: this.getSelector() + ' .map-container',
height: 'auto',
});
},
});
});
export default ViewMapModalView;