This commit is contained in:
Yuri Kuznetsov
2024-08-05 10:00:04 +03:00
parent 20ac2dd2d7
commit 4e3cb38477
6 changed files with 249 additions and 251 deletions
-2
View File
@@ -489,8 +489,6 @@ class EmailDetailView extends DetailView {
this.getAcl(),
);
this.getHelper().getAppParam()
const attributes = emailHelper.getReplyAttributes(this.model, data, cc);
Espo.Ui.notify(' ... ');
+33 -40
View File
@@ -26,51 +26,44 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/email/modals/attachments', ['views/modal'], function (Dep) {
import ModalView from 'views/modal';
/**
* @class
* @name Class
* @extends module:views/modal
* @memberOf module:views/email/modals/attachments
*/
return Dep.extend(/** @lends module:views/email/modals/attachments.Class# */{
export default class extends ModalView {
backdrop: true,
backdrop = true
templateContent: `<div class="record no-side-margin">{{{record}}}</div>`,
templateContent = `<div class="record no-side-margin">{{{record}}}</div>`
setup: function () {
Dep.prototype.setup.call(this);
setup() {
super.setup();
this.headerText = this.translate('attachments', 'fields', 'Email');
this.headerText = this.translate('attachments', 'fields', 'Email');
this.createView('record', 'views/record/detail', {
model: this.model,
selector: '.record',
readOnly: true,
sideView: null,
buttonsDisabled: true,
detailLayout: [
{
rows: [
[
{
name: 'attachments',
noLabel: true,
},
false,
]
this.createView('record', 'views/record/detail', {
model: this.model,
selector: '.record',
readOnly: true,
sideView: null,
buttonsDisabled: true,
detailLayout: [
{
rows: [
[
{
name: 'attachments',
noLabel: true,
},
false,
]
}
],
});
]
}
],
});
if (!this.model.has('attachmentsIds')) {
this.wait(
this.model.fetch()
);
}
},
});
});
if (!this.model.has('attachmentsIds')) {
this.wait(
this.model.fetch()
);
}
}
}
+23 -24
View File
@@ -26,35 +26,34 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/email/modals/body-plain', ['views/modal'], function (Dep) {
import ModalView from 'views/modal';
return Dep.extend({
export default class extends ModalView {
backdrop: true,
backdrop = true
templateContent: '<div class="field" data-name="body-plain">{{{bodyPlain}}}</div>',
templateContent = `<div class="field" data-name="body-plain">{{{bodyPlain}}}</div>`
setup: function () {
Dep.prototype.setup.call(this);
setup() {
super.setup();
this.buttonList.push({
'name': 'cancel',
'label': 'Close'
});
this.buttonList.push({
'name': 'cancel',
'label': 'Close',
});
this.headerText = this.model.get('name');
this.headerText = this.model.get('name');
this.createView('bodyPlain', 'views/fields/text', {
selector: '.field[data-name="bodyPlain"]',
model: this.model,
defs: {
name: 'bodyPlain',
params: {
readOnly: true,
inlineEditDisabled: true,
},
this.createView('bodyPlain', 'views/fields/text', {
selector: '.field[data-name="bodyPlain"]',
model: this.model,
defs: {
name: 'bodyPlain',
params: {
readOnly: true,
inlineEditDisabled: true,
},
});
},
});
});
},
});
}
}
+33 -32
View File
@@ -26,44 +26,45 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/email/modals/detail', ['views/modals/detail', 'views/email/detail'], function (Dep, Detail) {
import DetailModalView from 'views/modals/detail';
import DetailView from 'views/email/detail';
return Dep.extend({
export default class extends DetailModalView {
setup: function () {
Dep.prototype.setup.call(this);
setup() {
super.setup();
this.addButton({
name: 'reply',
label: 'Reply',
hidden: this.model && this.model.get('status') === 'Draft',
style: 'danger',
position: 'right',
}, true)
this.addButton({
name: 'reply',
label: 'Reply',
hidden: this.model && this.model.get('status') === 'Draft',
style: 'danger',
position: 'right',
}, true)
if (this.model) {
this.listenToOnce(this.model, 'sync', () => {
setTimeout(() => {
this.model.set('isRead', true);
}, 50);
});
}
},
if (this.model) {
this.listenToOnce(this.model, 'sync', () => {
setTimeout(() => {
this.model.set('isRead', true);
}, 50);
});
}
}
controlRecordButtonsVisibility: function () {
Dep.prototype.controlRecordButtonsVisibility.call(this);
controlRecordButtonsVisibility() {
super.controlRecordButtonsVisibility();
if (this.model.get('status') === 'Draft' || !this.getAcl().check('Email', 'create')) {
this.hideActionItem('reply');
if (this.model.get('status') === 'Draft' || !this.getAcl().check('Email', 'create')) {
this.hideActionItem('reply');
return;
}
return;
}
this.showActionItem('reply');
},
this.showActionItem('reply');
}
actionReply: function (data, e) {
Detail.prototype.actionReply.call(this, {}, e, this.getPreferences().get('emailReplyToAllByDefault'));
},
});
});
// noinspection JSUnusedGlobalSymbols
actionReply(data, e) {
DetailView.prototype.actionReply.call(this, {}, e, this.getPreferences().get('emailReplyToAllByDefault'));
}
}
+157 -153
View File
@@ -26,20 +26,21 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/email/modals/insert-field',
['views/modal', 'helpers/misc/field-language'], function (Dep, FieldLanguage) {
import ModalView from 'views/modal';
import FieldLanguage from 'helpers/misc/field-language';
return Dep.extend({
export default class extends ModalView {
backdrop: true,
backdrop = true
templateContent: `
{{#each viewObject.dataList}}
<div class="margin-bottom">
<h5>{{label}}: {{translate entityType category='scopeNames'}}</h5>
</div>
<ul class="list-group no-side-margin">
{{#each dataList}}
// language=Handlebars
templateContent = `
{{#each viewObject.dataList}}
<div class="margin-bottom">
<h5>{{label}}: {{translate entityType category='scopeNames'}}</h5>
</div>
<ul class="list-group no-side-margin">
{{#each dataList}}
<li class="list-group-item clearfix">
<a role="button"
data-action="insert" class="text-bold" data-name="{{name}}" data-type="{{../type}}">
@@ -51,176 +52,179 @@ define('views/email/modals/insert-field',
{{valuePreview}}
</div>
</li>
{{/each}}
</ul>
{{/each}}
{{/each}}
</ul>
{{/each}}
{{#unless viewObject.dataList.length}}
{{translate 'No Data'}}
{{/unless}}
`,
{{#unless viewObject.dataList.length}}
{{translate 'No Data'}}
{{/unless}}
`
events: {
'click [data-action="insert"]': function (e) {
let name = $(e.currentTarget).data('name');
let type = $(e.currentTarget).data('type');
setup() {
super.setup();
this.insert(type, name);
},
},
this.headerText = this.translate('Insert Field', 'labels', 'Email');
setup: function () {
Dep.prototype.setup.call(this);
this.fieldLanguage = new FieldLanguage(this.getMetadata(), this.getLanguage());
this.headerText = this.translate('Insert Field', 'labels', 'Email');
this.wait(
Espo.Ajax
.getRequest('Email/insertFieldData', {
parentId: this.options.parentId,
parentType: this.options.parentType,
to: this.options.to,
})
.then(fetchedData => {
this.fetchedData = fetchedData;
this.prepareData();
})
);
this.fieldLanguage = new FieldLanguage(this.getMetadata(), this.getLanguage());
this.addActionHandler('insert', (e, target) => {
const name = target.dataset.name;
const type = target.dataset.type;
this.wait(
Espo.Ajax
.getRequest('Email/insertFieldData', {
parentId: this.options.parentId,
parentType: this.options.parentType,
to: this.options.to,
})
.then(fetchedData => {
this.fetchedData = fetchedData;
this.prepareData();
})
);
},
this.insert(type, name);
})
}
prepareData: function () {
this.dataList = [];
prepareData() {
this.dataList = [];
var fetchedData = this.fetchedData;
var typeList = ['parent', 'to'];
const fetchedData = this.fetchedData;
const typeList = ['parent', 'to'];
typeList.forEach(type => {
if (!fetchedData[type]) {
typeList.forEach(type => {
if (!fetchedData[type]) {
return;
}
const entityType = fetchedData[type].entityType;
const id = fetchedData[type].id;
for (const it of this.dataList) {
if (it.id === id && it.entityType === entityType) {
return;
}
}
let entityType = fetchedData[type].entityType;
let id = fetchedData[type].id;
const dataList = this.prepareDisplayValueList(fetchedData[type].entityType, fetchedData[type].values);
for (let it of this.dataList) {
if (it.id === id && it.entityType === entityType) {
if (!dataList.length) {
return;
}
this.dataList.push({
type: type,
entityType: entityType,
id: id,
name: fetchedData[type].name,
dataList: dataList,
label: this.translate(type, 'fields', 'Email'),
});
});
}
prepareDisplayValueList(scope, values) {
const list = [];
let attributeList = Object.keys(values);
const labels = {};
attributeList.forEach(item => {
labels[item] = this.fieldLanguage.translateAttribute(scope, item);
});
attributeList = attributeList
.sort((v1, v2) => {
return labels[v1].localeCompare(labels[v2]);
});
const ignoreAttributeList = ['id', 'modifiedAt', 'modifiedByName'];
const fm = this.getFieldManager();
fm.getEntityTypeFieldList(scope).forEach(field => {
const type = this.getMetadata().get(['entityDefs', scope, 'fields', field, 'type']);
if (['link', 'linkOne', 'image', 'filed', 'linkParent'].includes(type)) {
ignoreAttributeList.push(field + 'Id');
}
if (type === 'linkParent') {
ignoreAttributeList.push(field + 'Type');
}
});
attributeList.forEach(item => {
if (~ignoreAttributeList.indexOf(item)) {
return;
}
let value = values[item];
if (value === null || value === '') {
return;
}
if (typeof value == 'boolean') {
return;
}
if (Array.isArray(value)) {
for (const v in value) {
if (typeof v !== 'string') {
return;
}
}
var dataList = this.prepareDisplayValueList(fetchedData[type].entityType, fetchedData[type].values);
value = value.split(', ');
}
if (!dataList.length) {
return;
}
value = this.getHelper().sanitizeHtml(value);
this.dataList.push({
type: type,
entityType: entityType,
id: id,
name: fetchedData[type].name,
dataList: dataList,
label: this.translate(type, 'fields', 'Email'),
});
const valuePreview = value.replace(/<br( \/)?>/gm, ' ');
// noinspection RegExpUnnecessaryNonCapturingGroup
value = value.replace(/(?:\r\n|\r|\n)/g, '');
value = value.replace(/<br( \/)?>/gm, '\n');
list.push({
name: item,
label: labels[item],
value: value,
valuePreview: valuePreview,
});
},
});
prepareDisplayValueList: function (scope, values) {
let list = [];
return list;
}
let attributeList = Object.keys(values);
let labels = {};
/**
* @private
* @param {string} type
* @param {string} name
*/
insert(type, name) {
for (const g of this.dataList) {
if (g.type !== type) {
continue;
}
attributeList.forEach(item => {
labels[item] = this.fieldLanguage.translateAttribute(scope, item);
});
attributeList = attributeList
.sort((v1, v2) => {
return labels[v1].localeCompare(labels[v2]);
});
let ignoreAttributeList = ['id', 'modifiedAt', 'modifiedByName'];
let fm = this.getFieldManager();
fm.getEntityTypeFieldList(scope).forEach(field => {
let type = this.getMetadata().get(['entityDefs', scope, 'fields', field, 'type']);
if (~['link', 'linkOne', 'image', 'filed', 'linkParent'].indexOf(type)) {
ignoreAttributeList.push(field + 'Id');
}
if (type === 'linkParent') {
ignoreAttributeList.push(field + 'Type');
}
});
attributeList.forEach(item => {
if (~ignoreAttributeList.indexOf(item)) {
return;
}
let value = values[item];
if (value === null || value === '') {
return;
}
if (typeof value == 'boolean') {
return;
}
if (Array.isArray(value)) {
for (let v in value) {
if (typeof v !== 'string') {
return;
}
}
value = value.split(', ');
}
value = this.getHelper().sanitizeHtml(value);
var valuePreview = value.replace(/<br( \/)?>/gm, ' ');
value = value.replace(/(?:\r\n|\r|\n)/g, '');
value = value.replace(/<br( \/)?>/gm, '\n');
list.push({
name: item,
label: labels[item],
value: value,
valuePreview: valuePreview,
});
});
return list;
},
insert: function (type, name) {
for (let g of this.dataList) {
if (g.type !== type) {
for (const i of g.dataList) {
if (i.name !== name) {
continue;
}
for (let i of g.dataList) {
if (i.name !== name) {
continue;
}
this.trigger('insert', i.value);
break;
}
this.trigger('insert', i.value);
break;
}
this.close();
},
});
});
break;
}
this.close();
}
}
+3
View File
@@ -284,6 +284,9 @@ class DetailModalView extends ModalView {
}
}
/**
* @protected
*/
controlRecordButtonsVisibility() {
if (this.getAcl().check(this.model, 'edit')) {
this.showButton('edit');