GrapesJS support more or less finished.
This commit is contained in:
parent
b089993360
commit
c7d7b1fe0c
6 changed files with 535 additions and 36 deletions
18
client/package-lock.json
generated
18
client/package-lock.json
generated
|
@ -2180,6 +2180,11 @@
|
|||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"ckeditor": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/ckeditor/-/ckeditor-4.11.1.tgz",
|
||||
"integrity": "sha512-UhHe02cc/wWJquDQZysEgh0ohLMEMU56zDx+s8prDdjylY/aBDY2xdIiIpbgCBTXdjhrEPIAPyiDS9g3RxYXig=="
|
||||
},
|
||||
"ckeditor5": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-11.1.1.tgz",
|
||||
|
@ -4909,6 +4914,19 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"grapesjs-plugin-ckeditor": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/grapesjs-plugin-ckeditor/-/grapesjs-plugin-ckeditor-0.0.9.tgz",
|
||||
"integrity": "sha512-QXyAcSwgi09pzigGVS/NsHag5Skuw4zTkVGmEiBN/Qi8KU12/cQBG/OjAcjAB3/ZpToyPoglI33Ydjgj2nJuxQ=="
|
||||
},
|
||||
"grapesjs-preset-newsletter": {
|
||||
"version": "0.2.20",
|
||||
"resolved": "https://registry.npmjs.org/grapesjs-preset-newsletter/-/grapesjs-preset-newsletter-0.2.20.tgz",
|
||||
"integrity": "sha512-rffUeuznf9Saig+kIUddmGfhWwbLjxdaqAYf6Hoge4b0sfT8knOS4mQXJBdRsSROfzuRhFe6ybRHm4yC32lHxA==",
|
||||
"requires": {
|
||||
"juice": "4.3.2"
|
||||
}
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"datatables.net-bs": "^1.10.15",
|
||||
"grapesjs": "^0.14.40",
|
||||
"grapesjs-mjml": "0.0.27",
|
||||
"grapesjs-preset-newsletter": "^0.2.20",
|
||||
"i18next": "^8.4.3",
|
||||
"i18next-xhr-backend": "^1.4.2",
|
||||
"immutable": "^3.8.1",
|
||||
|
|
|
@ -31,16 +31,26 @@ import mjml2html from "mjml4-in-browser";
|
|||
|
||||
import 'grapesjs/dist/css/grapes.min.css';
|
||||
import grapesjs from 'grapesjs';
|
||||
import "grapesjs-mjml";
|
||||
|
||||
import 'grapesjs-mjml';
|
||||
|
||||
import 'grapesjs-preset-newsletter';
|
||||
import 'grapesjs-preset-newsletter/dist/grapesjs-preset-newsletter.css';
|
||||
|
||||
import "./sandboxed-grapesjs.scss";
|
||||
|
||||
import axios from './axios';
|
||||
import {GrapesJSSourceType} from "./sandboxed-grapesjs-shared";
|
||||
|
||||
grapesjs.plugins.add('mailtrain', (editor, opts = {}) => {
|
||||
|
||||
grapesjs.plugins.add('mailtrain-remove-buttons', (editor, opts = {}) => {
|
||||
// This needs to be done in on-load and after gjs plugin because grapesjs-preset-newsletter tries to set titles to all buttons (including those we remove)
|
||||
// see https://github.com/artf/grapesjs-preset-newsletter/blob/e0a91636973a5a1481e9d7929e57a8869b1db72e/src/index.js#L248
|
||||
editor.on('load', () => {
|
||||
const panelManager = editor.Panels;
|
||||
panelManager.removeButton('options','fullscreen');
|
||||
panelManager.removeButton('options','export-template');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
@ -60,16 +70,19 @@ export class GrapesJSSandbox extends Component {
|
|||
entityTypeId: PropTypes.string,
|
||||
entityId: PropTypes.number,
|
||||
initialSource: PropTypes.string,
|
||||
initialStyle: PropTypes.string
|
||||
initialStyle: PropTypes.string,
|
||||
sourceType: PropTypes.string
|
||||
}
|
||||
|
||||
async exportState(method, params) {
|
||||
const props = this.props;
|
||||
|
||||
const editor = this.editor;
|
||||
|
||||
// If exportState comes during text editing (via RichTextEditor), we need to cancel the editing, so that the
|
||||
// text being edited is stored in the model
|
||||
const sel = editor.getSelected();
|
||||
if (sel && sel.view && sel.disableEditing) {
|
||||
if (sel && sel.view && sel.view.disableEditing) {
|
||||
sel.view.disableEditing();
|
||||
}
|
||||
|
||||
|
@ -82,11 +95,21 @@ export class GrapesJSSandbox extends Component {
|
|||
|
||||
let html;
|
||||
|
||||
if (props.sourceType === GrapesJSSourceType.MJML) {
|
||||
const preMjml = '<mjml><mj-head></mj-head><mj-body>';
|
||||
const postMjml = '</mj-body></mjml>';
|
||||
const mjml = preMjml + source + postMjml;
|
||||
|
||||
const mjmlRes = mjml2html(mjml);
|
||||
html = mjmlRes.html;
|
||||
|
||||
} else if (props.sourceType === GrapesJSSourceType.HTML) {
|
||||
const commandManager = editor.Commands;
|
||||
|
||||
const cmdGetCode = commandManager.get('gjs-get-inlined-html');
|
||||
html = cmdGetCode.run(editor);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
html,
|
||||
|
@ -124,19 +147,7 @@ export class GrapesJSSandbox extends Component {
|
|||
const sandboxUrlBase = getSandboxUrl();
|
||||
const publicUrlBase = getPublicUrl();
|
||||
|
||||
const source = props.initialSource ?
|
||||
base(props.initialSource, trustedUrlBase, sandboxUrlBase, publicUrlBase) :
|
||||
' <mj-container>\n' +
|
||||
' <mj-section>\n' +
|
||||
' <mj-column>\n' +
|
||||
' <mj-text>My Company</mj-text>\n' +
|
||||
' </mj-column>\n' +
|
||||
' </mj-section>\n' +
|
||||
' </mj-container>';
|
||||
|
||||
const css = props.initialStyle && base(props.initialStyle, trustedUrlBase, sandboxUrlBase, publicUrlBase);
|
||||
|
||||
this.editor = grapesjs.init({
|
||||
const config = {
|
||||
noticeOnUnload: false,
|
||||
container: this.canvasNode,
|
||||
height: '100%',
|
||||
|
@ -157,19 +168,458 @@ export class GrapesJSSandbox extends Component {
|
|||
clearProperties: true,
|
||||
},
|
||||
fromElement: false,
|
||||
components: source,
|
||||
style: css,
|
||||
components: '',
|
||||
style: '',
|
||||
plugins: [
|
||||
'mailtrain',
|
||||
'gjs-mjml'
|
||||
],
|
||||
pluginsOpts: {
|
||||
'gjs-mjml': {
|
||||
}
|
||||
};
|
||||
|
||||
let defaultSource, defaultStyle;
|
||||
|
||||
if (props.sourceType === GrapesJSSourceType.MJML) {
|
||||
defaultSource =
|
||||
'<mj-container>\n' +
|
||||
' <mj-section>\n' +
|
||||
' <mj-column>\n' +
|
||||
' <mj-text>Lorem Ipsum...</mj-text>\n' +
|
||||
' </mj-column>\n' +
|
||||
' </mj-section>\n' +
|
||||
'</mj-container>';
|
||||
|
||||
defaultStyle = '';
|
||||
|
||||
config.plugins.push('gjs-mjml');
|
||||
config.pluginsOpts['gjs-mjml'] = {
|
||||
preMjml: '<mjml><mj-head></mj-head><mj-body>',
|
||||
postMjml: '</mj-body></mjml>'
|
||||
};
|
||||
|
||||
} else if (props.sourceType === GrapesJSSourceType.HTML) {
|
||||
defaultSource =
|
||||
'<table class="main-body">\n' +
|
||||
' <tr class="row">\n' +
|
||||
' <td class="main-body-cell">\n' +
|
||||
' <table class="container">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="container-cell">\n' +
|
||||
' <table class="table100 c1790">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="top-cell" id="c1793">\n' +
|
||||
' <u class="browser-link" id="c307">View in browser\n' +
|
||||
' </u>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' <table class="c1766">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="cell c1769">\n' +
|
||||
' <img class="c926" src="http://artf.github.io/grapesjs/img/grapesjs-logo.png" alt="GrapesJS."/>\n' +
|
||||
' </td>\n' +
|
||||
' <td class="cell c1776">\n' +
|
||||
' <div class="c1144">GrapesJS Newsletter Builder\n' +
|
||||
' <br/>\n' +
|
||||
' </div>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' <table class="card">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="card-cell">\n' +
|
||||
' <img class="c1271" src="http://artf.github.io/grapesjs/img/tmp-header-txt.jpg" alt="Big image here"/>\n' +
|
||||
' <table class="table100 c1357">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="card-content">\n' +
|
||||
' <h1 class="card-title">Build your newsletters faster than ever\n' +
|
||||
' <br/>\n' +
|
||||
' </h1>\n' +
|
||||
' <p class="card-text">Import, build, test and export responsive newsletter templates faster than ever using the GrapesJS Newsletter Builder.\n' +
|
||||
' </p>\n' +
|
||||
' <table class="c1542">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="card-footer" id="c1545">\n' +
|
||||
' <a class="button" href="https://github.com/artf/grapesjs">Free and Open Source\n' +
|
||||
' </a>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' <table class="list-item">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="list-item-cell">\n' +
|
||||
' <table class="list-item-content">\n' +
|
||||
' <tr class="list-item-row">\n' +
|
||||
' <td class="list-cell-left">\n' +
|
||||
' <img class="list-item-image" src="http://artf.github.io/grapesjs/img/tmp-blocks.jpg" alt="Image1"/>\n' +
|
||||
' </td>\n' +
|
||||
' <td class="list-cell-right">\n' +
|
||||
' <h1 class="card-title">Built-in Blocks\n' +
|
||||
' </h1>\n' +
|
||||
' <p class="card-text">Drag and drop built-in blocks from the right panel and style them in a matter of seconds\n' +
|
||||
' </p>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' <table class="list-item">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="list-item-cell">\n' +
|
||||
' <table class="list-item-content">\n' +
|
||||
' <tr class="list-item-row">\n' +
|
||||
' <td class="list-cell-left">\n' +
|
||||
' <img class="list-item-image" src="http://artf.github.io/grapesjs/img/tmp-tgl-images.jpg" alt="Image2"/>\n' +
|
||||
' </td>\n' +
|
||||
' <td class="list-cell-right">\n' +
|
||||
' <h1 class="card-title">Toggle images\n' +
|
||||
' </h1>\n' +
|
||||
' <p class="card-text">Build a good looking newsletter even without images enabled by the email clients\n' +
|
||||
' </p>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' <table class="grid-item-row">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="grid-item-cell2-l">\n' +
|
||||
' <table class="grid-item-card">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="grid-item-card-cell">\n' +
|
||||
' <img class="grid-item-image" src="http://artf.github.io/grapesjs/img/tmp-send-test.jpg" alt="Image1"/>\n' +
|
||||
' <table class="grid-item-card-body">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="grid-item-card-content">\n' +
|
||||
' <h1 class="card-title">Test it\n' +
|
||||
' </h1>\n' +
|
||||
' <p class="card-text">You can send email tests directly from the editor and check how are looking on your email clients\n' +
|
||||
' </p>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' <td class="grid-item-cell2-r">\n' +
|
||||
' <table class="grid-item-card">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="grid-item-card-cell">\n' +
|
||||
' <img class="grid-item-image" src="http://artf.github.io/grapesjs/img/tmp-devices.jpg" alt="Image2"/>\n' +
|
||||
' <table class="grid-item-card-body">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="grid-item-card-content">\n' +
|
||||
' <h1 class="card-title">Responsive\n' +
|
||||
' </h1>\n' +
|
||||
' <p class="card-text">Using the device manager you\'ll always send a fully responsive contents\n' +
|
||||
' </p>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' <table class="footer">\n' +
|
||||
' <tr>\n' +
|
||||
' <td class="footer-cell">\n' +
|
||||
' <div class="c2577">\n' +
|
||||
' <p class="footer-info">GrapesJS Newsletter Builder is a free and open source preset (plugin) used on top of the GrapesJS core library.\n' +
|
||||
' For more information about and how to integrate it inside your applications check<p>\n' +
|
||||
' <a class="link" href="https://github.com/artf/grapesjs-preset-newsletter">GrapesJS Newsletter Preset</a>\n' +
|
||||
' <br/>\n' +
|
||||
' </div>\n' +
|
||||
' <div class="c2421">\n' +
|
||||
' MADE BY <a class="link" href="https://github.com/artf">ARTUR ARSENIEV</a>\n' +
|
||||
' <p>\n' +
|
||||
' </div>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
' </table>\n' +
|
||||
' </td>\n' +
|
||||
' </tr>\n' +
|
||||
'</table>';
|
||||
|
||||
defaultStyle =
|
||||
'.link {\n' +
|
||||
' color: rgb(217, 131, 166);\n' +
|
||||
' }\n' +
|
||||
' .row{\n' +
|
||||
' vertical-align:top;\n' +
|
||||
' }\n' +
|
||||
' .main-body{\n' +
|
||||
' min-height:150px;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' width:100%;\n' +
|
||||
' height:100%;\n' +
|
||||
' background-color:rgb(234, 236, 237);\n' +
|
||||
' }\n' +
|
||||
' .c926{\n' +
|
||||
' color:rgb(158, 83, 129);\n' +
|
||||
' width:100%;\n' +
|
||||
' font-size:50px;\n' +
|
||||
' }\n' +
|
||||
' .cell.c849{\n' +
|
||||
' width:11%;\n' +
|
||||
' }\n' +
|
||||
' .c1144{\n' +
|
||||
' padding: 10px;\n' +
|
||||
' font-size:17px;\n' +
|
||||
' font-weight: 300;\n' +
|
||||
' }\n' +
|
||||
' .card{\n' +
|
||||
' min-height:150px;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' margin-bottom:20px;\n' +
|
||||
' height:0px;\n' +
|
||||
' }\n' +
|
||||
' .card-cell{\n' +
|
||||
' background-color:rgb(255, 255, 255);\n' +
|
||||
' overflow:hidden;\n' +
|
||||
' border-radius: 3px;\n' +
|
||||
' padding: 0;\n' +
|
||||
' text-align:center;\n' +
|
||||
' }\n' +
|
||||
' .card.sector{\n' +
|
||||
' background-color:rgb(255, 255, 255);\n' +
|
||||
' border-radius: 3px;\n' +
|
||||
' border-collapse:separate;\n' +
|
||||
' }\n' +
|
||||
' .c1271{\n' +
|
||||
' width:100%;\n' +
|
||||
' margin: 0 0 15px 0;\n' +
|
||||
' font-size:50px;\n' +
|
||||
' color:rgb(120, 197, 214);\n' +
|
||||
' line-height:250px;\n' +
|
||||
' text-align:center;\n' +
|
||||
' }\n' +
|
||||
' .table100{\n' +
|
||||
' width:100%;\n' +
|
||||
' }\n' +
|
||||
' .c1357{\n' +
|
||||
' min-height:150px;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' margin: auto;\n' +
|
||||
' height:0px;\n' +
|
||||
' }\n' +
|
||||
' .darkerfont{\n' +
|
||||
' color:rgb(65, 69, 72);\n' +
|
||||
' }\n' +
|
||||
' .button{\n' +
|
||||
' font-size:12px;\n' +
|
||||
' padding: 10px 20px;\n' +
|
||||
' background-color:rgb(217, 131, 166);\n' +
|
||||
' color:rgb(255, 255, 255);\n' +
|
||||
' text-align:center;\n' +
|
||||
' border-radius: 3px;\n' +
|
||||
' font-weight:300;\n' +
|
||||
' }\n' +
|
||||
' .table100.c1437{\n' +
|
||||
' text-align:left;\n' +
|
||||
' }\n' +
|
||||
' .cell.cell-bottom{\n' +
|
||||
' text-align:center;\n' +
|
||||
' height:51px;\n' +
|
||||
' }\n' +
|
||||
' .card-title{\n' +
|
||||
' font-size:25px;\n' +
|
||||
' font-weight:300;\n' +
|
||||
' color:rgb(68, 68, 68);\n' +
|
||||
' }\n' +
|
||||
' .card-content{\n' +
|
||||
' font-size:13px;\n' +
|
||||
' line-height:20px;\n' +
|
||||
' color:rgb(111, 119, 125);\n' +
|
||||
' padding: 10px 20px 0 20px;\n' +
|
||||
' vertical-align:top;\n' +
|
||||
' }\n' +
|
||||
' .container{\n' +
|
||||
' font-family: Helvetica, serif;\n' +
|
||||
' min-height:150px;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' margin:auto;\n' +
|
||||
' height:0px;\n' +
|
||||
' width:90%;\n' +
|
||||
' max-width:550px;\n' +
|
||||
' }\n' +
|
||||
' .cell.c856{\n' +
|
||||
' vertical-align:middle;\n' +
|
||||
' }\n' +
|
||||
' .container-cell{\n' +
|
||||
' vertical-align:top;\n' +
|
||||
' font-size:medium;\n' +
|
||||
' padding-bottom:50px;\n' +
|
||||
' }\n' +
|
||||
' .c1790{\n' +
|
||||
' min-height:150px;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' margin:auto;\n' +
|
||||
' height:0px;\n' +
|
||||
' }\n' +
|
||||
' .table100.c1790{\n' +
|
||||
' min-height:30px;\n' +
|
||||
' border-collapse:separate;\n' +
|
||||
' margin: 0 0 10px 0;\n' +
|
||||
' }\n' +
|
||||
' .browser-link{\n' +
|
||||
' font-size:12px;\n' +
|
||||
' }\n' +
|
||||
' .top-cell{\n' +
|
||||
' text-align:right;\n' +
|
||||
' color:rgb(152, 156, 165);\n' +
|
||||
' }\n' +
|
||||
' .table100.c1357{\n' +
|
||||
' margin: 0;\n' +
|
||||
' border-collapse:collapse;\n' +
|
||||
' }\n' +
|
||||
' .c1769{\n' +
|
||||
' width:30%;\n' +
|
||||
' }\n' +
|
||||
' .c1776{\n' +
|
||||
' width:70%;\n' +
|
||||
' }\n' +
|
||||
' .c1766{\n' +
|
||||
' margin: 0 auto 10px 0;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' width:100%;\n' +
|
||||
' min-height:30px;\n' +
|
||||
' }\n' +
|
||||
' .cell.c1769{\n' +
|
||||
' width:11%;\n' +
|
||||
' }\n' +
|
||||
' .cell.c1776{\n' +
|
||||
' vertical-align:middle;\n' +
|
||||
' }\n' +
|
||||
' .c1542{\n' +
|
||||
' margin: 0 auto 10px auto;\n' +
|
||||
' padding:5px;\n' +
|
||||
' width:100%;\n' +
|
||||
' }\n' +
|
||||
' .card-footer{\n' +
|
||||
' padding: 20px 0;\n' +
|
||||
' text-align:center;\n' +
|
||||
' }\n' +
|
||||
' .c2280{\n' +
|
||||
' height:150px;\n' +
|
||||
' margin:0 auto 10px auto;\n' +
|
||||
' padding:5px 5px 5px 5px;\n' +
|
||||
' width:100%;\n' +
|
||||
' }\n' +
|
||||
' .c2421{\n' +
|
||||
' padding:10px;\n' +
|
||||
' }\n' +
|
||||
' .c2577{\n' +
|
||||
' padding:10px;\n' +
|
||||
' }\n' +
|
||||
' .footer{\n' +
|
||||
' margin-top: 50px;\n' +
|
||||
' color:rgb(152, 156, 165);\n' +
|
||||
' text-align:center;\n' +
|
||||
' font-size:11px;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' }\n' +
|
||||
' .quote {\n' +
|
||||
' font-style: italic;\n' +
|
||||
' }\n' +
|
||||
' .list-item{\n' +
|
||||
' height:auto;\n' +
|
||||
' width:100%;\n' +
|
||||
' margin: 0 auto 10px auto;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' }\n' +
|
||||
' .list-item-cell{\n' +
|
||||
' background-color:rgb(255, 255, 255);\n' +
|
||||
' border-radius: 3px;\n' +
|
||||
' overflow: hidden;\n' +
|
||||
' padding: 0;\n' +
|
||||
' }\n' +
|
||||
' .list-cell-left{\n' +
|
||||
' width:30%;\n' +
|
||||
' padding: 0;\n' +
|
||||
' }\n' +
|
||||
' .list-cell-right{\n' +
|
||||
' width:70%;\n' +
|
||||
' color:rgb(111, 119, 125);\n' +
|
||||
' font-size:13px;\n' +
|
||||
' line-height:20px;\n' +
|
||||
' padding: 10px 20px 0px 20px;\n' +
|
||||
' }\n' +
|
||||
' .list-item-content{\n' +
|
||||
' border-collapse: collapse;\n' +
|
||||
' margin: 0 auto;\n' +
|
||||
' padding: 5px;\n' +
|
||||
' height:150px;\n' +
|
||||
' width:100%;\n' +
|
||||
' }\n' +
|
||||
' .list-item-image{\n' +
|
||||
' color:rgb(217, 131, 166);\n' +
|
||||
' font-size:45px;\n' +
|
||||
' width: 100%;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-image{\n' +
|
||||
' line-height:150px;\n' +
|
||||
' font-size:50px;\n' +
|
||||
' color:rgb(120, 197, 214);\n' +
|
||||
' margin-bottom:15px;\n' +
|
||||
' width:100%;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-row {\n' +
|
||||
' margin: 0 auto 10px;\n' +
|
||||
' padding: 5px 0;\n' +
|
||||
' width: 100%;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-card {\n' +
|
||||
' width:100%;\n' +
|
||||
' padding: 5px 0;\n' +
|
||||
' margin-bottom: 10px;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-card-cell{\n' +
|
||||
' background-color:rgb(255, 255, 255);\n' +
|
||||
' overflow: hidden;\n' +
|
||||
' border-radius: 3px;\n' +
|
||||
' text-align:center;\n' +
|
||||
' padding: 0;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-card-content{\n' +
|
||||
' font-size:13px;\n' +
|
||||
' color:rgb(111, 119, 125);\n' +
|
||||
' padding: 0 10px 20px 10px;\n' +
|
||||
' width:100%;\n' +
|
||||
' line-height:20px;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-cell2-l{\n' +
|
||||
' vertical-align:top;\n' +
|
||||
' padding-right:10px;\n' +
|
||||
' width:50%;\n' +
|
||||
' }\n' +
|
||||
' .grid-item-cell2-r{\n' +
|
||||
' vertical-align:top;\n' +
|
||||
' padding-left:10px;\n' +
|
||||
' width:50%;\n' +
|
||||
' }';
|
||||
|
||||
config.plugins.push('gjs-preset-newsletter');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
config.components = props.initialSource ? base(props.initialSource, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultSource;
|
||||
config.style = props.initialStyle ? base(props.initialStyle, trustedUrlBase, sandboxUrlBase, publicUrlBase) : defaultStyle;
|
||||
|
||||
config.plugins.push('mailtrain-remove-buttons');
|
||||
|
||||
this.editor = grapesjs.init(config);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -182,7 +632,6 @@ export class GrapesJSSandbox extends Component {
|
|||
}
|
||||
|
||||
|
||||
|
||||
export default function() {
|
||||
parentRPC.init();
|
||||
|
||||
|
|
6
client/src/lib/sandboxed-grapesjs-shared.js
Normal file
6
client/src/lib/sandboxed-grapesjs-shared.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
export const GrapesJSSourceType = {
|
||||
MJML: 'mjml',
|
||||
HTML: 'html'
|
||||
};
|
|
@ -10,6 +10,7 @@ import styles
|
|||
import {UntrustedContentHost} from './untrusted';
|
||||
import {Icon} from "./bootstrap-components";
|
||||
import {getTrustedUrl} from "./urls";
|
||||
import {GrapesJSSourceType} from "./sandboxed-grapesjs-shared";
|
||||
|
||||
@translate(null, { withRef: true })
|
||||
export class GrapesJSHost extends Component {
|
||||
|
@ -26,6 +27,7 @@ export class GrapesJSHost extends Component {
|
|||
entity: PropTypes.object,
|
||||
initialSource: PropTypes.string,
|
||||
initialStyle: PropTypes.string,
|
||||
sourceType: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
onFullscreenAsync: PropTypes.func
|
||||
}
|
||||
|
@ -49,7 +51,8 @@ export class GrapesJSHost extends Component {
|
|||
entityTypeId: this.props.entityTypeId,
|
||||
entityId: this.props.entity.id,
|
||||
initialSource: this.props.initialSource,
|
||||
initialStyle: this.props.initialStyle
|
||||
initialStyle: this.props.initialStyle,
|
||||
sourceType: this.props.sourceType
|
||||
};
|
||||
|
||||
const tokenData = {
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
import {Trans} from "react-i18next";
|
||||
|
||||
import styles from "../lib/styles.scss";
|
||||
import {GrapesJSSourceType} from "../lib/sandboxed-grapesjs-shared";
|
||||
|
||||
export const ResourceType = {
|
||||
TEMPLATE: 'template',
|
||||
|
@ -175,9 +176,26 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
|||
validate: state => {}
|
||||
};
|
||||
|
||||
|
||||
const grapesJSSourceTypes = [
|
||||
{key: GrapesJSSourceType.MJML, label: t('MJML')},
|
||||
{key: GrapesJSSourceType.HTML, label: t('HTML')}
|
||||
];
|
||||
|
||||
const grapesJSSourceTypeLabels = {};
|
||||
for ({key, label} of grapesJSSourceTypes) {
|
||||
grapesJSSourceTypeLabels[key] = label;
|
||||
}
|
||||
|
||||
templateTypes.grapesjs = {
|
||||
typeName: t('GrapeJS'),
|
||||
getTypeForm: (owner, isEdit) => null,
|
||||
getTypeForm: (owner, isEdit) => {
|
||||
if (isEdit) {
|
||||
return <StaticField id={prefix + 'grapesJSSourceType'} className={styles.formDisabled} label={t('Type')}>{grapesJSSourceTypeLabels[(owner.getFormValue(prefix + 'grapesJSSourceType'))]}</StaticField>;
|
||||
} else {
|
||||
return <Dropdown id={prefix + 'grapesJSSourceType'} label={t('Type')} options={grapesJSSourceTypes}/>;
|
||||
}
|
||||
},
|
||||
getHTMLEditor: owner =>
|
||||
<AlignedRow label={t('Template content (HTML)')}>
|
||||
<GrapesJSHost
|
||||
|
@ -186,6 +204,7 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
|||
entityTypeId={entityTypeId}
|
||||
initialSource={owner.getFormValue(prefix + 'grapesJSData').source}
|
||||
initialStyle={owner.getFormValue(prefix + 'grapesJSData').style}
|
||||
sourceType={owner.getFormValue(prefix + 'grapesJSSourceType')}
|
||||
title={t('GrapesJS Template Designer')}
|
||||
onFullscreenAsync={::owner.setElementInFullscreen}
|
||||
/>
|
||||
|
@ -199,9 +218,11 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
|||
});
|
||||
},
|
||||
initData: () => ({
|
||||
[prefix + 'grapesJSSourceType']: GrapesJSSourceType.MJML,
|
||||
[prefix + 'grapesJSData']: {}
|
||||
}),
|
||||
afterLoad: data => {
|
||||
data[prefix + 'grapesJSSourceType'] = data[prefix + 'data'].sourceType;
|
||||
data[prefix + 'grapesJSData'] = {
|
||||
source: data[prefix + 'data'].source,
|
||||
style: data[prefix + 'data'].style
|
||||
|
@ -209,6 +230,7 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
|||
},
|
||||
beforeSave: data => {
|
||||
data[prefix + 'data'] = {
|
||||
sourceType: data[prefix + 'grapesJSSourceType'],
|
||||
source: data[prefix + 'grapesJSData'].source,
|
||||
style: data[prefix + 'grapesJSData'].style
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue