Skip to content

Commit

Permalink
feat: add preview modal (#59)
Browse files Browse the repository at this point in the history
- move preview button to post status slot
- slight refactoring
- handle campaign fetching in editor plugin
  • Loading branch information
adekbadek authored Apr 20, 2020
2 parents f36d8f3 + 6156243 commit 515f281
Show file tree
Hide file tree
Showing 8 changed files with 511 additions and 108 deletions.
405 changes: 405 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"@wordpress/plugins": "^2.13.0",
"@wordpress/url": "^2.13.0",
"lodash": "^4.17.15",
"newspack-components": "^1.1.0",
"webpack": "^4.42.1"
},
"devDependencies": {
Expand Down
39 changes: 23 additions & 16 deletions src/editor/editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,41 @@ import { compose } from '@wordpress/compose';
import apiFetch from '@wordpress/api-fetch';
import { withDispatch, withSelect } from '@wordpress/data';
import { useEffect } from '@wordpress/element';
import { registerPlugin } from '@wordpress/plugins';

/**
* Internal dependencies
*/
import { getEditPostPayload } from '../utils';
import './style.scss';

export default compose( [
withDispatch( dispatch => {
const { lockPostSaving, unlockPostSaving, editPost } = dispatch( 'core/editor' );
return { lockPostSaving, unlockPostSaving, editPost };
} ),
const Editor = compose( [
withSelect( select => {
const { getCurrentPostId, getEditedPostAttribute } = select( 'core/editor' );
const { getCurrentPostId, getEditedPostAttribute, isPublishingPost, isSavingPost } = select(
'core/editor'
);
const { getActiveGeneralSidebarName } = select( 'core/edit-post' );
const meta = getEditedPostAttribute( 'meta' );
return {
postId: getCurrentPostId(),
isReady: meta.campaign_validation_errors
? meta.campaign_validation_errors.length === 0
: false,
isReady: meta.campaignValidationErrors ? meta.campaignValidationErrors.length === 0 : false,
activeSidebarName: getActiveGeneralSidebarName(),
isPublishingOrSavingPost: isSavingPost() || isPublishingPost(),
};
} ),
withDispatch( dispatch => {
const { lockPostSaving, unlockPostSaving, editPost } = dispatch( 'core/editor' );
return { lockPostSaving, unlockPostSaving, editPost };
} ),
] )( props => {
// Fetch campaign data.
useEffect(() => {
// Fetch initially if the sidebar is be hidden.
if ( props.activeSidebarName !== 'edit-post/document' ) {
apiFetch( { path: `/newspack-newsletters/v1/mailchimp/${ props.postId }` } ).then( result => {
props.editPost( getEditPostPayload( result.campaign ) );
} );
}
}, []);
apiFetch( { path: `/newspack-newsletters/v1/mailchimp/${ props.postId }` } ).then( result => {
props.editPost( getEditPostPayload( result ) );
} );
}, [ props.isPublishingOrSavingPost ]);

// Lock or unlock post publishing.
useEffect(() => {
if ( props.isReady ) {
props.unlockPostSaving( 'newspack-newsletters-post-lock' );
Expand All @@ -49,3 +50,9 @@ export default compose( [

return null;
} );

export default () => {
registerPlugin( 'newspack-newsletters-edit', {
render: Editor,
} );
};
23 changes: 7 additions & 16 deletions src/editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { withSelect, withDispatch } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { Fragment, useState } from '@wordpress/element';
import domReady from '@wordpress/dom-ready';
import { PluginDocumentSettingPanel, PluginPrePublishPanel } from '@wordpress/edit-post';
import { PluginDocumentSettingPanel } from '@wordpress/edit-post';
import { addFilter } from '@wordpress/hooks';
import { registerPlugin } from '@wordpress/plugins';

Expand All @@ -16,13 +16,17 @@ import { registerPlugin } from '@wordpress/plugins';
*/
import TemplateModal from '../components/template-modal';
import Sidebar from './sidebar/';
import Editor from './editor/';
import PrePublishSlot from './pre-publish-slot';
import registerEditorPlugin from './editor/';
import registerPrePublishSlot from './pre-publish-slot';
import registerPostStatusSlot from './post-status-slot';
import registerPostsInserterBlock from './blocks/posts-inserter';
import { addBlocksValidationFilter } from './blocks-validation/blocks-filters';
import { NestedColumnsDetection } from './blocks-validation/nesting-detection';

addBlocksValidationFilter();
registerPrePublishSlot();
registerPostStatusSlot();
registerEditorPlugin();
registerPostsInserterBlock();

/* Unregister core block styles that are unsupported in emails */
Expand Down Expand Up @@ -113,16 +117,3 @@ registerPlugin( 'newspack-newsletters-sidebar', {
render: NewsletterEditWithSelect,
icon: null,
} );

registerPlugin( 'newspack-newsletters-pre-publish', {
render: () => (
<PluginPrePublishPanel>
<PrePublishSlot />
</PluginPrePublishPanel>
),
icon: null,
} );

registerPlugin( 'newspack-newsletters-edit', {
render: Editor,
} );
39 changes: 39 additions & 0 deletions src/editor/post-status-slot/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* External dependencies
*/
import { WebPreview } from 'newspack-components';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { withSelect } from '@wordpress/data';
import { PluginPostStatusInfo } from '@wordpress/edit-post';
import { registerPlugin } from '@wordpress/plugins';
import { Button } from '@wordpress/components';

const StatusInfoPreviewButton = ( { url } ) =>
url ? (
<PluginPostStatusInfo>
<WebPreview
url={ url }
renderButton={ ( { showPreview } ) => (
<Button isPrimary onClick={ showPreview }>
{ __( 'Preview', 'newspack-newsletters' ) }
</Button>
) }
/>
</PluginPostStatusInfo>
) : null;

const StatusInfoPreviewButtonWithSelect = withSelect( select => {
const { getEditedPostAttribute } = select( 'core/editor' );
const meta = getEditedPostAttribute( 'meta' );
return { url: meta.campaign && meta.campaign.long_archive_url };
} )( StatusInfoPreviewButton );

export default () => {
registerPlugin( 'newspack-newsletters-post-status-info', {
render: StatusInfoPreviewButtonWithSelect,
} );
};
17 changes: 15 additions & 2 deletions src/editor/pre-publish-slot/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import { Notice } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { registerPlugin } from '@wordpress/plugins';
import { PluginPrePublishPanel } from '@wordpress/edit-post';

export default withSelect( select => {
const PrePublishSlot = withSelect( select => {
const { getEditedPostAttribute } = select( 'core/editor' );
const meta = getEditedPostAttribute( 'meta' );
return {
validationErrors: meta.campaign_validation_errors || [],
validationErrors: meta.campaignValidationErrors || [],
};
} )( ( { validationErrors } ) => {
if ( validationErrors.length ) {
Expand All @@ -31,3 +33,14 @@ export default withSelect( select => {
</Notice>
);
} );

export default () => {
registerPlugin( 'newspack-newsletters-pre-publish', {
render: () => (
<PluginPrePublishPanel>
<PrePublishSlot />
</PluginPrePublishPanel>
),
icon: null,
} );
};
85 changes: 15 additions & 70 deletions src/editor/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,9 @@
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';
import { compose } from '@wordpress/compose';
import { withSelect, withDispatch, subscribe } from '@wordpress/data';
import { withSelect, withDispatch } from '@wordpress/data';
import { Component, Fragment } from '@wordpress/element';
import {
Button,
ExternalLink,
Modal,
Notice,
SelectControl,
Spinner,
TextControl,
} from '@wordpress/components';
import { Button, Modal, Notice, SelectControl, Spinner, TextControl } from '@wordpress/components';

/**
* External dependencies
Expand All @@ -29,38 +21,13 @@ import './style.scss';

class Sidebar extends Component {
state = {
campaign: {},
lists: [],
hasResults: false,
inFlight: false,
isPublishingOrSaving: false,
showTestModal: false,
testEmail: '',
senderEmail: '',
senderName: '',
senderDirty: false,
};
componentDidMount = () => {
this.retrieveMailchimp();
subscribe( () => {
const { isPublishingPost, isSavingPost } = this.props;
const { isPublishingOrSaving } = this.state;
if ( ( isPublishingPost() || isSavingPost() ) && ! isPublishingOrSaving ) {
this.setState( { isPublishingOrSaving: true } );
}
if ( ! isPublishingPost() && ! isSavingPost() && isPublishingOrSaving ) {
this.setState( { isPublishingOrSaving: false }, () => {
this.retrieveMailchimp();
} );
}
} );
};
retrieveMailchimp = () => {
const { postId } = this.props;
apiFetch( { path: `/newspack-newsletters/v1/mailchimp/${ postId }` } ).then( result =>
this.setStateFromAPIResponse( result )
);
};
sendMailchimpTest = () => {
const { testEmail } = this.state;
this.setState( { inFlight: true } );
Expand All @@ -72,7 +39,7 @@ class Sidebar extends Component {
},
method: 'POST',
};
apiFetch( params ).then( result => this.setStateFromAPIResponse( result ) );
apiFetch( params ).then( this.setStateFromAPIResponse );
};
setList = listId => {
this.setState( { inFlight: true } );
Expand All @@ -81,7 +48,7 @@ class Sidebar extends Component {
path: `/newspack-newsletters/v1/mailchimp/${ postId }/list/${ listId }`,
method: 'POST',
};
apiFetch( params ).then( result => this.setStateFromAPIResponse( result ) );
apiFetch( params ).then( this.setStateFromAPIResponse );
};
setInterest = interestId => {
this.setState( { inFlight: true } );
Expand All @@ -103,15 +70,12 @@ class Sidebar extends Component {
},
method: 'POST',
};
apiFetch( params ).then( result => this.setStateFromAPIResponse( result ) );
apiFetch( params ).then( this.setStateFromAPIResponse );
};
setStateFromAPIResponse = result => {
this.props.editPost( getEditPostPayload( result.campaign ) );
this.props.editPost( getEditPostPayload( result ) );

this.setState( {
campaign: result.campaign,
lists: result.lists.lists,
interestCategories: result.interest_categories,
hasResults: true,
inFlight: false,
senderName: result.campaign.settings.from_name,
senderEmail: result.campaign.settings.reply_to,
Expand Down Expand Up @@ -173,27 +137,17 @@ class Sidebar extends Component {
* Render
*/
render() {
const { editPost, title } = this.props;
const {
campaign,
hasResults,
inFlight,
lists,
showTestModal,
testEmail,
senderName,
senderEmail,
senderDirty,
} = this.state;
if ( ! hasResults ) {
const { campaign, lists, editPost, title } = this.props;
const { inFlight, showTestModal, testEmail, senderName, senderEmail, senderDirty } = this.state;
if ( ! campaign ) {
return (
<div className="newspack-newsletters__loading-data">
{ __( 'Retrieving Mailchimp data...', 'newspack-newsletters' ) }
<Spinner key="spinner" />
</div>
);
}
const { recipients, status, long_archive_url } = campaign || {};
const { recipients, status } = campaign || {};
const { list_id } = recipients || {};
if ( ! status ) {
return (
Expand Down Expand Up @@ -296,29 +250,20 @@ class Sidebar extends Component {
</Button>
</Modal>
) }
{ long_archive_url && (
<Fragment>
<hr />
<ExternalLink href={ long_archive_url }>
{ __( 'View on Mailchimp', 'newspack-newsletters' ) }
</ExternalLink>
</Fragment>
) }
</Fragment>
);
}
}

export default compose( [
withSelect( select => {
const { getEditedPostAttribute, getCurrentPostId, isPublishingPost, isSavingPost } = select(
'core/editor'
);
const { getEditedPostAttribute, getCurrentPostId } = select( 'core/editor' );
const meta = getEditedPostAttribute( 'meta' );
return {
title: getEditedPostAttribute( 'title' ),
campaign: meta.campaign,
lists: meta.lists ? meta.lists.lists : [],
postId: getCurrentPostId(),
isPublishingPost,
isSavingPost,
};
} ),
withDispatch( dispatch => {
Expand Down
10 changes: 6 additions & 4 deletions src/editor/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ const validateCampaign = campaign => {
return messages;
};

export const getEditPostPayload = campaign => ( {
export const getEditPostPayload = ( { campaign, lists } ) => ( {
meta: {
// This meta field does not have to be registered on the back end,
// as it is not used there.
campaign_validation_errors: validateCampaign( campaign ),
// These meta fields do not have to be registered on the back end,
// as they are not used there.
campaignValidationErrors: validateCampaign( campaign ),
campaign,
lists,
},
} );

0 comments on commit 515f281

Please sign in to comment.