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

Support: Add concierge offer to contact form #16144

Merged
merged 8 commits into from
Jul 14, 2017
66 changes: 66 additions & 0 deletions client/me/help/chat-business-concierge-notice/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* External dependencies
*/
import { identity } from 'lodash';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import i18n, { localize } from 'i18n-calypso';

/**
* Internal dependencies
*/
import analytics from 'lib/analytics';
import HelpTeaserButton from '../help-teaser-button';
import { isBusinessPlanUser } from 'state/selectors';

class ChatBusinessConciergeNotice extends Component {
static propTypes = {
translate: PropTypes.func,
isBusinessPlanUser: PropTypes.bool.isRequired,
from: PropTypes.string.isRequired,
to: PropTypes.string.isRequired,
};

static defaultProps = {
translate: identity,
};

trackCalendlyOfferClick = () => {
analytics.tracks.recordEvent( 'calypso_help_calendly_offer_click' );
};

render = () => {
const { translate } = this.props;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just nitpicking around, not a blocker but I guess we could destructure all used props here instead of using this.props

const fromDate = i18n.moment( this.props.from );
const toDate = i18n.moment( this.props.to );

if ( ! i18n.moment().isAfter( fromDate ) || ! i18n.moment().isBefore( toDate ) ) {
return null;
}

if ( ! this.props.isBusinessPlanUser ) {
return (
<HelpTeaserButton
title={ translate( 'Chat is temporarily closed.' ) }
description={ translate(
'We\'re still available over email in the meantime. ' +
'Chat will be back on Friday, July 21st!'
) } />
);
}

return (
<HelpTeaserButton
onClick={ this.trackCalendlyOfferClick }
href="https://calendly.com/wordpressdotcom/wordpress-com-business-site-setup/"
title={ translate( 'Chat with us over screenshare!' ) }
description={ translate( 'Click here to get one-on-one help with a Happiness Engineer.' ) } />
);
}
}

export default connect(
( state ) => ( {
isBusinessPlanUser: isBusinessPlanUser( state ),
} )
)( localize( ChatBusinessConciergeNotice ) );
7 changes: 7 additions & 0 deletions client/me/help/help-contact-form/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import FormTextInput from 'components/forms/form-text-input';
import FormButton from 'components/forms/form-button';
import SitesDropdown from 'components/sites-dropdown';
import ChatClosureNotice from '../chat-closure-notice';
import ChatBusinessConciergeNotice from '../chat-business-concierge-notice';
import { selectSiteId } from 'state/help/actions';
import { getHelpSelectedSite } from 'state/help/selectors';
import wpcomLib from 'lib/wp';
Expand Down Expand Up @@ -240,8 +241,14 @@ export const HelpContactForm = React.createClass( {
from="2016-12-24T00:00:00Z"
to="2017-01-02T00:00:00Z"
/>

{ formDescription && ( <p>{ formDescription }</p> ) }

<ChatBusinessConciergeNotice
from="2017-07-19T00:00:00Z"
to="2017-07-21T00:00:00Z"
/>

{ showHowCanWeHelpField && (
<div>
<FormLabel>{ translate( 'How can we help?' ) }</FormLabel>
Expand Down
2 changes: 2 additions & 0 deletions client/me/help/help-contact/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
isDirectlyReady,
isDirectlyUninitialized,
} from 'state/selectors';
import QueryUserPurchases from 'components/data/query-user-purchases';

/**
* Module variables
Expand Down Expand Up @@ -666,6 +667,7 @@ const HelpContact = React.createClass( {
<HappychatConnection />
<QueryOlark />
<QueryTicketSupportConfiguration />
<QueryUserPurchases userId={ this.props.currentUser.ID } />
</Main>
);
}
Expand Down
1 change: 1 addition & 0 deletions client/state/selectors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export isActivatingJetpackModule from './is-activating-jetpack-module';
export isAmbiguousThemeFilterTerm from './is-ambiguous-theme-filter-term';
export isAutomatedTransferActive from './is-automated-transfer-active';
export isAutomatedTransferFailed from './is-automated-transfer-failed';
export isBusinessPlanUser from './is-business-plan-user';
export isDeactivatingJetpackJumpstart from './is-deactivating-jetpack-jumpstart';
export isDeactivatingJetpackModule from './is-deactivating-jetpack-module';
export isDeletingPublicizeShareAction from './is-deleting-publicize-share-action';
Expand Down
28 changes: 28 additions & 0 deletions client/state/selectors/is-business-plan-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Internal dependencies
*/
import { getCurrentUserId } from 'state/current-user/selectors';
import { getUserPurchases } from 'state/purchases/selectors';
import { PLAN_BUSINESS } from 'lib/plans/constants';

/**
* Returns a boolean flag indicating if the current user is a business plan user.
*
* @param {Object} state Global state tree
* @return {Boolean} If the current user is a business plan user.
*/
export default ( state ) => {
const userId = getCurrentUserId( state );

if ( ! userId ) {
return false;
}

const purchases = getUserPurchases( state, userId );

if ( ! purchases || 0 === purchases.length ) {
return false;
}

return purchases.some( ( purchase ) => PLAN_BUSINESS === purchase.productSlug );
};
86 changes: 86 additions & 0 deletions client/state/selectors/test/is-business-plan-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* External dependencies
*/
import { assert } from 'chai';
import deepFreeze from 'deep-freeze';

/**
* Internal dependencies
*/
import { isBusinessPlanUser } from '../';
import { PLAN_BUSINESS } from 'lib/plans/constants';

describe( 'isBusinessPlanUser()', () => {
it( 'should return true if any purchase is a business plan.', () => {
const state = deepFreeze( {
currentUser: {
id: 123,
},
purchases: {
data: [
{
user_id: '123',
product_slug: 'some-other-plan',
},
{
user_id: '123',
product_slug: PLAN_BUSINESS,
}
],
hasLoadedUserPurchasesFromServer: true,
},
} );

assert.isTrue( isBusinessPlanUser( state ) );
} );

it( 'should return false if non of the purchases is a business plan.', () => {
const state = deepFreeze( {
currentUser: {
id: 123,
},
purchases: {
data: [
{
user_id: '123',
product_slug: 'some-other-plan',
},
{
user_id: '123',
product_slug: 'yet-another-plan',
}
],
hasLoadedUserPurchasesFromServer: true,
},
} );

assert.isFalse( isBusinessPlanUser( state ) );
} );

it( 'should return false if current user id is null.', () => {
const state = deepFreeze( {
currentUser: {}
} );

assert.isFalse( isBusinessPlanUser( state ) );
} );

it( 'should return false if purchasing data is null.', () => {
const state = deepFreeze( {
currentUser: {
id: 123,
},
purchases: {
data: [
{ // intentionally put a purchase that doesn't belong to the user 123 here.
user_id: '789',
product_slug: PLAN_BUSINESS,
}
],
hasLoadedUserPurchasesFromServer: true,
},
} );

assert.isFalse( isBusinessPlanUser( state ) );
} );
} );