Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plans: Reduxify Plan Remove component #2952

Merged
merged 23 commits into from
Feb 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
49e548c
Plans: Fix redirection failing when clicking success notice in Plans …
stephanethomas Feb 1, 2016
59b2a91
Plans: Remove duplicate action types constants
stephanethomas Feb 1, 2016
4710553
Plans: Rename action type constants for fetching site plans to follow…
stephanethomas Feb 1, 2016
68ca6d9
Plans: Rename action type constants for removing site plans to follow…
stephanethomas Feb 1, 2016
155272f
Framework: Order action type constants alphabetically
stephanethomas Feb 1, 2016
023bb89
Plans: Move import to the right place in Site Plans reducer
stephanethomas Feb 1, 2016
9f9922f
Plans: Order imports alphabetically in Site Plans actions
stephanethomas Feb 1, 2016
45f6e31
Plans: Update action for clearing site plans to return an action object
stephanethomas Feb 1, 2016
46cd8ee
Plans: Standardize descriptions of unit tests of Site Plans reducer
stephanethomas Feb 1, 2016
c10fc88
Plans: Update unit tests of Site Plans reducer to be easier to reason…
stephanethomas Feb 1, 2016
012549d
Plans: Add more unit tests for Site Plans reducer
stephanethomas Feb 1, 2016
2774663
Plans: Fix error not reset when fetching site plans
stephanethomas Feb 1, 2016
8ddd47f
Plans: Add error handling when fetching site plans
stephanethomas Feb 1, 2016
9a914ca
Plans: Update action for fetching site plans upon completion
stephanethomas Feb 1, 2016
0d76443
Plans: Add new actions for canceling a plan free trial
stephanethomas Feb 1, 2016
fc552a9
Plans: Extract duplicate code into function that update state in Site…
stephanethomas Feb 1, 2016
a9848cc
Plans: Reduxify the Plan Remove component
stephanethomas Feb 1, 2016
192fabd
Plans: Refine description of unit tests for Site Plans reducer
stephanethomas Feb 2, 2016
aa10d11
Plans: Fixed wrong translate calls in Site Plans actions
stephanethomas Feb 2, 2016
ff3702d
Plans: Merge imports in Site Plans reducer
stephanethomas Feb 5, 2016
f3d3e12
Plans: Fixed Site Plans reducer unit tests failing after a merge
stephanethomas Feb 5, 2016
2355f59
Plans: Rename updating flag in Site Plans reducer
stephanethomas Feb 5, 2016
16e700e
Plans: Rename fetching flag in Site Plans reducer
stephanethomas Feb 5, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/lib/plans/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export function isInGracePeriod( plan ) {
};

export function shouldFetchSitePlans( sitePlans, selectedSite ) {
return ! sitePlans.hasLoadedFromServer && ! sitePlans.isFetching && selectedSite;
return ! sitePlans.hasLoadedFromServer && ! sitePlans.isRequesting && selectedSite;
};

