Add additional question to CES modal (#35680)
This commit is contained in:
parent
cfffb27c45
commit
4db5c0d8cd
|
@ -0,0 +1,4 @@
|
|||
Significance: major
|
||||
Type: update
|
||||
|
||||
Updating to accept two questions to display in CES modal.
|
|
@ -14,8 +14,14 @@ import { CustomerFeedbackModal } from './customer-feedback-modal';
|
|||
const noop = () => {};
|
||||
|
||||
type CustomerEffortScoreProps = {
|
||||
recordScoreCallback: ( score: number, comments: string ) => void;
|
||||
label: string;
|
||||
recordScoreCallback: (
|
||||
score: number,
|
||||
secondScore: number,
|
||||
comments: string
|
||||
) => void;
|
||||
title: string;
|
||||
firstQuestion: string;
|
||||
secondQuestion: string;
|
||||
onNoticeShownCallback?: () => void;
|
||||
onNoticeDismissedCallback?: () => void;
|
||||
onModalShownCallback?: () => void;
|
||||
|
@ -30,7 +36,9 @@ type CustomerEffortScoreProps = {
|
|||
*
|
||||
* @param {Object} props Component props.
|
||||
* @param {Function} props.recordScoreCallback Function to call when the score should be recorded.
|
||||
* @param {string} props.label The label displayed in the modal.
|
||||
* @param {string} props.title The title displayed in the modal.
|
||||
* @param {string} props.firstQuestion The first survey question.
|
||||
* @param {string} props.secondQuestion The second survey question.
|
||||
* @param {Function} props.onNoticeShownCallback Function to call when the notice is shown.
|
||||
* @param {Function} props.onNoticeDismissedCallback Function to call when the notice is dismissed.
|
||||
* @param {Function} props.onModalShownCallback Function to call when the modal is shown.
|
||||
|
@ -38,7 +46,9 @@ type CustomerEffortScoreProps = {
|
|||
*/
|
||||
const CustomerEffortScore: React.VFC< CustomerEffortScoreProps > = ( {
|
||||
recordScoreCallback,
|
||||
label,
|
||||
title,
|
||||
firstQuestion,
|
||||
secondQuestion,
|
||||
onNoticeShownCallback = noop,
|
||||
onNoticeDismissedCallback = noop,
|
||||
onModalShownCallback = noop,
|
||||
|
@ -53,7 +63,7 @@ const CustomerEffortScore: React.VFC< CustomerEffortScoreProps > = ( {
|
|||
return;
|
||||
}
|
||||
|
||||
createNotice( 'success', label, {
|
||||
createNotice( 'success', title, {
|
||||
actions: [
|
||||
{
|
||||
label: __( 'Give feedback', 'woocommerce' ),
|
||||
|
@ -83,7 +93,9 @@ const CustomerEffortScore: React.VFC< CustomerEffortScoreProps > = ( {
|
|||
|
||||
return (
|
||||
<CustomerFeedbackModal
|
||||
label={ label }
|
||||
title={ title }
|
||||
firstQuestion={ firstQuestion }
|
||||
secondQuestion={ secondQuestion }
|
||||
recordScoreCallback={ recordScoreCallback }
|
||||
/>
|
||||
);
|
||||
|
@ -95,9 +107,9 @@ CustomerEffortScore.propTypes = {
|
|||
*/
|
||||
recordScoreCallback: PropTypes.func.isRequired,
|
||||
/**
|
||||
* The label displayed in the modal.
|
||||
* The title displayed in the modal.
|
||||
*/
|
||||
label: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
/**
|
||||
* The function to call when the notice is shown.
|
||||
*/
|
||||
|
|
|
@ -25,18 +25,28 @@ import { __ } from '@wordpress/i18n';
|
|||
*
|
||||
* @param {Object} props Component props.
|
||||
* @param {Function} props.recordScoreCallback Function to call when the results are sent.
|
||||
* @param {string} props.label Question to ask the customer.
|
||||
* @param {string} props.title Title displayed in the modal.
|
||||
* @param {string} props.firstQuestion The first survey question.
|
||||
* @param {string} props.secondQuestion The second survey question.
|
||||
* @param {string} props.defaultScore Default score.
|
||||
* @param {Function} props.onCloseModal Callback for when user closes modal by clicking cancel.
|
||||
*/
|
||||
function CustomerFeedbackModal( {
|
||||
recordScoreCallback,
|
||||
label,
|
||||
title,
|
||||
firstQuestion,
|
||||
secondQuestion,
|
||||
defaultScore = NaN,
|
||||
onCloseModal,
|
||||
}: {
|
||||
recordScoreCallback: ( score: number, comments: string ) => void;
|
||||
label: string;
|
||||
recordScoreCallback: (
|
||||
score: number,
|
||||
secondScore: number,
|
||||
comments: string
|
||||
) => void;
|
||||
title: string;
|
||||
firstQuestion: string;
|
||||
secondQuestion: string;
|
||||
defaultScore?: number;
|
||||
onCloseModal?: () => void;
|
||||
} ): JSX.Element | null {
|
||||
|
@ -63,7 +73,12 @@ function CustomerFeedbackModal( {
|
|||
},
|
||||
];
|
||||
|
||||
const [ score, setScore ] = useState( defaultScore || NaN );
|
||||
const [ firstQuestionScore, setFirstQuestionScore ] = useState(
|
||||
defaultScore || NaN
|
||||
);
|
||||
const [ secondQuestionScore, setSecondQuestionScore ] = useState(
|
||||
defaultScore || NaN
|
||||
);
|
||||
const [ comments, setComments ] = useState( '' );
|
||||
const [ showNoScoreMessage, setShowNoScoreMessage ] = useState( false );
|
||||
const [ isOpen, setOpen ] = useState( true );
|
||||
|
@ -75,19 +90,31 @@ function CustomerFeedbackModal( {
|
|||
}
|
||||
};
|
||||
|
||||
const onRadioControlChange = ( value: string ) => {
|
||||
const onRadioControlChange = (
|
||||
value: string,
|
||||
setter: ( val: number ) => void
|
||||
) => {
|
||||
const valueAsInt = parseInt( value, 10 );
|
||||
setScore( valueAsInt );
|
||||
setter( valueAsInt );
|
||||
setShowNoScoreMessage( ! Number.isInteger( valueAsInt ) );
|
||||
};
|
||||
|
||||
const sendScore = () => {
|
||||
if ( ! Number.isInteger( score ) ) {
|
||||
if (
|
||||
! (
|
||||
Number.isInteger( firstQuestionScore ) &&
|
||||
Number.isInteger( secondQuestionScore )
|
||||
)
|
||||
) {
|
||||
setShowNoScoreMessage( true );
|
||||
return;
|
||||
}
|
||||
setOpen( false );
|
||||
recordScoreCallback( score, comments );
|
||||
recordScoreCallback(
|
||||
firstQuestionScore,
|
||||
secondQuestionScore,
|
||||
comments
|
||||
);
|
||||
};
|
||||
|
||||
if ( ! isOpen ) {
|
||||
|
@ -97,10 +124,24 @@ function CustomerFeedbackModal( {
|
|||
return (
|
||||
<Modal
|
||||
className="woocommerce-customer-effort-score"
|
||||
title={ __( 'Please share your feedback', 'woocommerce' ) }
|
||||
title={ title }
|
||||
onRequestClose={ closeModal }
|
||||
shouldCloseOnClickOutside={ false }
|
||||
>
|
||||
<Text
|
||||
variant="body"
|
||||
as="p"
|
||||
className="woocommerce-customer-effort-score__intro"
|
||||
size={ 14 }
|
||||
lineHeight="20px"
|
||||
marginBottom="1.5em"
|
||||
>
|
||||
{ __(
|
||||
'Your feedback will help create a better experience for thousands of merchants like you. Please tell us to what extent you agree or disagree with the statements below.',
|
||||
'woocommerce'
|
||||
) }
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
variant="subtitle.small"
|
||||
as="p"
|
||||
|
@ -108,26 +149,63 @@ function CustomerFeedbackModal( {
|
|||
size="14"
|
||||
lineHeight="20px"
|
||||
>
|
||||
{ label }
|
||||
{ firstQuestion }
|
||||
</Text>
|
||||
|
||||
<div className="woocommerce-customer-effort-score__selection">
|
||||
<RadioControl
|
||||
selected={ score.toString( 10 ) }
|
||||
selected={ firstQuestionScore.toString( 10 ) }
|
||||
options={ options }
|
||||
onChange={ onRadioControlChange }
|
||||
onChange={ ( value ) =>
|
||||
onRadioControlChange(
|
||||
value as string,
|
||||
setFirstQuestionScore
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{ ( score === 1 || score === 2 ) && (
|
||||
<Text
|
||||
variant="subtitle.small"
|
||||
as="p"
|
||||
weight="600"
|
||||
size="14"
|
||||
lineHeight="20px"
|
||||
>
|
||||
{ secondQuestion }
|
||||
</Text>
|
||||
|
||||
<div className="woocommerce-customer-effort-score__selection">
|
||||
<RadioControl
|
||||
selected={ secondQuestionScore.toString( 10 ) }
|
||||
options={ options }
|
||||
onChange={ ( value ) =>
|
||||
onRadioControlChange(
|
||||
value as string,
|
||||
setSecondQuestionScore
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{ [ firstQuestionScore, secondQuestionScore ].some(
|
||||
( score ) => score === 1 || score === 2
|
||||
) && (
|
||||
<div className="woocommerce-customer-effort-score__comments">
|
||||
<TextareaControl
|
||||
label={ __( 'Comments (optional)', 'woocommerce' ) }
|
||||
label={ __(
|
||||
'How is that screen useful to you? What features would you add or change?',
|
||||
'woocommerce'
|
||||
) }
|
||||
help={ __(
|
||||
'Your feedback will go to the WooCommerce development team',
|
||||
'woocommerce'
|
||||
) }
|
||||
value={ comments }
|
||||
placeholder={ __(
|
||||
'Optional, but much apprecated. We love reading your feedback!',
|
||||
'woocommerce'
|
||||
) }
|
||||
onChange={ ( value: string ) => setComments( value ) }
|
||||
rows={ 5 }
|
||||
/>
|
||||
|
@ -153,7 +231,7 @@ function CustomerFeedbackModal( {
|
|||
{ __( 'Cancel', 'woocommerce' ) }
|
||||
</Button>
|
||||
<Button isPrimary onClick={ sendScore } name="send">
|
||||
{ __( 'Send', 'woocommerce' ) }
|
||||
{ __( 'Share', 'woocommerce' ) }
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
@ -162,7 +240,9 @@ function CustomerFeedbackModal( {
|
|||
|
||||
CustomerFeedbackModal.propTypes = {
|
||||
recordScoreCallback: PropTypes.func.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
firstQuestion: PropTypes.string.isRequired,
|
||||
secondQuestion: PropTypes.string.isRequired,
|
||||
defaultScore: PropTypes.number,
|
||||
onCloseModal: PropTypes.func,
|
||||
};
|
||||
|
|
|
@ -16,7 +16,9 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
title="Testing"
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -33,13 +35,15 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
title="Testing"
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
await screen.findByRole( 'dialog' ); // Wait for the modal to render.
|
||||
|
||||
fireEvent.click( screen.getByRole( 'button', { name: /send/i } ) ); // Press send button.
|
||||
fireEvent.click( screen.getByRole( 'button', { name: /share/i } ) ); // Press send button.
|
||||
|
||||
// Wait for error message.
|
||||
await screen.findByRole( 'alert' );
|
||||
|
@ -51,7 +55,9 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
title="Testing"
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -59,7 +65,9 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
await screen.findByRole( 'dialog' );
|
||||
|
||||
expect(
|
||||
screen.queryByLabelText( 'Comments (optional)' )
|
||||
screen.queryByLabelText(
|
||||
'How is that screen useful to you? What features would you add or change?'
|
||||
)
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
|
||||
|
@ -69,7 +77,9 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
render(
|
||||
<CustomerFeedbackModal
|
||||
recordScoreCallback={ mockRecordScoreCallback }
|
||||
label="Testing"
|
||||
title="Testing"
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -77,18 +87,22 @@ describe( 'CustomerFeedbackModal', () => {
|
|||
await screen.findByRole( 'dialog' );
|
||||
|
||||
// Select the option.
|
||||
fireEvent.click( screen.getByLabelText( labelText ) );
|
||||
fireEvent.click( screen.getAllByLabelText( labelText )[ 0 ] );
|
||||
|
||||
// Wait for comments field to show.
|
||||
await screen.findByLabelText( 'Comments (optional)' );
|
||||
await screen.findByLabelText(
|
||||
'How is that screen useful to you? What features would you add or change?'
|
||||
);
|
||||
|
||||
// Select neutral score.
|
||||
fireEvent.click( screen.getByLabelText( 'Neutral' ) );
|
||||
fireEvent.click( screen.getAllByLabelText( 'Neutral' )[ 0 ] );
|
||||
|
||||
// Wait for comments field to hide.
|
||||
await waitFor( () => {
|
||||
expect(
|
||||
screen.queryByLabelText( 'Comments (optional)' )
|
||||
screen.queryByLabelText(
|
||||
'How is that screen useful to you? What features would you add or change?'
|
||||
)
|
||||
).not.toBeInTheDocument();
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import 'customer-feedback-simple/customer-feedback-simple.scss';
|
||||
|
||||
.woocommerce-customer-effort-score__selection {
|
||||
margin: 1em 0;
|
||||
margin: 1em 0 1.5em 0;
|
||||
|
||||
.components-base-control__field {
|
||||
display: flex;
|
||||
|
@ -91,10 +91,14 @@
|
|||
}
|
||||
|
||||
.woocommerce-customer-effort-score__comments {
|
||||
margin-bottom: 1.5em;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
color: inherit;
|
||||
font-weight: bold;
|
||||
text-transform: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
|
@ -109,3 +113,8 @@
|
|||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-customer-effort-score .woocommerce-customer-effort-score__intro {
|
||||
max-width: 550px;
|
||||
margin: 0 0 1.5em 0;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,9 @@ describe( 'CustomerEffortScore', () => {
|
|||
render(
|
||||
<CustomerEffortScore
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
title={ 'title' }
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
onNoticeDismissedCallback={ noop }
|
||||
icon={ icon }
|
||||
/>
|
||||
|
@ -45,7 +47,7 @@ describe( 'CustomerEffortScore', () => {
|
|||
// Notice status.
|
||||
expect.any( String ),
|
||||
// Notice message.
|
||||
'label',
|
||||
'title',
|
||||
// Notice options.
|
||||
expect.objectContaining( {
|
||||
icon,
|
||||
|
@ -63,7 +65,9 @@ describe( 'CustomerEffortScore', () => {
|
|||
const { rerender } = render(
|
||||
<CustomerEffortScore
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
title={ 'title' }
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -71,7 +75,9 @@ describe( 'CustomerEffortScore', () => {
|
|||
rerender(
|
||||
<CustomerEffortScore
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label2' }
|
||||
title={ 'title2' }
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -82,7 +88,9 @@ describe( 'CustomerEffortScore', () => {
|
|||
render(
|
||||
<CustomerEffortScore
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
title={ 'title' }
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -121,7 +129,9 @@ describe( 'CustomerEffortScore', () => {
|
|||
render(
|
||||
<CustomerEffortScore
|
||||
recordScoreCallback={ noop }
|
||||
label={ 'label' }
|
||||
title={ 'title' }
|
||||
firstQuestion="First question"
|
||||
secondQuestion="Second question"
|
||||
onModalShownCallback={ mockOnModalShownCallback }
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -49,7 +49,9 @@ function CustomerEffortScoreTracksContainer( {
|
|||
<CustomerEffortScoreTracks
|
||||
key={ index }
|
||||
action={ item.action }
|
||||
label={ item.label }
|
||||
firstQuestion={ item.firstQuestion }
|
||||
secondQuestion={ item.secondQuestion }
|
||||
title={ item.title }
|
||||
onSubmitLabel={ item.onsubmit_label }
|
||||
trackProps={ item.props || {} }
|
||||
/>
|
||||
|
|
|
@ -22,7 +22,9 @@ const ALLOW_TRACKING_OPTION_NAME = 'woocommerce_allow_tracking';
|
|||
* @param {Object} props Component props.
|
||||
* @param {string} props.action The action name sent to Tracks.
|
||||
* @param {Object} props.trackProps Additional props sent to Tracks.
|
||||
* @param {string} props.label The label displayed in the modal.
|
||||
* @param {string} props.title The title displayed in the modal.
|
||||
* @param {string} props.firstQuestion The first survey question.
|
||||
* @param {string} props.secondQuestion The second survey question.
|
||||
* @param {string} props.onSubmitLabel The label displayed upon survey submission.
|
||||
* @param {Array} props.cesShownForActions The array of actions that the CES modal has been shown for.
|
||||
* @param {boolean} props.allowTracking Whether tracking is allowed or not.
|
||||
|
@ -34,7 +36,9 @@ const ALLOW_TRACKING_OPTION_NAME = 'woocommerce_allow_tracking';
|
|||
function CustomerEffortScoreTracks( {
|
||||
action,
|
||||
trackProps,
|
||||
label,
|
||||
title,
|
||||
firstQuestion,
|
||||
secondQuestion,
|
||||
onSubmitLabel = __( 'Thank you for your feedback!', 'woocommerce' ),
|
||||
cesShownForActions,
|
||||
allowTracking,
|
||||
|
@ -104,10 +108,12 @@ function CustomerEffortScoreTracks( {
|
|||
addActionToShownOption();
|
||||
};
|
||||
|
||||
const recordScore = ( score, comments ) => {
|
||||
const recordScore = ( score, secondScore, comments ) => {
|
||||
recordEvent( 'ces_feedback', {
|
||||
action,
|
||||
score,
|
||||
score_second_question: secondScore,
|
||||
score_combined: score + secondScore,
|
||||
comments: comments || '',
|
||||
store_age: storeAgeInWeeks,
|
||||
...trackProps,
|
||||
|
@ -118,7 +124,9 @@ function CustomerEffortScoreTracks( {
|
|||
return (
|
||||
<CustomerEffortScore
|
||||
recordScoreCallback={ recordScore }
|
||||
label={ label }
|
||||
title={ title }
|
||||
firstQuestion={ firstQuestion }
|
||||
secondQuestion={ secondQuestion }
|
||||
onNoticeShownCallback={ onNoticeShown }
|
||||
onNoticeDismissedCallback={ onNoticeDismissed }
|
||||
onModalShownCallback={ onModalShown }
|
||||
|
|
|
@ -23,25 +23,32 @@ export function setCesSurveyQueue( queue ) {
|
|||
/**
|
||||
* Add a new CES track to the state.
|
||||
*
|
||||
* @param {string} action action name for the survey
|
||||
* @param {string} label label for the snackback
|
||||
* @param {string} pageNow value of window.pagenow
|
||||
* @param {string} adminPage value of window.adminpage
|
||||
* @param {string} onsubmitLabel label for the snackback onsubmit
|
||||
* @param {Object} props object for optional props
|
||||
* @param {Object} args All arguments.
|
||||
* @param {string} args.action action name for the survey
|
||||
* @param {string} args.title title for the snackback
|
||||
* @param {string} args.firstQuestion first question for modal survey
|
||||
* @param {string} args.secondQuestion second question for modal survey
|
||||
* @param {string} args.pageNow value of window.pagenow
|
||||
* @param {string} args.adminPage value of window.adminpage
|
||||
* @param {string} args.onsubmitLabel label for the snackback onsubmit
|
||||
* @param {Object} args.props object for optional props
|
||||
*/
|
||||
export function addCesSurvey(
|
||||
export function addCesSurvey( {
|
||||
action,
|
||||
label,
|
||||
title,
|
||||
firstQuestion,
|
||||
secondQuestion,
|
||||
pageNow = window.pagenow,
|
||||
adminPage = window.adminpage,
|
||||
onsubmitLabel = undefined,
|
||||
props = {}
|
||||
) {
|
||||
props = {},
|
||||
} ) {
|
||||
return {
|
||||
type: TYPES.ADD_CES_SURVEY,
|
||||
action,
|
||||
label,
|
||||
title,
|
||||
firstQuestion,
|
||||
secondQuestion,
|
||||
pageNow,
|
||||
adminPage,
|
||||
onsubmit_label: onsubmitLabel,
|
||||
|
@ -53,26 +60,45 @@ export function addCesSurvey(
|
|||
* Add a new CES survey track for the pages in Analytics menu
|
||||
*/
|
||||
export function addCesSurveyForAnalytics() {
|
||||
return addCesSurvey(
|
||||
'analytics_filtered',
|
||||
__( 'How easy was it to filter your store analytics?', 'woocommerce' ),
|
||||
'woocommerce_page_wc-admin',
|
||||
'woocommerce_page_wc-admin'
|
||||
);
|
||||
return addCesSurvey( {
|
||||
action: 'analytics_filtered',
|
||||
title: __(
|
||||
'How easy was it to filter your store analytics?',
|
||||
'woocommerce'
|
||||
),
|
||||
firstQuestion: __(
|
||||
'The filters in the analytics screen are easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
secondQuestion: __(
|
||||
`The filters' functionality meets my needs.`,
|
||||
'woocommerce'
|
||||
),
|
||||
pageNow: 'woocommerce_page_wc-admin',
|
||||
adminPage: 'woocommerce_page_wc-admin',
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new CES survey track on searching customers.
|
||||
*/
|
||||
export function addCesSurveyForCustomerSearch() {
|
||||
return addCesSurvey(
|
||||
'ces_search',
|
||||
__( 'How easy was it to use search?', 'woocommerce' ),
|
||||
'woocommerce_page_wc-admin',
|
||||
'woocommerce_page_wc-admin',
|
||||
undefined,
|
||||
{
|
||||
return addCesSurvey( {
|
||||
action: 'ces_search',
|
||||
title: __( 'How easy was it to use search?', 'woocommerce' ),
|
||||
firstQuestion: __(
|
||||
'The search feature in WooCommerce is easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
secondQuestion: __(
|
||||
`The search's functionality meets my needs.`,
|
||||
'woocommerce'
|
||||
),
|
||||
pageNow: 'woocommerce_page_wc-admin',
|
||||
adminPage: 'woocommerce_page_wc-admin',
|
||||
onsubmit_label: undefined,
|
||||
props: {
|
||||
search_area: 'customer',
|
||||
}
|
||||
);
|
||||
},
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -24,7 +24,9 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
|
|||
}
|
||||
const newTrack = {
|
||||
action: action.action,
|
||||
label: action.label,
|
||||
title: action.title,
|
||||
firstQuestion: action.firstQuestion,
|
||||
secondQuestion: action.secondQuestion,
|
||||
pagenow: action.pageNow,
|
||||
adminpage: action.adminPage,
|
||||
onSubmitLabel: action.onSubmitLabel,
|
||||
|
|
|
@ -97,10 +97,20 @@ export const TaskListCompletedHeader: React.FC<
|
|||
}
|
||||
}, [ hasSubmittedScore ] );
|
||||
|
||||
const submitScore = ( recordedScore: number, comments?: string ) => {
|
||||
const submitScore = ( {
|
||||
firstScore,
|
||||
secondScore,
|
||||
comments,
|
||||
}: {
|
||||
firstScore: number;
|
||||
secondScore?: number;
|
||||
comments?: string;
|
||||
} ) => {
|
||||
recordEvent( 'ces_feedback', {
|
||||
action: CUSTOMER_EFFORT_SCORE_ACTION,
|
||||
score: recordedScore,
|
||||
score: firstScore,
|
||||
score_second_question: secondScore ?? null,
|
||||
score_combined: firstScore + ( secondScore ?? 0 ),
|
||||
comments: comments || '',
|
||||
store_age: storeAgeInWeeks,
|
||||
} );
|
||||
|
@ -116,7 +126,7 @@ export const TaskListCompletedHeader: React.FC<
|
|||
const recordScore = ( recordedScore: number ) => {
|
||||
if ( recordedScore > 2 ) {
|
||||
setScore( recordedScore );
|
||||
submitScore( recordedScore );
|
||||
submitScore( { firstScore: recordedScore } );
|
||||
} else {
|
||||
setScore( recordedScore );
|
||||
setShowCesModal( true );
|
||||
|
@ -127,9 +137,13 @@ export const TaskListCompletedHeader: React.FC<
|
|||
}
|
||||
};
|
||||
|
||||
const recordModalScore = ( recordedScore: number, comments: string ) => {
|
||||
const recordModalScore = (
|
||||
firstScore: number,
|
||||
secondScore: number,
|
||||
comments: string
|
||||
) => {
|
||||
setShowCesModal( false );
|
||||
submitScore( recordedScore, comments );
|
||||
submitScore( { firstScore, secondScore, comments } );
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -230,7 +244,15 @@ export const TaskListCompletedHeader: React.FC<
|
|||
</div>
|
||||
{ showCesModal ? (
|
||||
<CustomerFeedbackModal
|
||||
label={ __( 'How was your experience?', 'woocommerce' ) }
|
||||
title={ __( 'How was your experience?', 'woocommerce' ) }
|
||||
firstQuestion={ __(
|
||||
'The store setup is easy to complete.',
|
||||
'woocommerce'
|
||||
) }
|
||||
secondQuestion={ __(
|
||||
'The store setup process meets my needs.',
|
||||
'woocommerce'
|
||||
) }
|
||||
defaultScore={ score }
|
||||
recordScoreCallback={ recordModalScore }
|
||||
onCloseModal={ () => {
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Updating all CES events to support two questions in modal.
|
|
@ -142,11 +142,13 @@ class CustomerEffortScoreTracks {
|
|||
* an increase of the number of rows in tags table
|
||||
*
|
||||
* @param string $action Action name for the survey.
|
||||
* @param string $label Label for the snackbar.
|
||||
* @param string $title Title for the snackbar.
|
||||
* @param string $first_question The text for the first question.
|
||||
* @param string $second_question The text for the second question.
|
||||
*
|
||||
* @return string Generated JavaScript to append to page.
|
||||
*/
|
||||
private function get_script_track_edit_php( $action, $label ) {
|
||||
private function get_script_track_edit_php( $action, $title, $first_question, $second_question ) {
|
||||
return sprintf(
|
||||
"(function( $ ) {
|
||||
'use strict';
|
||||
|
@ -158,7 +160,7 @@ class CustomerEffortScoreTracks {
|
|||
if ( $('.tags tbody > tr').length > initialCount ) {
|
||||
// New tag detected.
|
||||
clearInterval( interval );
|
||||
wp.data.dispatch('wc/customer-effort-score').addCesSurvey( '%s', '%s', window.pagenow, window.adminpage, '%s' );
|
||||
wp.data.dispatch('wc/customer-effort-score').addCesSurvey({ action: '%s', title: '%s', firstQuestion: '%s', secondQuestion: '%s', onsubmitLabel: '%s' });
|
||||
} else {
|
||||
// Form is no longer loading, most likely failed.
|
||||
if ( $( '#addtag .submit .spinner.is-active' ).length < 1 ) {
|
||||
|
@ -169,7 +171,9 @@ class CustomerEffortScoreTracks {
|
|||
});
|
||||
})( jQuery );",
|
||||
esc_js( $action ),
|
||||
esc_js( $label ),
|
||||
esc_js( $title ),
|
||||
esc_js( $first_question ),
|
||||
esc_js( $second_question ),
|
||||
esc_js( $this->onsubmit_label )
|
||||
);
|
||||
}
|
||||
|
@ -271,10 +275,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::SEARCH_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to use search?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'The search feature in WooCommerce is easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'The search\'s functionality meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => $page_now,
|
||||
'adminpage' => $admin_page,
|
||||
|
@ -337,10 +349,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::PRODUCT_ADD_PUBLISH_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to add a product?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'The product creation screen is easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'The product creation screen\'s functionality meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => 'product',
|
||||
'adminpage' => 'post-php',
|
||||
|
@ -362,10 +382,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::PRODUCT_UPDATE_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to edit your product?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'The product update process is easy to complete.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'The product update process meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => 'product',
|
||||
'adminpage' => 'post-php',
|
||||
|
@ -387,10 +415,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::SHOP_ORDER_UPDATE_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to update an order?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'The order details screen is easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'The order details screen\'s functionality meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => 'shop_order',
|
||||
'adminpage' => 'post-php',
|
||||
|
@ -447,7 +483,9 @@ class CustomerEffortScoreTracks {
|
|||
wc_enqueue_js(
|
||||
$this->get_script_track_edit_php(
|
||||
self::ADD_PRODUCT_CATEGORIES_ACTION_NAME,
|
||||
__( 'How easy was it to add product category?', 'woocommerce' )
|
||||
__( 'How easy was it to add product category?', 'woocommerce' ),
|
||||
__( 'The product category details screen is easy to use.', 'woocommerce' ),
|
||||
__( "The product category details screen's functionality meets my needs.", 'woocommerce' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -463,7 +501,9 @@ class CustomerEffortScoreTracks {
|
|||
wc_enqueue_js(
|
||||
$this->get_script_track_edit_php(
|
||||
self::ADD_PRODUCT_TAGS_ACTION_NAME,
|
||||
__( 'How easy was it to add a product tag?', 'woocommerce' )
|
||||
__( 'How easy was it to add a product tag?', 'woocommerce' ),
|
||||
__( 'The product tag details screen is easy to use.', 'woocommerce' ),
|
||||
__( "The product tag details screen's functionality meets my needs.", 'woocommerce' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -484,10 +524,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::IMPORT_PRODUCTS_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to import products?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'The product import process is easy to complete.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'The product import process meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => 'product_page_product_importer',
|
||||
'adminpage' => 'product_page_product_importer',
|
||||
|
@ -519,10 +567,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::SETTINGS_CHANGE_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to update your settings?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'The settings screen is easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'The settings screen\'s functionality meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => 'woocommerce_page_wc-settings',
|
||||
'adminpage' => 'woocommerce_page_wc-settings',
|
||||
|
@ -542,10 +598,18 @@ class CustomerEffortScoreTracks {
|
|||
$this->enqueue_to_ces_tracks(
|
||||
array(
|
||||
'action' => self::ADD_PRODUCT_ATTRIBUTES_ACTION_NAME,
|
||||
'label' => __(
|
||||
'title' => __(
|
||||
'How easy was it to add a product attribute?',
|
||||
'woocommerce'
|
||||
),
|
||||
'firstQuestion' => __(
|
||||
'Product attributes are easy to use.',
|
||||
'woocommerce'
|
||||
),
|
||||
'secondQuestion' => __(
|
||||
'Product attributes\' functionality meets my needs.',
|
||||
'woocommerce'
|
||||
),
|
||||
'onsubmit_label' => $this->onsubmit_label,
|
||||
'pagenow' => 'product_page_product_attributes',
|
||||
'adminpage' => 'product_page_product_attributes',
|
||||
|
|
Loading…
Reference in New Issue