Skip to content

Commit

Permalink
Merge pull request #4067 from Automattic/update/non-admins-renew
Browse files Browse the repository at this point in the history
Checkout: Allow non-admins to renew their subscriptions
  • Loading branch information
scruffian committed Mar 18, 2016
2 parents e607557 + 586e701 commit 7412894
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 19 deletions.
2 changes: 2 additions & 0 deletions client/components/data/purchases/manage-purchase/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const user = userFactory(),
function getStateFromStores( props ) {
return {
cart: CartStore.get(),
hasLoadedSites: props.hasLoadedSites,
purchaseId: props.purchaseId,
selectedPurchase: PurchasesStore.getByPurchaseId( parseInt( props.purchaseId, 10 ) ),
selectedSite: props.selectedSite,
Expand Down Expand Up @@ -57,6 +58,7 @@ const ManagePurchaseData = React.createClass( {
return (
<StoreConnection
component={ this.props.component }
hasLoadedSites={ this.props.sites.fetched }
isDataLoading={ this.props.isDataLoading }
loadingPlaceholder={ this.props.loadingPlaceholder }
stores={ stores }
Expand Down
8 changes: 8 additions & 0 deletions client/components/plans/plan-actions/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ var PlanActions = React.createClass( {
return null;
}

if ( this.props.site && ! this.props.site.isUpgradeable() ) {
return null;
}

if ( this.siteHasThisPlan() ) {
if ( this.props.sitePlan.freeTrial ) {
return this.upgradeActions();
Expand Down Expand Up @@ -132,6 +136,10 @@ var PlanActions = React.createClass( {
return;
}

if ( this.props.site && ! this.props.site.isUpgradeable() ) {
return;
}

const actionType = event.target.tagName === 'A' ? 'link' : 'button';

if ( 'link' === actionType ) {
Expand Down
4 changes: 0 additions & 4 deletions client/lib/cart/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ function setSelectedSite() {
return;
}

if ( ! selectedSite.isUpgradeable() ) {
return;
}

if ( _synchronizer && _poller ) {
PollerPool.remove( _poller );
_synchronizer.off( 'change', emitChange );
Expand Down
72 changes: 59 additions & 13 deletions client/me/purchases/manage-purchase/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { getDetailsUrl as getThemeDetailsUrl } from 'my-sites/themes/helpers';
import paths from '../paths';
import PaymentLogo from 'components/payment-logo';
import RemovePurchase from '../remove-purchase';
import supportPaths from 'lib/url/support';
import titles from 'me/purchases/titles';
import VerticalNavItem from 'components/vertical-nav/item';
import * as upgradesActions from 'lib/upgrades/actions';
Expand All @@ -46,21 +47,33 @@ import {
purchaseType,
showCreditCardExpiringWarning,
} from 'lib/purchases';
import { getPurchase, getSelectedSite, goToList, isDataLoading, recordPageView } from '../utils';
import { getPurchase, getSelectedSite, goToList, recordPageView } from '../utils';
import { isDomainProduct, isGoogleApps, isPlan, isSiteRedirect, isTheme } from 'lib/products-values';

function canEditPaymentDetails( purchase ) {
return config.isEnabled( 'upgrades/credit-cards' ) && ! isExpired( purchase ) && ! isOneTimePurchase( purchase ) && ! isIncludedWithPlan( purchase );
}

/**
* Determines if data is being fetched. This is different than `isDataLoading` in `PurchasesUtils`
* because this page can be rendered without a selected site.
*
* @param {object} props The props passed to `ManagePurchase`
* @return {bool} Whether or not the data is loading
*/
function isDataLoading( props ) {
return ! props.hasLoadedSites || ! props.selectedPurchase.hasLoadedFromServer;
}

const ManagePurchase = React.createClass( {
propTypes: {
cart: React.PropTypes.object.isRequired,
selectedPurchase: React.PropTypes.object.isRequired,
selectedSite: React.PropTypes.oneOfType( [
React.PropTypes.object,
React.PropTypes.bool
] ).isRequired,
React.PropTypes.bool,
React.PropTypes.undefined
] ),
destinationType: React.PropTypes.string,
user: React.PropTypes.object.isRequired
},
Expand Down Expand Up @@ -88,7 +101,7 @@ const ManagePurchase = React.createClass( {
return true;
}

return getSelectedSite( props ) && getPurchase( props );
return Boolean( getPurchase( props ) );
},

renderNotices() {
Expand All @@ -99,6 +112,28 @@ const ManagePurchase = React.createClass( {
return this.renderPurchaseExpiringNotice() || this.renderCreditCardExpiringNotice();
},

renderContactSupportToRenewMessage() {
const purchase = getPurchase( this.props );

if ( getSelectedSite( this.props ) ) {
return null;
}

return (
<div className="manage-purchase__contact-support">
{ this.translate( '{{strong}}Looking to renew?{{/strong}} Please {{contactSupportLink}}contact support{{/contactSupportLink}} to renew %(purchaseName)s.', {
args: {
purchaseName: getName( purchase )
},
components: {
strong: <strong />,
contactSupportLink: <a href={ supportPaths.CONTACT } />
}
} ) }
</div>
);
},

renderPurchaseExpiringNotice() {
const purchase = getPurchase( this.props );
let noticeStatus = 'is-info';
Expand Down Expand Up @@ -130,7 +165,7 @@ const ManagePurchase = React.createClass( {
},

renderRenewNoticeAction() {
if ( ! config.isEnabled( 'upgrades/checkout' ) ) {
if ( ! config.isEnabled( 'upgrades/checkout' ) || ! getSelectedSite( this.props ) ) {
return null;
}

Expand All @@ -145,7 +180,7 @@ const ManagePurchase = React.createClass( {
const purchase = getPurchase( this.props ),
{ id, payment: { creditCard } } = purchase;

if ( isExpired( purchase ) || isOneTimePurchase( purchase ) || isIncludedWithPlan( purchase ) ) {
if ( isExpired( purchase ) || isOneTimePurchase( purchase ) || isIncludedWithPlan( purchase ) || ! getSelectedSite( this.props ) ) {
return null;
}

Expand Down Expand Up @@ -279,10 +314,14 @@ const ManagePurchase = React.createClass( {
},

renderProductLink() {
const { selectedSite } = this.props,
const selectedSite = getSelectedSite( this.props ),
purchase = getPurchase( this.props );
let url, text;

if ( ! selectedSite ) {
return null;
}

if ( isPlan( purchase ) ) {
url = '/plans/compare';
text = this.translate( 'View Plan Features' );
Expand Down Expand Up @@ -367,7 +406,7 @@ const ManagePurchase = React.createClass( {
</span>
);

if ( isDataLoading( this.props ) || ! canEditPaymentDetails( purchase ) || ! isPaidWithCreditCard( purchase ) ) {
if ( isDataLoading( this.props ) || ! canEditPaymentDetails( purchase ) || ! isPaidWithCreditCard( purchase ) || ! getSelectedSite( this.props ) ) {
return (
<li>
{ paymentDetails }
Expand All @@ -389,7 +428,7 @@ const ManagePurchase = React.createClass( {
renderRenewButton() {
const purchase = getPurchase( this.props );

if ( ! config.isEnabled( 'upgrades/checkout' ) || ! isRenewable( purchase ) || isExpired( purchase ) || isExpiring( purchase ) ) {
if ( ! config.isEnabled( 'upgrades/checkout' ) || ! isRenewable( purchase ) || isExpired( purchase ) || isExpiring( purchase ) || ! getSelectedSite( this.props ) ) {
return null;
}

Expand Down Expand Up @@ -469,6 +508,10 @@ const ManagePurchase = React.createClass( {
const purchase = getPurchase( this.props ),
{ id, payment } = purchase;

if ( ! getSelectedSite( this.props ) ) {
return null;
}

let path = paths.editCardDetails( this.props.selectedSite.slug, id );
if ( isPaidWithCreditCard( purchase ) ) {
path = paths.editSpecificCardDetails( this.props.selectedSite.slug, id, payment.creditCard.id );
Expand All @@ -482,14 +525,14 @@ const ManagePurchase = React.createClass( {
);
}

return null
return null;
},

renderCancelPurchaseNavItem() {
const purchase = getPurchase( this.props ),
{ id } = purchase;

if ( ! isCancelable( purchase ) ) {
if ( ! isCancelable( purchase ) || ! getSelectedSite( this.props ) ) {
return null;
}

Expand All @@ -512,7 +555,7 @@ const ManagePurchase = React.createClass( {
const purchase = getPurchase( this.props ),
{ id } = purchase;

if ( isExpired( purchase ) || ! hasPrivateRegistration( purchase ) ) {
if ( isExpired( purchase ) || ! hasPrivateRegistration( purchase ) || ! getSelectedSite( this.props ) ) {
return null;
}

Expand All @@ -539,7 +582,8 @@ const ManagePurchase = React.createClass( {
expiredRenewNotice,
editPaymentMethodNavItem,
cancelPurchaseNavItem,
cancelPrivateRegistrationNavItem;
cancelPrivateRegistrationNavItem,
contactSupportToRenewMessage;

if ( isDataLoading( this.props ) ) {
classes = 'manage-purchase__info is-placeholder';
Expand All @@ -560,6 +604,7 @@ const ManagePurchase = React.createClass( {
renewsOrExpiresOnLabel = this.renderRenewsOrExpiresOnLabel();
renewsOrExpiresOn = this.renderRenewsOrExpiresOn();
renewButton = this.renderRenewButton();
contactSupportToRenewMessage = this.renderContactSupportToRenewMessage();
expiredRenewNotice = this.renderExpiredRenewNotice();
editPaymentMethodNavItem = this.renderEditPaymentMethodNavItem();
cancelPurchaseNavItem = this.renderCancelPurchaseNavItem();
Expand Down Expand Up @@ -596,6 +641,7 @@ const ManagePurchase = React.createClass( {
</ul>

{ renewButton }
{ contactSupportToRenewMessage }
</Card>

{ expiredRenewNotice }
Expand Down
7 changes: 7 additions & 0 deletions client/me/purchases/manage-purchase/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,10 @@
top: 16px;
}
}

.manage-purchase__contact-support {
border-top: solid 1px lighten( $gray, 30% );
color: $gray;
margin-top: 15px;
padding-top: 10px;
}
5 changes: 3 additions & 2 deletions client/me/purchases/remove-purchase/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ const RemovePurchase = React.createClass( {
selectedPurchase: React.PropTypes.object.isRequired,
selectedSite: React.PropTypes.oneOfType( [
React.PropTypes.object,
React.PropTypes.bool
] ).isRequired,
React.PropTypes.bool,
React.PropTypes.undefined
] ),
user: React.PropTypes.object.isRequired
},

Expand Down

0 comments on commit 7412894

Please sign in to comment.