From b223a38b73058fafbd3b4c19e6963ab50eefb6d3 Mon Sep 17 00:00:00 2001 From: Juan Tejada Date: Tue, 16 Aug 2016 13:21:30 -0700 Subject: [PATCH] fix(mail-merge/preview): Don't unmount components when toggling preview Summary: See edgehill revision: https://phab.nylas.com/D3160 - CustomContenteditableComponents.get now takes a single component to register as an overlaid component, and this component will be passed a prop `{isPreview: true}` when it is meant to be rendered as a preview. Update scheduler and mail-merge to use this new api. - This prevents the mail merge state from being incorrectly updated when we toggled preview mode -- previously, it believed that the tokens had been unmounted when toggling preview, so they were incorrectly removed from the mail merge state. - Additionally, makes sure that tokens are correctly added to the mail merge state whenever a token is rendered via componentDidMount -- previously, we only added the token to state when a token was dropped on the contenteditable, however, a token might be pasted or an anchor node might be added by any other means, in which case we want the mail merge state to reflect that. (Adds docs about this) Test Plan: Manual Reviewers: jackie, evan Reviewed By: jackie, evan Differential Revision: https://phab.nylas.com/D3161 --- .../composer/stylesheets/composer.less | 2 +- .../custom-contenteditable-components.es6 | 8 ++-- .../overlaid-components.jsx | 39 +++++++++++-------- .../overlaid-composer-extension.es6 | 12 +++--- src/pro | 2 +- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/internal_packages/composer/stylesheets/composer.less b/internal_packages/composer/stylesheets/composer.less index 799956027..59af0566e 100644 --- a/internal_packages/composer/stylesheets/composer.less +++ b/internal_packages/composer/stylesheets/composer.less @@ -483,7 +483,7 @@ body.platform-win32 { img.n1-overlaid-component-anchor-container { border: 0; } -.toggle-serialized { +.toggle-preview { position: absolute; top: -17px; right: 0; diff --git a/src/components/overlaid-components/custom-contenteditable-components.es6 b/src/components/overlaid-components/custom-contenteditable-components.es6 index 4c5a2c380..945a1626a 100644 --- a/src/components/overlaid-components/custom-contenteditable-components.es6 +++ b/src/components/overlaid-components/custom-contenteditable-components.es6 @@ -7,11 +7,11 @@ class CustomContenteditableComponents { return this._components[componentKey] } - register(componentKey, components = {}) { - if (!components.main) { - throw new Error("Must register a `main` component and optionally a `serialized` component.") + register(componentKey, component) { + if (!component) { + throw new Error("Must register a component.") } - this._components[componentKey] = components + this._components[componentKey] = component } unregister(componentKey) { diff --git a/src/components/overlaid-components/overlaid-components.jsx b/src/components/overlaid-components/overlaid-components.jsx index cec9ceb89..4b310b4ce 100644 --- a/src/components/overlaid-components/overlaid-components.jsx +++ b/src/components/overlaid-components/overlaid-components.jsx @@ -45,7 +45,9 @@ export default class OverlaidComponents extends React.Component { return { anchorId: overlayId, anchorTag: - ``, + ``, } } @@ -53,7 +55,7 @@ export default class OverlaidComponents extends React.Component { super(props); this.state = { anchorRectIds: [], - serialized: false, + previewMode: false, } this._anchorData = {} this._overlayData = {} @@ -162,12 +164,20 @@ export default class OverlaidComponents extends React.Component { return updatedRegistry } - _renderSerializeToggle() { + _onTogglePreview = () => { + this.setState({previewMode: !this.state.previewMode}) + } + + _renderPreviewToggle() { let msg = "Preview as recipient"; - if (this.state.serialized) { + if (this.state.previewMode) { msg = "Return to editor" } - return { this.setState({serialized: !this.state.serialized}) }}>{msg} + return ( + + {msg} + + ) } _renderOverlaidComponents() { @@ -177,25 +187,22 @@ export default class OverlaidComponents extends React.Component { if (!data) { throw new Error("No mounted rect for #{id}") } const style = {left: data.left, top: data.top, position: 'absolute'} - const componentData = CustomContenteditableComponents.get(data.componentKey); + const component = CustomContenteditableComponents.get(data.componentKey); - if (!componentData) { + if (!component) { // It's possible that the plugin with that will register this // componentKey hasn't loaded yet. This is common in popout // composers where 3rd party plugins are loaded later. continue } - const component = this.state.serialized ? componentData.serialized : componentData.main; - - if (!component) { throw new Error(`No registered component for ${data.componentKey}`) } - - let props = JSON.parse(data.componentProps); - - props = Object.assign({}, this.props.exposedProps, props); + const props = Object.assign({}, + this.props.exposedProps, + JSON.parse(data.componentProps), + {isPreview: this.state.previewMode} + ); const el = React.createElement(component, props) - const wrap = ( 0) ? this._renderSerializeToggle() : false + const toggle = (els.length > 0) ? this._renderPreviewToggle() : false return (
{toggle} diff --git a/src/components/overlaid-components/overlaid-composer-extension.es6 b/src/components/overlaid-components/overlaid-composer-extension.es6 index 677a14d85..e32c3b8a2 100644 --- a/src/components/overlaid-components/overlaid-composer-extension.es6 +++ b/src/components/overlaid-components/overlaid-composer-extension.es6 @@ -49,18 +49,20 @@ export default class OverlaidComposerExtension extends ComposerExtension { const matcher = self.overlayMatches(self._anchorExtractRe(), outDraft.body) for (const match of matcher) { - const componentData = CustomContenteditableComponents.get(match.dataComponentKey); - if (!componentData || !componentData.serialized) { + const component = CustomContenteditableComponents.get(match.dataComponentKey); + if (!component) { continue } - const component = componentData.serialized - const props = Object.assign({draft}, match.dataComponentProps); + const props = Object.assign({draft, isPreview: true}, match.dataComponentProps); const el = React.createElement(component, props); let html = ReactDOMServer.renderToStaticMarkup(el); html = `${html}` - outBody = outBody.replace(OverlaidComposerExtension._anchorReplacerRe(match.dataOverlayId), html) + outBody = outBody.replace( + OverlaidComposerExtension._anchorReplacerRe(match.dataOverlayId), + html + ) } outDraft.body = outBody; diff --git a/src/pro b/src/pro index b58b059bd..33cacbd12 160000 --- a/src/pro +++ b/src/pro @@ -1 +1 @@ -Subproject commit b58b059bde6e81a70170ff03288200c55615c162 +Subproject commit 33cacbd129e3db61fa8f6c748af3428314413876