Skip to content

Commit

Permalink
MailChimp integration spike.
Browse files Browse the repository at this point in the history
Rebsed after:
1. MailChimp integration query components. #18751
2. MailChimp getting started UI view. #18779
3. MailChimp setup log into MailChimp.com step. #18783
4. MailChimp API key input. #18789
5. MailChimp store info card. #18797
6. MailChimp newsletter settings UI component. #18804
7. Add MailChimp to plugins installation process. #18777
  • Loading branch information
budzanowski committed Oct 16, 2017
1 parent 18091d5 commit f6fe750
Show file tree
Hide file tree
Showing 20 changed files with 2,078 additions and 0 deletions.
39 changes: 39 additions & 0 deletions client/extensions/woocommerce/app/settings/email/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* External dependencies
*/
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { localize } from 'i18n-calypso';

/**
* Internal dependencies
*/
import Main from 'components/main';
import MailChimp from './mailchimp';
import ActionHeader from 'woocommerce/components/action-header';
import SettingsNavigation from '../navigation';
import { getLink } from 'woocommerce/lib/nav-utils';

const Email = ( { site, siteId, translate, className } ) => {
const breadcrumbs = [
( <a href={ getLink( '/store/:site/', site ) }>{ translate( 'Settings' ) }</a> ),
( <span>{ translate( 'Email' ) }</span> ),
];

return (
<Main className={ classNames( 'email', className ) }>
<ActionHeader breadcrumbs={ breadcrumbs } />
<SettingsNavigation activeSection="email" />
<MailChimp siteId={ siteId } />
</Main>
);
};

Email.propTypes = {
className: PropTypes.string,
siteId: PropTypes.number,
site: PropTypes.object,
};

export default localize( Email );
Empty file.
106 changes: 106 additions & 0 deletions client/extensions/woocommerce/app/settings/email/mailchimp/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* External dependencies
*/
import classNames from 'classnames';
import { connect } from 'react-redux';
import { filter, matches } from 'lodash';
import { localize } from 'i18n-calypso';
import PropTypes from 'prop-types';
import React from 'react';

/**
* Internal dependencies
*/
import Card from 'components/card';
import { getPlugins } from 'state/plugins/installed/selectors';
import { getSelectedSiteId } from 'state/ui/selectors';
import { isRequestingForSites } from 'state/plugins/installed/selectors';

import { mailchimpSettings, isRequestingSettings } from 'woocommerce/state/sites/settings/email/selectors';
import MailChimpGettingStarted from './getting-started';
import MailChimpSetup from './setup-mailchimp';
import MailChimpDashboard from './mailchimp_dashboard';
import QueryJetpackPlugins from 'components/data/query-jetpack-plugins';
import QueryMailChimpSettings from 'woocommerce/state/sites/settings/email/querySettings';

class MailChimp extends React.Component {

constructor( props ) {
super( props );
this.state = {
setupWizardStarted: false
};
}

startWizard = () => {
this.setState( { setupWizardStarted: true } );
}

closeWizard = () => {
this.setState( { setupWizardStarted: false } );
}

render() {
const { hasMailChimp, isRequestingMailChimpSettings, isRequestingPlugins, siteId, settings, translate } = this.props;
const className = classNames( 'mailchimp__main', { mailchimp__loading: isRequestingMailChimpSettings } );
const { setupWizardStarted } = this.state;
const isRequestingData = ( isRequestingMailChimpSettings || isRequestingPlugins );
const mailChimpIsReady = ! isRequestingData &&
( settings && settings.active_tab === 'sync' );
const gettingStarted = ! setupWizardStarted && ! isRequestingData &&
( settings && settings.active_tab !== 'sync' );
return (
<div className={ className }>
<QueryJetpackPlugins siteIds={ [ siteId ] } />
<QueryMailChimpSettings siteId={ siteId } />
{ isRequestingData && <Card>{ translate( 'MailChimp is Loading' ) }</Card> }
{ mailChimpIsReady && <MailChimpDashboard siteId={ siteId } onClick={ this.startWizard } /> }
{ gettingStarted &&
<MailChimpGettingStarted
siteId={ siteId }
isPlaceholder={ isRequestingMailChimpSettings }
onClick={ this.startWizard }
/>
}
{ setupWizardStarted &&
<MailChimpSetup
hasMailChimp={ hasMailChimp }
settings={ settings }
siteId={ siteId }
onClose={ this.closeWizard }
/>
}
</div>
);
}
}

MailChimp.propTypes = {
siteId: PropTypes.number.isRequired,
hasMailChimp: PropTypes.bool,
isRequestingPlugins: PropTypes.bool,
isRequestingMailChimpSettings: PropTypes.bool,
settings: PropTypes.object,
};

const MailChimpConnected = connect(
( state ) => {
const mailChimpId = 'mailchimp-for-woocommerce/mailchimp-woocommerce';
const siteId = getSelectedSiteId( state );
const isRequestingPlugins = isRequestingForSites( state, [ siteId ] );
const isRequestingMailChimpSettings = isRequestingSettings( state, siteId );
const sitePlugins = getPlugins( state, [ siteId ] );
const mailChimp = filter( sitePlugins, matches( { id: mailChimpId } ) );
const hasMailChimp = !! mailChimp.length;
const settings = mailchimpSettings( state, siteId );
return {
siteId,
hasMailChimp,
isRequestingPlugins,
isRequestingMailChimpSettings,
settings: settings || {},
};
}
)( MailChimp );

export default localize( MailChimpConnected );
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
/**
* External dependencies
*/
import React from 'react';
import { connect } from 'react-redux';

/**
* Internal dependencies
*/
import { localize } from 'i18n-calypso';
import Button from 'components/button';
import Card from 'components/card';
import FormCheckbox from 'components/forms/form-checkbox';
import FormFieldset from 'components/forms/form-fieldset';
import FormLabel from 'components/forms/form-label';
import FormLegend from 'components/forms/form-legend';
import FormToggle from 'components/forms/form-toggle';
import FormRadio from 'components/forms/form-radio';
import FormTextInput from 'components/forms/form-text-input';
import Notice from 'components/notice';
import QueryMailChimpSyncStatus from 'woocommerce/state/sites/settings/email/querySyncStatus';
import {
syncStatus,
mailchimpSettings,
isRequestingSettings } from 'woocommerce/state/sites/settings/email/selectors';
import { submitMailchimpNewsletterSettings, requestResync } from 'woocommerce/state/sites/settings/email/actions.js';
import { isSubmittingNewsletterSetting, newsletterSettingsSubmitError } from 'woocommerce/state/sites/settings/email/selectors';
import { errorNotice, successNotice } from 'state/notices/actions';

const SyncTab = localize( ( { siteId, translate, syncState, resync } ) => {
const { account_name, store_syncing, product_count, mailchimp_total_products,
mailchimp_total_orders, order_count } = syncState;
const hasProductInfo = ( product_count !== undefined ) && ( mailchimp_total_products !== undefined );
const products = hasProductInfo ? ( product_count + '/' + mailchimp_total_products ) : 'X/X';
const hasOrdersInfo = ( order_count !== undefined ) && ( mailchimp_total_orders !== undefined );
const orders = hasOrdersInfo ? ( order_count + '/' + mailchimp_total_orders ) : 'X/X';

const synced = () => (
<Notice
status="is-success"
isCompact={ true }
showDismiss={ false }
text={ syncState.mailchimp_list_name + ' ' + translate( 'list synced' ) }>
</Notice>
);

const syncing = () => (
<Notice
status="is-warning"
isCompact={ true }
showDismiss={ false }
text={ syncState.mailchimp_list_name + ' ' + translate( 'list is being synced' ) }>
</Notice>
);

const onResyncCLick = () => {
resync( siteId );
};

return (
<div>
<div>
<span className="mailchimp__account-info">{ translate( 'MailChimp account:' ) }</span>
<span>{ account_name }</span>
</div>
<span>{ store_syncing ? syncing() : synced() }</span>
<a onClick={ onResyncCLick }>Resync</a>
<div>
<span className="mailchimp__account-info" >{ translate( 'Products:' ) }</span>
<span>{ products }</span>
<span className="mailchimp__account-info" >{ ' ' + translate( 'Orders:' ) }</span>
<span>{ orders || '' }</span>
</div>
</div>
);
} );

const Settings = localize( ( { translate, settings, oldCheckbox, isSubbmittingSettings, onChange, onSave } ) => {
const onRadioChange = ( e ) => {
onChange( { mailchimp_checkbox_defaults: e.target.value } );
};

const onNewslatterLabelChange = ( e ) => {
onChange( { newsletter_label: e.target.value } );
};

const onToggle = ( e ) => {
const visibleOption = oldCheckbox !== 'hide' ? oldCheckbox : 'check';
onChange( { mailchimp_checkbox_defaults: e ? visibleOption : 'hide' } );
};

const checkbox = settings.mailchimp_checkbox_defaults;
const toggle = checkbox === 'check' || checkbox === 'uncheck';
return (
<div className="mailchimp__dashboard-settings">
<span className="mailchimp__dashboard-settings-form">
<FormFieldset>
<FormLegend>{ translate( 'Newsletter subscriptions' ) }</FormLegend>
<FormLabel>
<FormToggle
checked={ toggle }
onChange={ onToggle }
id="show-subscribe-message"
/>
<span>{ translate( 'Show a subscribe message to ustomer at checkout' ) }</span>
</FormLabel>
<FormLabel>
<FormRadio
disabled={ ! toggle }
value="check"
checked={ 'check' === checkbox }
onChange={ onRadioChange }
/>
<span>{ translate( 'Subscribe message is checked by default' ) }</span>
</FormLabel>
<FormLabel>
<FormRadio
disabled={ ! toggle }
value="uncheck"
checked={ 'uncheck' === checkbox }
onChange={ onRadioChange }
/>
<span>{ translate( 'Subscribe message is unchecked by default' ) }</span>
</FormLabel>
<FormLabel>
{ translate( 'Subscribe message is unchecked by default' ) }
</FormLabel>
<FormTextInput
name={ 'newsletter_label' }
onChange={ onNewslatterLabelChange }
value={ settings.newsletter_label }
/>
</FormFieldset>
</span>
<span className="mailchimp__dashboard-settings-preview">
<div>{ translate( 'PREVIEW' ) }</div>
<div className="mailchimp__dashboard-settings-preview-view">
{toggle && <FormLabel>
<FormCheckbox checked={ checkbox === 'check' } disabled={ true } />
<span>{ settings.newsletter_label }</span>
</FormLabel>}
</div>
<div className="mailchimp__dashboard-settings-save">
<Button
primary
onClick={ onSave }
busy={ isSubbmittingSettings }
disabled={ isSubbmittingSettings }>
{ translate( 'Save' ) }
</Button>
</div>
</span>
</div>
);
} );

class MailChimpDashboard extends React.Component {

constructor( props ) {
super( props );
this.state = {
syncStatus: null,
settings: props.settings
};
}

componentWillReceiveProps( nextProps ) {
const { translate } = nextProps;
if ( ( nextProps.isSubmittingNewsletterSetting === false ) && this.props.isSubmittingNewsletterSetting ) {
if ( nextProps.newsletterSettingsSubmitError ) {
nextProps.errorNotice( translate( 'There was a problem saving the email settings. Please try again.' ) );
} else {
nextProps.successNotice( translate( 'Email settings saved.' ), { duration: 4000 } );
}
}
}

onSettingsChange = ( change ) => {
this.setState( { settings: Object.assign( {}, this.state.settings, change ) } );
}

onSave = () => {
const { submitMailchimpNewsletterSettings: submit, siteId } = this.props;
const settings = this.state.settings;
const message = {
mailchimp_list: settings.mailchimp_list,
newsletter_label: settings.newsletter_label,
mailchimp_auto_subscribe: settings.mailchimp_auto_subscribe,
mailchimp_checkbox_defaults: settings.mailchimp_checkbox_defaults,
mailchimp_checkbox_action: settings.mailchimp_checkbox_action,
};
submit( siteId, message );
}

render() {
const { siteId, syncStatusData, translate } = this.props;
const slogan = translate( 'Allow customers to subscribe to your MailChimp email list' );

return (
<div>
<QueryMailChimpSyncStatus siteId={ siteId } />
<Card className="mailchimp__dashboard" >
<div className="mailchimp__dashboard-first-section" >
<span className="mailchimp__dashboard-title-and-slogan">
<div className="mailchimp__dashboard-title">Mailchimp</div>
<div>{ slogan }</div>
</span>
<span className="mailchimp__dashboard-sync-status" >
<SyncTab
siteId={ siteId }
syncState={ syncStatusData }
resync={ this.props.requestResync } />
</span>
</div>
<div className="mailchimp__dashboard-second-section" >
<Settings
settings={ this.state.settings }
isRequesting={ this.props.isRequestingSettings }
onChange={ this.onSettingsChange }
onSave={ this.onSave }
isSubbmittingSettings={ this.props.isSubmittingNewsletterSetting }
oldCheckbox={ this.props.settings.mailchimp_checkbox_defaults } />
</div>
<Button className="mailchimp__getting-started-button" onClick={ this.props.onClick }>
{ translate( 'Start setup wizard.' ) }
</Button>

</Card>
</div>
);
}
}

export default connect(
( state, { siteId } ) => ( {
siteId,
syncStatusData: syncStatus( state, siteId ),
isRequestingSettings: isRequestingSettings( state, siteId ),
isSubmittingNewsletterSetting: isSubmittingNewsletterSetting( state, siteId ),
newsletterSettingsSubmitError: newsletterSettingsSubmitError( state, siteId ),
settings: mailchimpSettings( state, siteId ),
} ),
{
errorNotice,
successNotice,
submitMailchimpNewsletterSettings,
requestResync
}
)( localize( MailChimpDashboard ) );
Loading

0 comments on commit f6fe750

Please sign in to comment.