-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Changes from 7 commits
89307cd
585ee7d
337da43
9f0706b
d7345d4
20e9239
555ba80
89c6b3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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; | ||
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 ), | ||
} ), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This trailing comma doesn't cause a JS error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch, no it's not throwing an error for me and the linter is not complaining about it because it is a comma between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I always thought trailing commas only worked for arrays and I maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's standard for function calls, I mean |
||
)( localize( ChatBusinessConciergeNotice ) ); |
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 an boolean flag indicating if the current user is a business plan user. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Returns a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
* | ||
* @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 ); | ||
}; |
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 ) ); | ||
} ); | ||
} ); |
There was a problem hiding this comment.
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