More elements for mosaico mjml support. Added "MJML Sample" wizard to mosaico templates.
This commit is contained in:
parent
ec0f288d81
commit
94a2cdf89e
7 changed files with 415 additions and 12 deletions
|
@ -27,7 +27,7 @@ import {
|
|||
} from '../../lib/namespace';
|
||||
import {DeleteModalDialog} from "../../lib/modals";
|
||||
|
||||
import {getVersafix} from "../../../../shared/mosaico-templates";
|
||||
import {getVersafix, getMJMLSample} from "../../../../shared/mosaico-templates";
|
||||
import {
|
||||
getTemplateTypes,
|
||||
getTemplateTypesOrder
|
||||
|
@ -87,6 +87,15 @@ export default class CUD extends Component {
|
|||
html: getVersafix()
|
||||
});
|
||||
|
||||
} else if (wizard === 'mjml-sample') {
|
||||
this.populateFormValues({
|
||||
name: '',
|
||||
description: '',
|
||||
namespace: mailtrainConfig.user.namespace,
|
||||
type: 'mjml',
|
||||
mjml: getMJMLSample()
|
||||
});
|
||||
|
||||
} else {
|
||||
this.populateFormValues({
|
||||
name: '',
|
||||
|
@ -183,7 +192,7 @@ export default class CUD extends Component {
|
|||
<Form stateOwner={this} onSubmitAsync={::this.submitHandler}>
|
||||
<InputField id="name" label={t('name')}/>
|
||||
<TextArea id="description" label={t('description')}/>
|
||||
{isEdit ?
|
||||
{isEdit || this.props.wizard ?
|
||||
<StaticField id="type" className={styles.formDisabled} label={t('type')}>
|
||||
{typeKey && this.templateTypes[typeKey].typeName}
|
||||
</StaticField>
|
||||
|
|
|
@ -123,6 +123,7 @@ export default class List extends Component {
|
|||
<ButtonDropdown buttonClassName="btn-primary" menuClassName="dropdown-menu-right" label={t('createMosaicoTemplate')}>
|
||||
<DropdownLink to="/templates/mosaico/create">{t('blank')}</DropdownLink>
|
||||
<DropdownLink to="/templates/mosaico/create/versafix">{t('versafixOne')}</DropdownLink>
|
||||
<DropdownLink to="/templates/mosaico/create/mjml-sample">{t('MJML Sample')}</DropdownLink>
|
||||
</ButtonDropdown>
|
||||
</Toolbar>
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ export function getTemplateTypes(t) {
|
|||
owner.setFormStatusMessage('success', t('MJML is valid.'));
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
owner.setFormStatusMessage('danger', t('Invalid MJML.'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ function handleMosaicoEditable(block, src) {
|
|||
|
||||
|
||||
for (const attrMatch of attrsMatches) {
|
||||
if (attrMatch[1] === 'mosaico-editable') {
|
||||
if (attrMatch[1] === 'mj-mosaico-editable') {
|
||||
const propertyId = attrMatch[2];
|
||||
block.addMosaicoProperty(propertyId);
|
||||
|
||||
|
@ -80,13 +80,24 @@ class MjMosaicoProperty extends HeadComponent {
|
|||
static allowedAttributes = {
|
||||
'property-id': 'string',
|
||||
label: 'string',
|
||||
widget: 'string',
|
||||
type: 'enum(image,link)'
|
||||
}
|
||||
|
||||
handler() {
|
||||
const { add } = this.context;
|
||||
|
||||
add('style', ` @supports -ko-blockdefs { ${this.getAttribute('property-id')} { label: ${this.getAttribute('label')}; widget: ${this.getAttribute('widget')} } }`);
|
||||
let properties = null;
|
||||
|
||||
const type = this.getAttribute('type');
|
||||
if (type === 'image') {
|
||||
properties = 'src url alt';
|
||||
} else if (type === 'link') {
|
||||
properties = 'text url';
|
||||
}
|
||||
|
||||
const propertiesStr = properties ? ` properties: ${properties}` : '';
|
||||
|
||||
add('style', ` @supports -ko-blockdefs { ${this.getAttribute('property-id')} { label: ${this.getAttribute('label')};${propertiesStr} } }`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,7 +258,10 @@ class MjMosaicoImage extends BodyComponent {
|
|||
const propertyId = this.getAttribute('property-id');
|
||||
this.propertyId = propertyId || `image_${getId()}`;
|
||||
|
||||
getParent().addMosaicoProperty(this.propertyId);
|
||||
const parentBlock = getParent();
|
||||
if (parentBlock) {
|
||||
parentBlock.addMosaicoProperty(this.propertyId);
|
||||
}
|
||||
}
|
||||
|
||||
static tagOmission = true
|
||||
|
@ -425,6 +439,154 @@ class MjMosaicoImage extends BodyComponent {
|
|||
}
|
||||
|
||||
|
||||
// Adapted from https://github.com/mjmlio/mjml/blob/master/packages/mjml-button/src/index.js
|
||||
class MjMosaicoButton extends BodyComponent {
|
||||
constructor(initialDatas = {}) {
|
||||
super(initialDatas);
|
||||
|
||||
const propertyId = this.getAttribute('property-id');
|
||||
this.propertyId = propertyId || `button_${getId()}`;
|
||||
|
||||
const parentBlock = getParent();
|
||||
if (parentBlock) {
|
||||
parentBlock.addMosaicoProperty(this.propertyId);
|
||||
}
|
||||
}
|
||||
|
||||
static endingTag = true
|
||||
|
||||
static allowedAttributes = {
|
||||
'property-id': 'string',
|
||||
align: 'enum(left,center,right)',
|
||||
'background-color': 'color',
|
||||
'border-bottom': 'string',
|
||||
'border-left': 'string',
|
||||
'border-radius': 'string',
|
||||
'border-right': 'string',
|
||||
'border-top': 'string',
|
||||
border: 'string',
|
||||
color: 'color',
|
||||
'container-background-color': 'color',
|
||||
'font-family': 'string',
|
||||
'font-size': 'unit(px)',
|
||||
'font-style': 'string',
|
||||
'font-weight': 'string',
|
||||
height: 'unit(px,%)',
|
||||
name: 'string',
|
||||
'inner-padding': 'unit(px,%)',
|
||||
'line-height': 'unit(px,%)',
|
||||
'padding-bottom': 'unit(px,%)',
|
||||
'padding-left': 'unit(px,%)',
|
||||
'padding-right': 'unit(px,%)',
|
||||
'padding-top': 'unit(px,%)',
|
||||
padding: 'unit(px,%){1,4}',
|
||||
rel: 'string',
|
||||
target: 'string',
|
||||
'text-decoration': 'string',
|
||||
'text-transform': 'string',
|
||||
'vertical-align': 'enum(top,bottom,middle)',
|
||||
'text-align': 'enum(left,right,center)',
|
||||
width: 'unit(px,%)',
|
||||
}
|
||||
|
||||
static defaultAttributes = {
|
||||
align: 'center',
|
||||
'background-color': '#414141',
|
||||
border: 'none',
|
||||
'border-radius': '3px',
|
||||
color: '#ffffff',
|
||||
'font-family': 'Ubuntu, Helvetica, Arial, sans-serif',
|
||||
'font-size': '13px',
|
||||
'font-weight': 'normal',
|
||||
'inner-padding': '10px 25px',
|
||||
'line-height': '120%',
|
||||
padding: '10px 25px',
|
||||
target: '_blank',
|
||||
'text-decoration': 'none',
|
||||
'text-transform': 'none',
|
||||
'vertical-align': 'middle',
|
||||
}
|
||||
|
||||
getStyles() {
|
||||
return {
|
||||
table: {
|
||||
'border-collapse': 'separate',
|
||||
width: this.getAttribute('width'),
|
||||
'line-height': '100%',
|
||||
},
|
||||
td: {
|
||||
border: this.getAttribute('border'),
|
||||
'border-bottom': this.getAttribute('border-bottom'),
|
||||
'border-left': this.getAttribute('border-left'),
|
||||
'border-radius': this.getAttribute('border-radius'),
|
||||
'border-right': this.getAttribute('border-right'),
|
||||
'border-top': this.getAttribute('border-top'),
|
||||
cursor: 'auto',
|
||||
'font-style': this.getAttribute('font-style'),
|
||||
height: this.getAttribute('height'),
|
||||
padding: this.getAttribute('inner-padding'),
|
||||
'text-align': this.getAttribute('text-align'),
|
||||
background: this.getAttribute('background-color'),
|
||||
},
|
||||
content: {
|
||||
background: this.getAttribute('background-color'),
|
||||
color: this.getAttribute('color'),
|
||||
'font-family': this.getAttribute('font-family'),
|
||||
'font-size': this.getAttribute('font-size'),
|
||||
'font-style': this.getAttribute('font-style'),
|
||||
'font-weight': this.getAttribute('font-weight'),
|
||||
'line-height': this.getAttribute('line-height'),
|
||||
Margin: '0',
|
||||
'text-decoration': this.getAttribute('text-decoration'),
|
||||
'text-transform': this.getAttribute('text-transform'),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return `
|
||||
<table
|
||||
${this.htmlAttributes({
|
||||
border: '0',
|
||||
cellpadding: '0',
|
||||
cellspacing: '0',
|
||||
role: 'presentation',
|
||||
style: 'table',
|
||||
})}
|
||||
>
|
||||
<tr>
|
||||
<td
|
||||
${this.htmlAttributes({
|
||||
align: 'center',
|
||||
bgcolor:
|
||||
this.getAttribute('background-color') === 'none'
|
||||
? undefined
|
||||
: this.getAttribute('background-color'),
|
||||
role: 'presentation',
|
||||
style: 'td',
|
||||
valign: this.getAttribute('vertical-align'),
|
||||
})}
|
||||
>
|
||||
<a
|
||||
${this.htmlAttributes({
|
||||
rel: this.getAttribute('rel'),
|
||||
name: this.getAttribute('name'),
|
||||
style: 'content',
|
||||
target: this.getAttribute('target'),
|
||||
'data-ko-editable': this.getAttribute('property-id') + '.text',
|
||||
'data-ko-link': this.getAttribute('property-id') + '.url'
|
||||
})}
|
||||
>
|
||||
${this.getContent()}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const mjmlInstance = new MJML();
|
||||
|
||||
|
@ -432,15 +594,21 @@ mjmlInstance.registerComponent(MjMosaicoContainer);
|
|||
mjmlInstance.registerComponent(MjMosaicoBlock);
|
||||
mjmlInstance.registerComponent(MjMosaicoInnerBlock);
|
||||
mjmlInstance.registerComponent(MjMosaicoImage);
|
||||
mjmlInstance.registerComponent(MjMosaicoButton);
|
||||
mjmlInstance.registerComponent(MjMosaicoProperty);
|
||||
|
||||
mjmlInstance.registerDependencies({
|
||||
'mj-mosaico-container': ['mj-mosaico-block', 'mj-mosaico-inner-block'],
|
||||
'mj-body': ['mj-mosaico-container', 'mj-mosaico-block'],
|
||||
'mj-section': ['mj-mosaico-container', 'mj-mosaico-block'],
|
||||
'mj-column': ['mj-mosaico-container', 'mj-mosaico-inner-block', 'mj-mosaico-image'],
|
||||
'mj-column': ['mj-mosaico-container', 'mj-mosaico-inner-block', 'mj-mosaico-image', 'mj-mosaico-button'],
|
||||
'mj-mosaico-block': ['mj-section', 'mj-column'],
|
||||
'mj-mosaico-inner-block': ['mj-mosaico-image', 'mj-divider', 'mj-text', 'mj-image', 'mj-table']
|
||||
'mj-mosaico-inner-block': [
|
||||
'mj-mosaico-image', 'mj-mosaico-button',
|
||||
'mj-accordion', 'mj-button', 'mj-carousel', 'mj-divider', 'mj-html', 'mj-image', 'mj-invoice', 'mj-list',
|
||||
'mj-location', 'mj-raw', 'mj-social', 'mj-spacer', 'mj-table', 'mj-text', 'mj-navbar'
|
||||
],
|
||||
'mj-head': ['mj-mosaico-property']
|
||||
});
|
||||
|
||||
mjmlInstance.addToHeader(`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue