Skip to content

Commit

Permalink
Themes: 'Thanks' modal on activation from Theme Sheet (#5259)
Browse files Browse the repository at this point in the history
* Themes: Thanks modal in sheet when activating theme
* Add README.md for empty component
* Themes: `source` prop for thanks modal
* Themes: Show customize link in modal on sheet activation
* Themes: Click-tracking for thanks-modal
* Themes: use mapDispatchToProps for sheet actions
  • Loading branch information
seear committed May 12, 2016
1 parent 7217096 commit c65ca89
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 21 deletions.
2 changes: 2 additions & 0 deletions client/components/data/activating-theme/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/** @ssr-ready **/

/**
* External dependencies
*/
Expand Down
18 changes: 18 additions & 0 deletions client/components/empty-component/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
EmptyComponent
==============

Useful for stubbing out components that will not build on the server when rendering server-side.

#### How to use:

In the webpack server [config file](/webpack.config.node.js):
```js
plugins: [
...
new webpack.NormalModuleReplacementPlugin( /^my-sites\/themes\/thanks-modal$/, 'components/empty-component' ) // Depends on BOM
],
```
In the above example, on the server build, any occurrences of `/my-sites/themes/thanks-modal` will be replaced with the empty component.

NOTE: You will also need to add the replaced component to the list of ignored modules in the [SSR pragma checker](/server/pragma-checker/index.js).

6 changes: 6 additions & 0 deletions client/components/empty-component/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* External dependencies
*/
import React from 'react';

export default () => <div/>;
32 changes: 22 additions & 10 deletions client/my-sites/theme/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import React from 'react';
import { connect } from 'react-redux';
import page from 'page';
import { isPremium } from 'my-sites/themes/helpers';

/**
* Internal dependencies
Expand All @@ -23,11 +22,14 @@ import NavTabs from 'components/section-nav/tabs';
import NavItem from 'components/section-nav/item';
import Card from 'components/card';
import Gridicon from 'components/gridicon';
import { signup, purchase, activate } from 'state/themes/actions';
import { signup, purchase, activate, clearActivated } from 'state/themes/actions';
import i18n from 'lib/mixins/i18n';
import { getSelectedSite } from 'state/ui/selectors';
import { getSiteSlug } from 'state/sites/selectors';
import Helpers from 'my-sites/themes/helpers';
import { isPremium } from 'my-sites/themes/helpers';
import ActivatingTheme from 'components/data/activating-theme';
import ThanksModal from 'my-sites/themes/thanks-modal';

const ThemeSheet = React.createClass( {
displayName: 'ThemeSheet',
Expand Down Expand Up @@ -61,13 +63,13 @@ const ThemeSheet = React.createClass( {
// TODO: if active -> customize (could use theme slug from selected site)

if ( ! this.props.isLoggedIn ) {
this.props.dispatch( signup( this.props ) );
this.props.signup( this.props );
// TODO: use site picker if no selected site
} else if ( isPremium( this.props ) ) {
// TODO: check theme is not already purchased
this.props.dispatch( purchase( this.props, this.props.selectedSite, 'showcase-sheet' ) );
this.props.purchase( this.props, this.props.selectedSite, 'showcase-sheet' );
} else {
this.props.dispatch( activate( this.props, this.props.selectedSite, 'showcase-sheet' ) );
this.props.activate( this.props, this.props.selectedSite, 'showcase-sheet' );
}
},

Expand Down Expand Up @@ -216,10 +218,17 @@ const ThemeSheet = React.createClass( {

const section = this.validateSection( this.props.section );
const priceElement = <span className="themes__sheet-action-bar-cost" dangerouslySetInnerHTML={ { __html: this.props.price } } />;
const siteID = this.props.selectedSite && this.props.selectedSite.ID;

return (
<Main className="themes__sheet">
{ this.renderBar() }
<ActivatingTheme siteId={ siteID }>
<ThanksModal
site={ this.props.selectedSite }
source={ 'details' }
clearActivated={ this.props.clearActivated }/>
</ActivatingTheme>
<div className="themes__sheet-columns">
<div className="themes__sheet-column-left">
<HeaderCake className="themes__sheet-action-bar" onClick={ this.onBackClick }>
Expand All @@ -246,8 +255,11 @@ const ThemeSheet = React.createClass( {
}
} );

export default connect( ( state ) => {
const selectedSite = getSelectedSite( state );
const siteSlug = selectedSite ? getSiteSlug( state, selectedSite.ID ) : '';
return { selectedSite, siteSlug };
} )( ThemeSheet );
export default connect(
( state ) => {
const selectedSite = getSelectedSite( state );
const siteSlug = selectedSite ? getSiteSlug( state, selectedSite.ID ) : '';
return { selectedSite, siteSlug };
},
{ signup, purchase, activate, clearActivated }
)( ThemeSheet );
1 change: 1 addition & 0 deletions client/my-sites/themes/single-site.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ var ThemesSingleSite = React.createClass( {
<ActivatingTheme siteId={ site.ID } >
<ThanksModal
site={ site }
source={ 'list' }
clearActivated={ bindActionCreators( Action.clearActivated, this.props.dispatch ) } />
</ActivatingTheme>
<CurrentThemeData site={ site }>
Expand Down
44 changes: 34 additions & 10 deletions client/my-sites/themes/thanks-modal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ var ThanksModal = React.createClass( {
trackClick: Helpers.trackClick.bind( null, 'current theme' ),

propTypes: {
clearActivated: React.PropTypes.func.isRequired
clearActivated: React.PropTypes.func.isRequired,
// Where is the modal being used?
source: React.PropTypes.oneOf( [ 'details', 'list' ] ).isRequired,
},

onCloseModal: function() {
Expand All @@ -32,20 +34,36 @@ var ThanksModal = React.createClass( {
this.onCloseModal();
},

onLinkClick: function( link ) {
return this.trackClick.bind( null, link, 'click' );
},

renderWpcomInfo: function() {
const features = this.translate( "Discover this theme's {{a}}awesome features.{{/a}}", {
components: {
a: <a href={ Helpers.getDetailsUrl( this.props.currentTheme, this.props.site ) }
target="_blank"
onClick={ this.onLinkClick( 'features' ) }/>
}
} );
const customize = this.translate( '{{a}}Customize{{/a}} this design.', {
components: {
a: <a href={ Helpers.getCustomizeUrl( this.props.currentTheme, this.props.site ) }
target="_blank"
onClick={ this.onLinkClick( 'customize' ) }/>
}
} );
return (
<ul>
<li>
{ this.translate( "Discover this theme's {{a}}awesome features.{{/a}}", {
components: {
a: <a href={ Helpers.getDetailsUrl( this.props.currentTheme, this.props.site ) } target="_blank" />
}
} ) }
{ this.props.source === 'list' ? features : customize }
</li>
<li>
{ this.translate( 'Have questions? Stop by our {{a}}support forums.{{/a}}', {
components: {
a: <a href={ Helpers.getForumUrl( this.props.currentTheme ) } target="_blank" />
a: <a href={ Helpers.getForumUrl( this.props.currentTheme ) }
target="_blank"
onClick={ this.onLinkClick( 'support' ) }/>
}
} ) }
</li>
Expand All @@ -59,7 +77,9 @@ var ThanksModal = React.createClass( {
<li>
{ this.translate( 'Learn more about this {{a}}awesome theme{{/a}}.', {
components: {
a: <a href={ themeUri } target="_blank" />
a: <a href={ themeUri }
target="_blank"
onClick={ this.onLinkClick( 'org theme' ) }/>
}
} ) }
</li>
Expand All @@ -73,7 +93,9 @@ var ThanksModal = React.createClass( {
<li>
{ this.translate( 'Have questions? {{a}}Contact the theme author.{{/a}}', {
components: {
a: <a href={ authorUri } target="_blank" />
a: <a href={ authorUri }
target="_blank"
onClick={ this.onLinkClick( 'org author' ) }/>
}
} ) }
</li>
Expand All @@ -86,7 +108,9 @@ var ThanksModal = React.createClass( {
<li>
{ this.translate( 'If you need support, visit the WordPress.org {{a}}Themes forum{{/a}}.', {
components: {
a: <a href="https://wordpress.org/support/forum/themes-and-templates" target="_blank" />
a: <a href="https://wordpress.org/support/forum/themes-and-templates"
target="_blank"
onClick={ this.onLinkClick( 'org forum' ) }/>
}
} ) }
</li>
Expand Down
1 change: 1 addition & 0 deletions server/pragma-checker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var IGNORED_MODULES = [
'lib/upgrades/actions', // nooped on the server as it still uses the singleton Flux architecture
'lib/mixins/i18n', // ignore this until we make it work properly on the server
'lib/mixins/i18n/localize', // ignore this until we make it work properly on the server
'my-sites/themes/thanks-modal', // stubbed on the server until we develop an isomorphic version
];

function PragmaCheckPlugin( options ) {
Expand Down
3 changes: 2 additions & 1 deletion webpack.config.node.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ module.exports = {
new webpack.BannerPlugin( 'require( "source-map-support" ).install();', { raw: true, entryOnly: false } ),
new webpack.NormalModuleReplacementPlugin( /^lib\/analytics$/, 'lodash/noop' ), // Depends on BOM
new webpack.NormalModuleReplacementPlugin( /^lib\/upgrades\/actions$/, 'lodash/noop' ), // Uses Flux dispatcher
new webpack.NormalModuleReplacementPlugin( /^lib\/route$/, 'lodash/noop' ) // Depends too much on page.js
new webpack.NormalModuleReplacementPlugin( /^lib\/route$/, 'lodash/noop' ), // Depends too much on page.js
new webpack.NormalModuleReplacementPlugin( /^my-sites\/themes\/thanks-modal$/, 'components/empty-component' ) // Depends on BOM
],
externals: getExternals()
};

0 comments on commit c65ca89

Please sign in to comment.