export function filterPlansBySiteAndProps( plans, site, hideFreePlan ) {
Expand Down
5 changes: 2 additions & 3 deletions client/my-sites/plans/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ var Plans = React.createClass( {
},

redirectToDefault() {
page.redirect( paths.plans( this.props.getSelectedSite().slug ) );
page.redirect( paths.plans( this.props.sites.getSelectedSite().slug ) );
},

renderNotice() {
Expand Down Expand Up @@ -148,8 +148,7 @@ var Plans = React.createClass( {
cart={ this.props.cart }
destinationType={ this.props.context.params.destinationType }
plan={ currentPlan }
selectedSite={ selectedSite }
store={ this.props.context.store } />
selectedSite={ selectedSite } />
);
}

Expand Down
6 changes: 2 additions & 4 deletions client/my-sites/plans/plan-overview/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ const PlanOverview = React.createClass( {
selectedSite: React.PropTypes.oneOfType( [
React.PropTypes.object,
React.PropTypes.bool
] ).isRequired,
store: React.PropTypes.object.isRequired
] ).isRequired
},

redirectToDefault() {
Expand Down Expand Up @@ -70,8 +69,7 @@ const PlanOverview = React.createClass( {

<PlanRemove
plan={ this.props.plan }
selectedSite={ this.props.selectedSite }
store={ this.props.store } />
selectedSite={ this.props.selectedSite } />
</Main>
</div>
);
Expand Down
57 changes: 33 additions & 24 deletions client/my-sites/plans/plan-overview/plan-remove/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,48 @@ import React from 'react';
/**
* Internal dependencies
*/
import { cancelSitePlanTrial } from 'state/sites/plans/actions';
import CompactCard from 'components/card/compact';
import { connect } from 'react-redux';
import Dialog from 'components/dialog';
import { getPlansBySite } from 'state/sites/plans/selectors';
import { isInGracePeriod } from 'lib/plans';
import notices from 'notices';
import paths from '../../paths';
import { fetchSitePlansCompleted } from 'state/sites/plans/actions';
import wpcom from 'lib/wp';

const PlanRemove = React.createClass( {
propTypes: {
cancelSitePlanTrial: React.PropTypes.func.isRequired,
isRequesting: React.PropTypes.bool.isRequired,
plan: React.PropTypes.object.isRequired,
selectedSite: React.PropTypes.oneOfType( [
React.PropTypes.object,
React.PropTypes.bool
] ).isRequired,
store: React.PropTypes.object.isRequired
] ).isRequired
},

getInitialState() {
return {
isCanceling: false,
showDialog: false
};
},

removePlan( closeDialog ) {
this.setState( { isCanceling: true } );
this.props.cancelSitePlanTrial( this.props.selectedSite.ID, this.props.plan.id ).then( () => {
Dispatcher.handleViewAction( {
type: 'FETCH_SITES'
} );

wpcom.undocumented().cancelPlanTrial( this.props.plan.id, ( error, data ) => {
if ( data && data.success ) {
this.props.store.dispatch( fetchSitePlansCompleted( this.props.selectedSite.ID, data.plans ) );
page( paths.plansDestination( this.props.selectedSite.slug, 'free-trial-canceled' ) );
} ).catch( ( error ) => {
closeDialog();

Dispatcher.handleViewAction( {
type: 'FETCH_SITES'
} );

page( paths.plansDestination( this.props.selectedSite.slug, 'free-trial-canceled' ) );
} else {
closeDialog();

notices.error( error.message || this.translate( 'There was a problem removing the plan. Please try again later or contact support.' ) );
}
notices.error( error );
} );
},

closeDialog() {
this.setState( {
isCanceling: false,
this.setState( {
showDialog: false
} );
},
Expand Down Expand Up @@ -84,12 +78,12 @@ const PlanRemove = React.createClass( {
const buttons = [
{
action: 'cancel',
disabled: this.state.isCanceling,
disabled: this.props.isRequesting,
label: this.translate( 'Cancel' )
},
{
action: 'remove',
disabled: this.state.isCanceling,
disabled: this.props.isRequesting,
isPrimary: true,
label: this.translate( 'Remove Now' ),
onClick: this.removePlan
Expand Down Expand Up @@ -135,4 +129,19 @@ const PlanRemove = React.createClass( {
}
} );

export default PlanRemove;
export default connect(
( state, props ) => {
const plans = getPlansBySite( state, props.selectedSite );

return {
isRequesting: plans.isRequesting
};
},
( dispatch ) => {
return {
cancelSitePlanTrial: ( siteId, planId ) => {
return dispatch( cancelSitePlanTrial( siteId, planId ) );
}
};
}
)( PlanRemove );
10 changes: 7 additions & 3 deletions client/state/action-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export const EXPORT_ADVANCED_SETTINGS_FETCH = 'EXPORT_ADVANCED_SETTINGS_FETCH';
export const EXPORT_ADVANCED_SETTINGS_FETCH_FAIL = 'EXPORT_ADVANCED_SETTINGS_FETCH_FAIL';
export const EXPORT_ADVANCED_SETTINGS_RECEIVE = 'EXPORT_ADVANCED_SETTINGS_RECEIVE';
export const FAIL_EXPORT = 'FAIL_EXPORT';
export const FETCH_SITE_PLANS = 'FETCH_SITE_PLANS';
export const FETCH_SITE_PLANS_COMPLETED = 'FETCH_SITE_PLANS_COMPLETED';
export const FETCH_WPORG_PLUGIN_DATA = 'FETCH_WPORG_PLUGIN_DATA';
export const NEW_NOTICE = 'NEW_NOTICE';
export const POST_REQUEST = 'POST_REQUEST';
Expand All @@ -39,14 +37,20 @@ export const PUBLICIZE_CONNECTIONS_REQUEST_FAILURE = 'PUBLICIZE_CONNECTIONS_REQU
export const READER_SIDEBAR_LISTS_TOGGLE = 'READER_SIDEBAR_LISTS_TOGGLE';
export const READER_SIDEBAR_TAGS_TOGGLE = 'READER_SIDEBAR_TAGS_TOGGLE';
export const REMOVE_NOTICE = 'REMOVE_NOTICE';
export const REMOVE_SITE_PLANS = 'REMOVE_SITE_PLANS';
export const REPLY_START_EXPORT = 'REPLY_START_EXPORT';
export const REQUEST_START_EXPORT = 'REQUEST_START_EXPORT';
export const SELECTED_SITE_SET = 'SELECTED_SITE_SET';
export const SERIALIZE = 'SERIALIZE';
export const SET_EXPORT_POST_TYPE = 'SET_EXPORT_POST_TYPE';
export const SET_ROUTE = 'SET_ROUTE';
export const SET_SECTION = 'SET_SECTION';
export const SITE_PLANS_FETCH = 'SITE_PLANS_FETCH';
export const SITE_PLANS_FETCH_COMPLETED = 'SITE_PLANS_FETCH_COMPLETED';
export const SITE_PLANS_FETCH_FAILED = 'SITE_PLANS_FETCH_FAILED';
export const SITE_PLANS_REMOVE = 'SITE_PLANS_REMOVE';
export const SITE_PLANS_TRIAL_CANCEL = 'SITE_PLANS_TRIAL_CANCEL';
export const SITE_PLANS_TRIAL_CANCEL_COMPLETED = 'SITE_PLANS_TRIAL_CANCEL_COMPLETED';
export const SITE_PLANS_TRIAL_CANCEL_FAILED = 'SITE_PLANS_TRIAL_CANCEL_FAILED';
export const SITE_RECEIVE = 'SITE_RECEIVE';
export const SUPPORT_USER_TOKEN_FETCH = 'SUPPORT_USER_TOKEN_FETCH';
export const SUPPORT_USER_TOKEN_SET = 'SUPPORT_USER_TOKEN_SET';
Expand Down
4 changes: 2 additions & 2 deletions client/state/sites/plans/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Used in combination with the Redux store instance `dispatch` function, actions c

Fetches plans for the site with the given site ID.

### `fetchSitePlansCompleted( siteId: Number, plans: Object )`
### `fetchSitePlansCompleted( siteId: Number, data: Object )`

Adds the plans to the set of plans for the given site ID.
Adds the plans fetched from the API to the set of plans for the given site ID.

```js
import { fetchSitePlans, fetchSitePlansCompleted } from 'state/sites/plans/actions';
Expand Down
3 changes: 0 additions & 3 deletions client/state/sites/plans/action-types.js

This file was deleted.

89 changes: 69 additions & 20 deletions client/state/sites/plans/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,73 @@ const debug = debugFactory( 'calypso:site-plans:actions' );
* Internal dependencies
*/
import { createSitePlanObject } from './assembler';
import wpcom from 'lib/wp';
import i18n from 'lib/mixins/i18n';
import {
FETCH_SITE_PLANS,
FETCH_SITE_PLANS_COMPLETED,
REMOVE_SITE_PLANS
} from './action-types';
SITE_PLANS_FETCH,
SITE_PLANS_FETCH_COMPLETED,
SITE_PLANS_FETCH_FAILED,
SITE_PLANS_REMOVE,
SITE_PLANS_TRIAL_CANCEL,
SITE_PLANS_TRIAL_CANCEL_COMPLETED,
SITE_PLANS_TRIAL_CANCEL_FAILED
} from 'state/action-types';
import wpcom from 'lib/wp';

/**
* Clears plans for the given site.
* Cancels the specified plan trial for the given site.
*
* @param {Number} siteId identifier of the site
* @returns {Function} the corresponding action thunk
* @param {Number} planId identifier of the plan
* @returns {Function} a promise that will resolve once updating is completed
*/
export function clearSitePlans( siteId ) {
export function cancelSitePlanTrial( siteId, planId ) {
return ( dispatch ) => {
dispatch( {
type: REMOVE_SITE_PLANS,
type: SITE_PLANS_TRIAL_CANCEL,
siteId
} );

return new Promise( ( resolve, reject ) => {
wpcom.undocumented().cancelPlanTrial( planId, ( error, data ) => {
if ( data && data.success ) {
dispatch( {
type: SITE_PLANS_TRIAL_CANCEL_COMPLETED,
siteId,
plans: map( data.plans, createSitePlanObject )
} );

resolve();
} else {
debug( 'Canceling site plan trial failed: ', error );

const errorMessage = error.message || i18n.translate( 'There was a problem canceling the plan trial. Please try again later or contact support.' );

dispatch( {
type: SITE_PLANS_TRIAL_CANCEL_FAILED,
siteId,
error: errorMessage
} );

reject( errorMessage );
}
} );
} );
}
}

/**
* Returns an action object to be used in signalling that plans for the given site has been cleared.
*
* @param {Number} siteId identifier of the site
* @returns {Object} the corresponding action object
*/
export function clearSitePlans( siteId ) {
return {
type: SITE_PLANS_REMOVE,
siteId
};
}

/**
* Fetches plans for the given site.
*
Expand All @@ -42,14 +87,22 @@ export function clearSitePlans( siteId ) {
export function fetchSitePlans( siteId ) {
return ( dispatch ) => {
dispatch( {
type: FETCH_SITE_PLANS,
type: SITE_PLANS_FETCH,
siteId
} );

return new Promise( ( resolve ) => {
wpcom.undocumented().getSitePlans( siteId, ( error, data ) => {
if ( error ) {
debug( 'Fetching site plans failed: ', error );

const errorMessage = error.message || i18n.translate( 'There was a problem fetching site plans. Please try again later or contact support.' );

dispatch( {
type: SITE_PLANS_FETCH_FAILED,
siteId,
error: errorMessage
} );
} else {
dispatch( fetchSitePlansCompleted( siteId, data ) );
}
Expand All @@ -65,16 +118,16 @@ export function fetchSitePlans( siteId ) {
* the plans for a given site have been received.
*
* @param {Number} siteId identifier of the site
* @param {Object} plans list of plans received from the API
* @param {Object} data list of plans received from the API
* @returns {Object} the corresponding action object
*/
export function fetchSitePlansCompleted( siteId, plans ) {
plans = reject( plans, '_headers' );
export function fetchSitePlansCompleted( siteId, data ) {
data = reject( data, '_headers' );

return {
type: FETCH_SITE_PLANS_COMPLETED,
type: SITE_PLANS_FETCH_COMPLETED,
siteId,
plans: map( plans, createSitePlanObject )
plans: map( data, createSitePlanObject )
};
}

Expand All @@ -86,11 +139,7 @@ export function fetchSitePlansCompleted( siteId, plans ) {
*/
export function refreshSitePlans( siteId ) {
return ( dispatch ) => {
dispatch( {
type: REMOVE_SITE_PLANS,
siteId
} );

dispatch( clearSitePlans( siteId ) );
dispatch( fetchSitePlans( siteId ) );
}
}
Loading