Save button for template editors
This commit is contained in:
parent
3bb235a585
commit
bd20072455
8 changed files with 73 additions and 17 deletions
|
@ -63,15 +63,17 @@ export default class CustomContent extends Component {
|
||||||
entity: PropTypes.object
|
entity: PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
loadFromEntityMutator(data) {
|
||||||
this.getFormValuesFromEntity(this.props.entity, data => {
|
data.data_sourceCustom_type = data.data.sourceCustom.type;
|
||||||
data.data_sourceCustom_type = data.data.sourceCustom.type;
|
data.data_sourceCustom_data = data.data.sourceCustom.data;
|
||||||
data.data_sourceCustom_data = data.data.sourceCustom.data;
|
data.data_sourceCustom_html = data.data.sourceCustom.html;
|
||||||
data.data_sourceCustom_html = data.data.sourceCustom.html;
|
data.data_sourceCustom_text = data.data.sourceCustom.text;
|
||||||
data.data_sourceCustom_text = data.data.sourceCustom.text;
|
|
||||||
|
|
||||||
this.templateTypes[data.data.sourceCustom.type].afterLoad(data);
|
this.templateTypes[data.data.sourceCustom.type].afterLoad(data);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getFormValuesFromEntity(this.props.entity, data => this.loadFromEntityMutator(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
localValidateFormValues(state) {
|
localValidateFormValues(state) {
|
||||||
|
@ -84,7 +86,15 @@ export default class CustomContent extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async save() {
|
||||||
|
await this.doSave(true);
|
||||||
|
}
|
||||||
|
|
||||||
async submitHandler() {
|
async submitHandler() {
|
||||||
|
await this.doSave(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async doSave(stayOnPage) {
|
||||||
const t = this.props.t;
|
const t = this.props.t;
|
||||||
|
|
||||||
const customTemplateTypeKey = this.getFormValue('data_sourceCustom_type');
|
const customTemplateTypeKey = this.getFormValue('data_sourceCustom_type');
|
||||||
|
@ -115,10 +125,14 @@ export default class CustomContent extends Component {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (submitResponse) {
|
if (submitResponse) {
|
||||||
if (this.props.entity) {
|
if (stayOnPage) {
|
||||||
this.navigateToWithFlashMessage('/campaigns', 'success', t('campaignSaved'));
|
await this.getFormValuesFromURL(`rest/campaigns-content/${this.props.entity.id}`, data => this.loadFromEntityMutator(data));
|
||||||
|
this.enableForm();
|
||||||
|
this.clearFormStatusMessage();
|
||||||
|
this.setFlashMessage('success', t('campaignSaved'));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.navigateToWithFlashMessage(`/campaigns/${submitResponse}/edit`, 'success', t('campaignSaved'));
|
this.navigateToWithFlashMessage('/campaigns', 'success', t('campaignSaved'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.enableForm();
|
this.enableForm();
|
||||||
|
|
|
@ -31,6 +31,8 @@ export class CKEditorHost extends Component {
|
||||||
entity: PropTypes.object,
|
entity: PropTypes.object,
|
||||||
initialSource: PropTypes.string,
|
initialSource: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
onSave: PropTypes.func,
|
||||||
|
canSave: PropTypes.bool,
|
||||||
onTestSend: PropTypes.func,
|
onTestSend: PropTypes.func,
|
||||||
onFullscreenAsync: PropTypes.func
|
onFullscreenAsync: PropTypes.func
|
||||||
}
|
}
|
||||||
|
@ -91,6 +93,7 @@ export class CKEditorHost extends Component {
|
||||||
<div className={styles.title}>{this.props.title}</div>
|
<div className={styles.title}>{this.props.title}</div>
|
||||||
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="fullscreen"/></a>
|
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="fullscreen"/></a>
|
||||||
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a>
|
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a>
|
||||||
|
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>}
|
||||||
</div>
|
</div>
|
||||||
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="ckeditor/editor" tokenMethod="ckeditor" tokenParams={editorData}/>
|
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="ckeditor/editor" tokenMethod="ckeditor" tokenParams={editorData}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -91,6 +91,9 @@ class CodeEditorSandbox extends Component {
|
||||||
|
|
||||||
this.refreshHandler = ::this.refresh;
|
this.refreshHandler = ::this.refresh;
|
||||||
this.refreshTimeoutId = null;
|
this.refreshTimeoutId = null;
|
||||||
|
|
||||||
|
this.onMessageFromPreviewHandler = ::this.onMessageFromPreview;
|
||||||
|
this.previewScroll = {x: 0, y: 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -128,6 +131,8 @@ class CodeEditorSandbox extends Component {
|
||||||
parentRPC.setMethodHandler('exportState', ::this.exportState);
|
parentRPC.setMethodHandler('exportState', ::this.exportState);
|
||||||
parentRPC.setMethodHandler('setPreview', ::this.setPreview);
|
parentRPC.setMethodHandler('setPreview', ::this.setPreview);
|
||||||
parentRPC.setMethodHandler('setWrap', ::this.setWrap);
|
parentRPC.setMethodHandler('setWrap', ::this.setWrap);
|
||||||
|
|
||||||
|
window.addEventListener('message', this.onMessageFromPreviewHandler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
@ -156,6 +161,12 @@ class CodeEditorSandbox extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMessageFromPreview(evt) {
|
||||||
|
if (evt.data.type === 'scroll') {
|
||||||
|
this.previewScroll = evt.data.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.refreshTimeoutId = null;
|
this.refreshTimeoutId = null;
|
||||||
|
|
||||||
|
@ -165,6 +176,16 @@ class CodeEditorSandbox extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const previewScript =
|
||||||
|
'(function() {\n' +
|
||||||
|
' function reportScroll() { window.parent.postMessage({type: \'scroll\', data: {x: window.scrollX, y: window.scrollY}}, \'*\'); }\n' +
|
||||||
|
' reportScroll();\n' +
|
||||||
|
' window.addEventListener(\'scroll\', reportScroll);\n' +
|
||||||
|
' window.addEventListener(\'load\', function(evt) { window.scrollTo(' + this.previewScroll.x + ',' + this.previewScroll.y +'); });\n' +
|
||||||
|
'})();\n';
|
||||||
|
|
||||||
|
const previewContents = this.state.previewContents.replace(/<\s*head\s*>/i, `<head><script>${previewScript}</script>`);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.sandbox}>
|
<div className={styles.sandbox}>
|
||||||
<div className={this.state.preview ? styles.aceEditorWithPreview : styles.aceEditorWithoutPreview}>
|
<div className={this.state.preview ? styles.aceEditorWithPreview : styles.aceEditorWithoutPreview}>
|
||||||
|
@ -185,7 +206,7 @@ class CodeEditorSandbox extends Component {
|
||||||
{
|
{
|
||||||
this.state.preview &&
|
this.state.preview &&
|
||||||
<div className={styles.preview}>
|
<div className={styles.preview}>
|
||||||
<iframe ref={node => this.previewNode = node} src={"data:text/html;charset=utf-8," + escape(this.state.previewContents)}></iframe>
|
<iframe ref={node => this.previewNode = node} src={"data:text/html;charset=utf-8," + escape(previewContents)}></iframe>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,8 +29,9 @@ export class CodeEditorHost extends Component {
|
||||||
initialSource: PropTypes.string,
|
initialSource: PropTypes.string,
|
||||||
sourceType: PropTypes.string,
|
sourceType: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
onTestSend: PropTypes.func,
|
|
||||||
onSave: PropTypes.func,
|
onSave: PropTypes.func,
|
||||||
|
canSave: PropTypes.bool,
|
||||||
|
onTestSend: PropTypes.func,
|
||||||
onFullscreenAsync: PropTypes.func
|
onFullscreenAsync: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ export class GrapesJSHost extends Component {
|
||||||
initialStyle: PropTypes.string,
|
initialStyle: PropTypes.string,
|
||||||
sourceType: PropTypes.string,
|
sourceType: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
onSave: PropTypes.func,
|
||||||
|
canSave: PropTypes.bool,
|
||||||
onTestSend: PropTypes.func,
|
onTestSend: PropTypes.func,
|
||||||
onFullscreenAsync: PropTypes.func
|
onFullscreenAsync: PropTypes.func
|
||||||
}
|
}
|
||||||
|
@ -67,6 +69,7 @@ export class GrapesJSHost extends Component {
|
||||||
<div className={styles.title}>{this.props.title}</div>
|
<div className={styles.title}>{this.props.title}</div>
|
||||||
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="fullscreen"/></a>
|
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="fullscreen"/></a>
|
||||||
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a>
|
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a>
|
||||||
|
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>}
|
||||||
</div>
|
</div>
|
||||||
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="grapesjs/editor" tokenMethod="grapesjs" tokenParams={tokenData}/>
|
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="grapesjs/editor" tokenMethod="grapesjs" tokenParams={tokenData}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,6 +26,8 @@ export class MosaicoHost extends Component {
|
||||||
entityTypeId: PropTypes.string,
|
entityTypeId: PropTypes.string,
|
||||||
entity: PropTypes.object,
|
entity: PropTypes.object,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
onSave: PropTypes.func,
|
||||||
|
canSave: PropTypes.bool,
|
||||||
onTestSend: PropTypes.func,
|
onTestSend: PropTypes.func,
|
||||||
onFullscreenAsync: PropTypes.func,
|
onFullscreenAsync: PropTypes.func,
|
||||||
templateId: PropTypes.number,
|
templateId: PropTypes.number,
|
||||||
|
@ -70,6 +72,7 @@ export class MosaicoHost extends Component {
|
||||||
<div className={styles.title}>{this.props.title}</div>
|
<div className={styles.title}>{this.props.title}</div>
|
||||||
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="fullscreen"/></a>
|
<a className={styles.btn} onClick={::this.toggleFullscreenAsync}><Icon icon="fullscreen"/></a>
|
||||||
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a>
|
<a className={styles.btn} onClick={this.props.onTestSend}><Icon icon="send"/></a>
|
||||||
|
{this.props.canSave ? <a className={styles.btn} onClick={this.props.onSave}><Icon icon="floppy-disk"/></a> : <span className={styles.btnDisabled}><Icon icon="floppy-disk"/></span>}
|
||||||
</div>
|
</div>
|
||||||
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="mosaico/editor" tokenMethod="mosaico" tokenParams={tokenData}/>
|
<UntrustedContentHost ref={node => this.contentNode = node} className={styles.host} singleToken={true} contentProps={editorData} contentSrc="mosaico/editor" tokenMethod="mosaico" tokenParams={tokenData}/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -52,7 +52,7 @@ export default class CUD extends Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
showMergeTagReference: false,
|
showMergeTagReference: false,
|
||||||
elementInFullscreen: false,
|
elementInFullscreen: false,
|
||||||
showTestSendModal: false
|
showTestSendModal: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.initForm({
|
this.initForm({
|
||||||
|
@ -76,11 +76,13 @@ export default class CUD extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadFromEntityMutator(data) {
|
||||||
|
this.templateTypes[data.type].afterLoad(data);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.props.entity) {
|
if (this.props.entity) {
|
||||||
this.getFormValuesFromEntity(this.props.entity, data => {
|
this.getFormValuesFromEntity(this.props.entity, data => this.loadFromEntityMutator(data));
|
||||||
this.templateTypes[data.type].afterLoad(data);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
this.populateFormValues({
|
this.populateFormValues({
|
||||||
name: '',
|
name: '',
|
||||||
|
@ -146,6 +148,7 @@ export default class CUD extends Component {
|
||||||
|
|
||||||
if (submitResponse) {
|
if (submitResponse) {
|
||||||
if (stayOnPage) {
|
if (stayOnPage) {
|
||||||
|
await this.getFormValuesFromURL(`rest/templates/${this.props.entity.id}`, data => this.loadFromEntityMutator(data));
|
||||||
this.enableForm();
|
this.enableForm();
|
||||||
this.clearFormStatusMessage();
|
this.clearFormStatusMessage();
|
||||||
this.setFlashMessage('success', t('templateSaved'));
|
this.setFlashMessage('success', t('templateSaved'));
|
||||||
|
|
|
@ -121,6 +121,8 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
||||||
templateId={owner.getFormValue(prefix + 'mosaicoTemplate')}
|
templateId={owner.getFormValue(prefix + 'mosaicoTemplate')}
|
||||||
entityTypeId={entityTypeId}
|
entityTypeId={entityTypeId}
|
||||||
title={t('mosaicoTemplateDesigner')}
|
title={t('mosaicoTemplateDesigner')}
|
||||||
|
onSave={::owner.save}
|
||||||
|
canSave={owner.isFormWithoutErrors()}
|
||||||
onTestSend={::owner.showTestSendModal}
|
onTestSend={::owner.showTestSendModal}
|
||||||
onFullscreenAsync={::owner.setElementInFullscreen}
|
onFullscreenAsync={::owner.setElementInFullscreen}
|
||||||
/>
|
/>
|
||||||
|
@ -194,6 +196,8 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
||||||
templatePath={getSandboxUrl(`static/mosaico/templates/${owner.getFormValue(prefix + 'mosaicoFsTemplate')}/index.html`)}
|
templatePath={getSandboxUrl(`static/mosaico/templates/${owner.getFormValue(prefix + 'mosaicoFsTemplate')}/index.html`)}
|
||||||
entityTypeId={entityTypeId}
|
entityTypeId={entityTypeId}
|
||||||
title={t('mosaicoTemplateDesigner')}
|
title={t('mosaicoTemplateDesigner')}
|
||||||
|
onSave={::owner.save}
|
||||||
|
canSave={owner.isFormWithoutErrors()}
|
||||||
onTestSend={::owner.showTestSendModal}
|
onTestSend={::owner.showTestSendModal}
|
||||||
onFullscreenAsync={::owner.setElementInFullscreen}
|
onFullscreenAsync={::owner.setElementInFullscreen}
|
||||||
/>
|
/>
|
||||||
|
@ -270,6 +274,8 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
||||||
initialStyle={owner.getFormValue(prefix + 'grapesJSData').style}
|
initialStyle={owner.getFormValue(prefix + 'grapesJSData').style}
|
||||||
sourceType={owner.getFormValue(prefix + 'grapesJSSourceType')}
|
sourceType={owner.getFormValue(prefix + 'grapesJSSourceType')}
|
||||||
title={t('grapesJsTemplateDesigner')}
|
title={t('grapesJsTemplateDesigner')}
|
||||||
|
onSave={::owner.save}
|
||||||
|
canSave={owner.isFormWithoutErrors()}
|
||||||
onTestSend={::owner.showTestSendModal}
|
onTestSend={::owner.showTestSendModal}
|
||||||
onFullscreenAsync={::owner.setElementInFullscreen}
|
onFullscreenAsync={::owner.setElementInFullscreen}
|
||||||
/>
|
/>
|
||||||
|
@ -322,6 +328,8 @@ export function getTemplateTypes(t, prefix = '', entityTypeId = ResourceType.TEM
|
||||||
initialSource={owner.getFormValue(prefix + 'ckeditor4Data').source}
|
initialSource={owner.getFormValue(prefix + 'ckeditor4Data').source}
|
||||||
entityTypeId={entityTypeId}
|
entityTypeId={entityTypeId}
|
||||||
title={t('ckEditor4TemplateDesigner')}
|
title={t('ckEditor4TemplateDesigner')}
|
||||||
|
onSave={::owner.save}
|
||||||
|
canSave={owner.isFormWithoutErrors()}
|
||||||
onTestSend={::owner.showTestSendModal}
|
onTestSend={::owner.showTestSendModal}
|
||||||
onFullscreenAsync={::owner.setElementInFullscreen}
|
onFullscreenAsync={::owner.setElementInFullscreen}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Reference in a new issue