wysiwyg cell params

This commit is contained in:
Yuri Kuznetsov
2024-05-06 15:40:37 +03:00
parent 2a42ab8db5
commit a26a48fac7
4 changed files with 316 additions and 29 deletions
@@ -922,18 +922,26 @@
"Activities": "Activities"
},
"wysiwygLabels": {
"cell": "Cell",
"align": "Align",
"width": "Width",
"height": "Height",
"borderWidth": "Border Width",
"borderColor": "Border Color",
"cellPadding": "Cell Padding",
"backgroundColor": "Background Color"
"backgroundColor": "Background Color",
"verticalAlign": "Vertical Align"
},
"wysiwygOptions": {
"align": {
"left": "Left",
"center": "Center",
"right": "Right"
},
"verticalAlign": {
"top": "Top",
"middle": "Middle",
"bottom": "Bottom"
}
}
}
+95 -15
View File
@@ -28,6 +28,7 @@
import $ from 'jquery';
import EditTableModalView from 'views/wysiwyg/modals/edit-table';
import EditCellModalView from 'views/wysiwyg/modals/edit-cell';
/**
* @type {{
@@ -53,7 +54,7 @@ function init(langSets) {
},
popover: {
table: [
['custom', ['tableParams']],
['custom', ['tableParams', 'cellParams']],
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
],
@@ -61,6 +62,81 @@ function init(langSets) {
});
$.extend($.summernote.plugins, {
'cellParams': function (/** Record */context) {
const ui = $.summernote.ui;
const options = context.options;
const view = /** @type {import('view').default} */options.espoView;
context.memo('button.cellParams', () => {
return ui.button({
className: '',
contents: '<i class="far fa-square fa-sm"/>',
tooltip: view.translate('cell', 'wysiwygLabels'),
click: () => {
context.invoke('cellParams.show');
},
}).render();
});
this.show = function () {
const range = context.invoke('editor.getLastRange');
const $td = $(range.ec).closest('td,th');
const td = /** @type {HTMLTableCellElement} */$td[0];
const width = td.style.width;
const height = td.style.height;
const backgroundColor = td.style.backgroundColor;
const verticalAlign = td.style.verticalAlign;
const params = {
width,
height,
backgroundColor,
verticalAlign,
};
//const prevParams = params;
const modalView = new EditCellModalView({
params,
headerText: view.translate('cell', 'wysiwygLabels'),
onApply: params => applyParams(params),
});
view.assignView('dialog', modalView)
.then(() => {
modalView.render();
});
/**
* @param {{
* width: string|null,
* height: string|null,
* backgroundColor: string|null,
* verticalAlign: string|null,
* }} params
*/
const applyParams = params => {
let backgroundColor = td.style.backgroundColor;
if (backgroundColor === 'transparent') {
backgroundColor = null;
}
td.style.backgroundColor = params.backgroundColor;
td.style.width = params.width;
td.style.height = params.height;
td.style.verticalAlign = params.verticalAlign;
};
};
this.destroy = function () {
if (view) {
view.clearView('dialog');
}
};
},
'tableParams': function (/** Record */context) {
const ui = $.summernote.ui;
@@ -71,7 +147,7 @@ function init(langSets) {
return ui.button({
className: '',
contents: '<i class="note-icon-table"/>',
tooltip: langSets.table.table, // @todo
tooltip: langSets.table.table,
click: () => {
context.invoke('tableParams.show');
},
@@ -81,7 +157,7 @@ function init(langSets) {
this.show = function () {
const range = context.invoke('editor.getLastRange');
const $table = $(range.ec).closest('table');
const table = /** @type {HTMLTableElement}*/$table[0];
const table = /** @type {HTMLTableElement} */$table[0];
let borderWidth = table.style.borderWidth;
@@ -136,10 +212,12 @@ function init(langSets) {
}
const width = table.style.width;
const height = table.style.height;
const params = {
align,
width,
height,
borderWidth,
borderColor,
cellPadding,
@@ -159,17 +237,18 @@ function init(langSets) {
modalView.render();
});
const applyParams =
/** {
* align: string,
* width: string,
* borderWidth: string,
* borderColor: string,
* cellPadding: string,
* backgroundColor: string,
* } */
params => {
/**
* @param {{
* align: string|null,
* width: string|null,
* height: string|null,
* borderWidth: string|null,
* borderColor: string|null,
* cellPadding: string|null,
* backgroundColor: string|null,
* }} params
*/
const applyParams = params => {
if (params.align === 'left') {
table.style.marginLeft = '0';
table.style.marginRight = 'auto';
@@ -186,6 +265,7 @@ function init(langSets) {
table.style.backgroundColor = params.backgroundColor;
table.style.width = params.width;
table.style.height = params.height;
if (params.borderWidth !== null || prevParams.borderWidth !== null) {
table.style.borderWidth = params.borderWidth;
@@ -205,7 +285,7 @@ function init(langSets) {
}
}
if (params.padding !== null || prevParams.padding !== null) {
if (params.cellPadding !== null || prevParams.padding !== null) {
for (const /** HTMLTableCellElement */cell of table.querySelectorAll('td, th')) {
cell.style.padding = params.cellPadding;
}
@@ -0,0 +1,173 @@
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2024 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
import ModalView from 'views/modal';
import EditForModal from 'views/record/edit-for-modal';
import Model from 'model';
import VarcharFieldView from 'views/fields/varchar';
import ColorpickerFieldView from 'views/fields/colorpicker';
import EnumFieldView from 'views/fields/enum';
class EditCellModalView extends ModalView {
templateContent = `
<div class="record no-side-margin">{{{record}}}</div>
`
/**
* @param {{
* params: {
* width: null|string,
* height: null|height,
* backgroundColor: null|string,
* verticalAlign: null|'top'|'middle'|'bottom',
* },
* onApply: function({
* width: null|string,
* height: null|height,
* backgroundColor: null|string,
* verticalAlign: null|'top'|'middle'|'bottom',
* }),
* }} options
*/
constructor(options) {
super(options);
this.params = options.params;
this.onApply = options.onApply;
}
setup() {
this.addButton({
name: 'apply',
style: 'primary',
label: 'Apply',
onClick: () => this.apply(),
});
this.addButton({
name: 'cancel',
label: 'Cancel',
onClick: () => this.close(),
});
this.shortcutKeys = {
'Control+Enter': () => this.apply(),
};
this.model = new Model({
width: this.params.width,
height: this.params.height,
backgroundColor: this.params.backgroundColor,
verticalAlign: this.params.verticalAlign,
});
this.recordView = new EditForModal({
model: this.model,
detailLayout: [
{
rows: [
[
{
view: new VarcharFieldView({
name: 'width',
labelText: this.translate('width', 'wysiwygLabels'),
params: {
maxLength: 12,
},
}),
},
{
view: new VarcharFieldView({
name: 'height',
labelText: this.translate('height', 'wysiwygLabels'),
params: {
maxLength: 12,
},
}),
},
],
[
{
view: new EnumFieldView({
name: 'verticalAlign',
labelText: this.translate('verticalAlign', 'wysiwygLabels'),
params: {
options: [
'',
'top',
'middle',
'bottom',
],
translation: 'Global.wysiwygOptions.verticalAlign',
},
}),
},
{
view: new ColorpickerFieldView({
name: 'backgroundColor',
labelText: this.translate('backgroundColor', 'wysiwygLabels'),
}),
},
]
],
},
],
});
this.assignView('record', this.recordView, '.record');
}
apply() {
if (this.recordView.validate()) {
return;
}
let width = this.model.attributes.width;
if (/^\d+$/.test(width)) {
width += 'px';
}
let height = this.model.attributes.height;
if (/^\d+$/.test(height)) {
height += 'px';
}
this.onApply({
width: width,
height: height,
backgroundColor: this.model.attributes.backgroundColor,
verticalAlign: this.model.attributes.verticalAlign,
});
this.close();
}
}
export default EditCellModalView
+39 -13
View File
@@ -43,6 +43,7 @@ class EditTableModalView extends ModalView {
* params: {
* align: null|'left'|'center'|'right',
* width: null|string,
* height: null|string,
* borderWidth: null|string,
* borderColor: null|string,
* cellPadding: null|string,
@@ -51,6 +52,7 @@ class EditTableModalView extends ModalView {
* onApply: function({
* align: null|'left'|'center'|'right',
* width: null|string,
* height: null|string,
* borderWidth: null|string,
* borderColor: null|string,
* cellPadding: null|string,
@@ -86,6 +88,7 @@ class EditTableModalView extends ModalView {
this.model = new Model({
align: this.params.align,
width: this.params.width,
height: this.params.height,
borderWidth: this.params.borderWidth,
borderColor: this.params.borderColor,
cellPadding: this.params.cellPadding,
@@ -99,24 +102,18 @@ class EditTableModalView extends ModalView {
rows: [
[
{
view: new EnumFieldView({
name: 'align',
labelText: this.translate('align', 'wysiwygLabels'),
view: new VarcharFieldView({
name: 'width',
labelText: this.translate('width', 'wysiwygLabels'),
params: {
options: [
'',
'left',
'center',
'right',
],
translation: 'Global.wysiwygOptions.align',
maxLength: 12,
},
}),
},
{
view: new VarcharFieldView({
name: 'width',
labelText: this.translate('width', 'wysiwygLabels'),
name: 'height',
labelText: this.translate('height', 'wysiwygLabels'),
params: {
maxLength: 12,
},
@@ -157,6 +154,24 @@ class EditTableModalView extends ModalView {
}),
},
],
[
{
view: new EnumFieldView({
name: 'align',
labelText: this.translate('align', 'wysiwygLabels'),
params: {
options: [
'',
'left',
'center',
'right',
],
translation: 'Global.wysiwygOptions.align',
},
}),
},
false
],
],
},
],
@@ -172,6 +187,8 @@ class EditTableModalView extends ModalView {
let borderWidth = this.model.attributes.borderWidth;
let cellPadding = this.model.attributes.cellPadding;
let width = this.model.attributes.width;
let height = this.model.attributes.height;
if (/^\d+$/.test(borderWidth)) {
borderWidth += 'px';
@@ -181,9 +198,18 @@ class EditTableModalView extends ModalView {
cellPadding += 'px';
}
if (/^\d+$/.test(width)) {
width += 'px';
}
if (/^\d+$/.test(height)) {
height += 'px';
}
this.onApply({
align: this.model.attributes.align,
width: this.model.attributes.width,
width: width,
height: height,
borderWidth: borderWidth,
borderColor: this.model.attributes.borderColor,
cellPadding: cellPadding,