diff --git a/application/Espo/Tools/Pdf/Dompdf/HtmlComposer.php b/application/Espo/Tools/Pdf/Dompdf/HtmlComposer.php index 75ddd17331..1d8dfb8015 100644 --- a/application/Espo/Tools/Pdf/Dompdf/HtmlComposer.php +++ b/application/Espo/Tools/Pdf/Dompdf/HtmlComposer.php @@ -87,6 +87,10 @@ class HtmlComposer font-size: {$fontSize}pt; } + table.bordered, table.bordered td, table.bordered th { + border: 1px solid; + } + > header { position: fixed; margin-top: -{$topMargin}mm; diff --git a/client/src/helpers/misc/summernote-custom.js b/client/src/helpers/misc/summernote-custom.js index d06267dcc3..71384446ae 100644 --- a/client/src/helpers/misc/summernote-custom.js +++ b/client/src/helpers/misc/summernote-custom.js @@ -315,7 +315,7 @@ function init(langSets) { tds.push(' '); } - tdHTML = tds.join(''); + tdHTML = tds.join('\n'); const trs = []; let trHTML; @@ -323,22 +323,21 @@ function init(langSets) { trs.push('' + tdHTML + ''); } - trHTML = trs.join(''); - const $table = $('' + trHTML + '
'); + trHTML = trs.join('\n'); + const $table = $('\n' + trHTML + '
'); - if (options.tableBorderWidth !== undefined) { + /*if (options.tableBorderWidth !== undefined) { $table.attr('border', options.tableBorderWidth); - //$table.css({border: options.tableBorderWidth + 'pt'}); } if (options.tableCellPadding !== undefined) { $table.attr('cellpadding', options.tableCellPadding); - } + }*/ $table.css({ width: '100%', borderCollapse: 'collapse', - borderSpacing: 0, + //borderSpacing: 0, }); if (options && options.tableClassName) { diff --git a/client/src/views/admin/template-manager/fields/body.js b/client/src/views/admin/template-manager/fields/body.js index f88ece7efb..4c21603e8e 100644 --- a/client/src/views/admin/template-manager/fields/body.js +++ b/client/src/views/admin/template-manager/fields/body.js @@ -30,5 +30,6 @@ import WysiwygFieldView from 'views/fields/wysiwyg'; export default class extends WysiwygFieldView { + htmlPurificationForEditDisabled = true handlebars = true } diff --git a/client/src/views/fields/wysiwyg.js b/client/src/views/fields/wysiwyg.js index b81e0f7833..79861bbc57 100644 --- a/client/src/views/fields/wysiwyg.js +++ b/client/src/views/fields/wysiwyg.js @@ -50,10 +50,10 @@ class WysiwygFieldView extends TextFieldView { fetchEmptyValueAsNull = false validationElementSelector = '.note-editor' htmlPurificationDisabled = false + htmlPurificationForEditDisabled = false tableClassName = 'table table-bordered' - tableBorderWidth - tableCellPadding noStylesheet = false + useIframe = false handlebars = false events = { @@ -322,11 +322,11 @@ class WysiwygFieldView extends TextFieldView { const documentElement = iframeElement.contentWindow.document; - let body = this.sanitizeHtml(this.model.get(this.name) || ''); + let bodyHtml = this.sanitizeHtml(this.model.get(this.name) || ''); - const useFallbackStylesheet = this.getThemeManager().getParam('isDark') && this.htmlHasColors(body); + const useFallbackStylesheet = this.getThemeManager().getParam('isDark') && this.htmlHasColors(bodyHtml); const addFallbackClass = this.getThemeManager().getParam('isDark') && - (this.htmlHasColors(body) || this.noStylesheet); + (this.htmlHasColors(bodyHtml) || this.noStylesheet); const $iframeContainer = $iframe.parent(); @@ -345,10 +345,23 @@ class WysiwygFieldView extends TextFieldView { this.getThemeManager().getIframeStylesheet() ); - body = linkElement.outerHTML + body; + bodyHtml = linkElement.outerHTML + bodyHtml; } - documentElement.write(body); + let headHtml = ''; + + if (this.noStylesheet) { + const styleElement = documentElement.createElement('style'); + + styleElement.textContent = `\ntable.bordered, table.bordered td, table.bordered th {border: 1px solid;}\n`; + + headHtml = styleElement.outerHTML; + } + + // noinspection HtmlRequiredTitleElement + const documentHtml = `${headHtml}${bodyHtml}` + + documentElement.write(documentHtml); documentElement.close(); const $body = $iframe.contents().find('html body'); @@ -604,8 +617,6 @@ class WysiwygFieldView extends TextFieldView { dialogsInBody: this.$el, codeviewFilter: true, tableClassName: this.tableClassName, - tableBorderWidth: this.tableBorderWidth, - tableCellPadding: this.tableCellPadding, }; if (this.height) { diff --git a/client/src/views/template/fields/body.js b/client/src/views/template/fields/body.js index 1a1bce9577..9178ef8c19 100644 --- a/client/src/views/template/fields/body.js +++ b/client/src/views/template/fields/body.js @@ -33,9 +33,7 @@ class BodyTemplateFieldView extends WysiwygFieldView { htmlPurificationForEditDisabled = true noStylesheet = true useIframe = true - tableClassName = '' - tableBorderWidth = 1 - tableCellPadding = 2 + tableClassName = 'bordered' handlebars = true } diff --git a/frontend/less/espo/custom.less b/frontend/less/espo/custom.less index 9dc3345edb..de2b01e1af 100644 --- a/frontend/less/espo/custom.less +++ b/frontend/less/espo/custom.less @@ -1615,104 +1615,7 @@ table.less-padding td.cell[data-name="buttons"] > .btn-group { right: -11px; } -.panel.note-editor { - margin-bottom: 0; - .note-toolbar { - border-bottom: 0 !important; - background-color: transparent; - - > .btn-group { - margin-bottom: 5px; - .btn { - margin-bottom: 0; - } - } - } - - &.panel-default { - > .panel-heading .btn-default { - background-color: @btn-default-bg !important; - border-color: @btn-default-border !important; - } - } - - .panel-heading { - padding: 5px 5px 0 5px; - min-height: calc(30px + 10px); - } - - .note-editable { - min-height: 39px; - } - - &.note-frame { - .note-editing-area { - .note-editable { - background-color: var(--input-bg); - color: var(--input-color); - - &[contenteditable="false"] { - background-color: var(--text-color); - } - } - } - - .note-statusbar { - background-color: var(--input-bg); - border-bottom-left-radius: var(--border-radius); - border-bottom-right-radius: var(--border-radius); - height: 8px; - } - - output.note-status-output { - padding-top: 0; - } - } - - .tooltip > .tooltip-inner { - border-radius: var(--dropdown-border-radius); - } -} - -body .note-editor { - .panel-heading { - > .btn-group { - right: 0; - top: 0; - - > .btn { - > i, - > span { - position: relative; - top: 1px; - } - } - - > .btn-group { - > .btn { - > i, - > span { - position: relative; - top: 1px; - } - } - } - } - } - - &.codeview { - textarea.note-codable { - min-height: 400px; - } - } - - .note-statusbar.locked { - .note-resizebar { - display: none; - } - } -} .list > table thead > th { border-top-width: 1px !important; @@ -2178,10 +2081,6 @@ div[data-scope="User"] .field[data-name="avatar"] { line-height: @line-height-computed; } -.note-editable blockquote { - font-size: @font-size-base; -} - .legend-container > table { margin: 0 auto; } @@ -3012,45 +2911,6 @@ table.table-admin-panel { } } -.note-editor { - .note-toolbar.sticked { - z-index: 1; - position: fixed; - background-color: @panel-bg; - } - - &.panel > .panel-heading { - .btn { - //border-bottom-width: 1px; - padding-top: 4px; - padding-bottom: 4px; - } - - .dropdown-menu .btn-group > .btn { - > i { - top: 1px; - position: relative; - } - } - } - - .note-editing-area { - ul, - ol { - margin-top: (@line-height-computed / 2); - margin-bottom: (@line-height-computed / 2); - - &:first-child { - margin-top: 0; - } - - &:last-child { - margin-bottom: 0; - } - } - } -} - .array-add-list-group > li { input[type="checkbox"] { margin-right: 12px; @@ -3425,12 +3285,6 @@ a.close:hover { scrollbar-width: thin; } -.wysiwyg-iframe-container.fallback { - border-radius: var(--border-radius); - overflow: hidden; - background-color: var(--white-color); -} - * { scrollbar-width: auto; scrollbar-color: var(--scroll-thumb-bg) var(--scroll-bg); @@ -3703,9 +3557,8 @@ body > .autocomplete-suggestions.text-search-suggestions { } } - - @import "misc/kanban.less"; +@import "misc/wysiwyg.less"; @import "elements/placement.less"; @import "elements/site.less"; diff --git a/frontend/less/espo/misc/wysiwyg.less b/frontend/less/espo/misc/wysiwyg.less new file mode 100644 index 0000000000..99c886fa37 --- /dev/null +++ b/frontend/less/espo/misc/wysiwyg.less @@ -0,0 +1,156 @@ + +.wysiwyg-iframe-container { + &.fallback { + border-radius: var(--border-radius); + overflow: hidden; + background-color: var(--white-color); + } +} + +.note-editable blockquote { + font-size: @font-size-base; +} + +.note-editor { + .note-toolbar.sticked { + z-index: 1; + position: fixed; + background-color: @panel-bg; + } + + &.panel > .panel-heading { + .btn { + //border-bottom-width: 1px; + padding-top: 4px; + padding-bottom: 4px; + } + + .dropdown-menu .btn-group > .btn { + > i { + top: 1px; + position: relative; + } + } + } + + .note-editing-area { + ul, + ol { + margin-top: (@line-height-computed / 2); + margin-bottom: (@line-height-computed / 2); + + &:first-child { + margin-top: 0; + } + + &:last-child { + margin-bottom: 0; + } + } + } +} + +.panel.note-editor { + margin-bottom: 0; + + .note-toolbar { + border-bottom: 0 !important; + background-color: transparent; + + > .btn-group { + margin-bottom: 5px; + .btn { + margin-bottom: 0; + } + } + } + + &.panel-default { + > .panel-heading .btn-default { + background-color: @btn-default-bg !important; + border-color: @btn-default-border !important; + } + } + + .panel-heading { + padding: 5px 5px 0 5px; + min-height: calc(30px + 10px); + } + + .note-editable { + min-height: 39px; + + table.bordered { + &, th, td { + border: 1px solid; + } + } + } + + &.note-frame { + .note-editing-area { + .note-editable { + background-color: var(--input-bg); + color: var(--input-color); + + &[contenteditable="false"] { + background-color: var(--text-color); + } + } + } + + .note-statusbar { + background-color: var(--input-bg); + border-bottom-left-radius: var(--border-radius); + border-bottom-right-radius: var(--border-radius); + height: 8px; + } + + output.note-status-output { + padding-top: 0; + } + } + + .tooltip > .tooltip-inner { + border-radius: var(--dropdown-border-radius); + } +} + +body .note-editor { + .panel-heading { + > .btn-group { + right: 0; + top: 0; + + > .btn { + > i, + > span { + position: relative; + top: 1px; + } + } + + > .btn-group { + > .btn { + > i, + > span { + position: relative; + top: 1px; + } + } + } + } + } + + &.codeview { + textarea.note-codable { + min-height: 400px; + } + } + + .note-statusbar.locked { + .note-resizebar { + display: none; + } + } +}