From 16af2f34102cc36ccb50b027d692c394108d36de Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Wed, 17 May 2023 13:52:00 +0000 Subject: [PATCH 1/7] Revert "Revert "Support chat using Zendesk Messaging (#76777)" (#77016)" This reverts commit 693705b1eb1b9231158017e8feb4f501b7950469. --- .../help-center/class-help-center.php | 4 + ...class-wp-rest-help-center-authenticate.php | 25 +++- ...-rest-help-center-support-availability.php | 41 ++++++ .../class-wp-rest-help-center-user-fields.php | 75 +++++++++++ .../help-center/src/config.js | 5 +- apps/happychat/src/index.ejs | 2 +- .../presales-zendesk-chat/index.tsx | 8 +- client/me/happychat/index.jsx | 20 +-- config/_shared.json | 1 + config/development.json | 3 +- config/production.json | 1 + config/stage.json | 1 + config/wpcalypso.json | 3 +- .../data-stores/src/help-center/actions.ts | 16 +++ .../data-stores/src/help-center/reducer.ts | 21 ++++ .../data-stores/src/help-center/selectors.ts | 2 + packages/data-stores/src/index.ts | 3 +- .../data-stores/src/support-queries/types.ts | 1 + .../support-queries/use-support-history.ts | 8 +- .../use-update-zendesk-user-fields.ts | 29 +++++ .../components/help-center-contact-form.tsx | 37 +++++- .../components/help-center-contact-page.tsx | 19 +-- .../src/components/help-center-container.tsx | 23 +--- .../src/components/help-center-search.scss | 11 ++ ...help-center-third-party-cookies-notice.tsx | 46 +++++++ .../src/components/help-center.tsx | 117 ++++++++++++++---- .../help-center/src/components/types.d.ts | 5 + .../src/hooks/use-messaging-auth.ts | 40 ++++++ .../src/hooks/use-messaging-availability.ts | 47 +++++++ .../hooks/use-should-render-chat-option.tsx | 16 +-- .../src/hooks/use-zendesk-config.ts | 19 +++ packages/help-center/src/index.ts | 1 - packages/help-center/src/types.ts | 10 ++ 33 files changed, 557 insertions(+), 103 deletions(-) create mode 100644 apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-user-fields.php create mode 100644 packages/data-stores/src/support-queries/use-update-zendesk-user-fields.ts create mode 100644 packages/help-center/src/components/help-center-third-party-cookies-notice.tsx create mode 100644 packages/help-center/src/hooks/use-messaging-auth.ts create mode 100644 packages/help-center/src/hooks/use-messaging-availability.ts create mode 100644 packages/help-center/src/hooks/use-zendesk-config.ts diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php index 42aab9f212f15..308479703c651 100644 --- a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php @@ -210,6 +210,10 @@ public function register_rest_api() { require_once __DIR__ . '/class-wp-rest-help-center-support-history.php'; $controller = new WP_REST_Help_Center_Support_History(); $controller->register_rest_route(); + + require_once __DIR__ . '/class-wp-rest-help-center-user-fields.php'; + $controller = new WP_REST_Help_Center_User_Fields(); + $controller->register_rest_route(); } /** * Returns true if the current site is a support site. diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-authenticate.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-authenticate.php index 44976558f3bb2..c47826d21d5f5 100644 --- a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-authenticate.php +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-authenticate.php @@ -32,16 +32,37 @@ public function register_rest_route() { 'methods' => \WP_REST_Server::CREATABLE, 'callback' => array( $this, 'get_chat_authentication' ), 'permission_callback' => array( $this, 'permission_callback' ), + 'args' => array( + 'type' => array( + 'type' => 'string', + 'default' => 'happychat', + 'required' => false, + ), + 'test_mode' => array( + 'type' => 'boolean', + 'default' => false, + 'required' => false, + ), + ), ) ); } /** * Callback to authorize user for chat. + * + * @param \WP_REST_Request $request The request sent to the API. + * + * @return WP_REST_Response */ - public function get_chat_authentication() { + public function get_chat_authentication( \WP_REST_Request $request ) { + $query_parameters = array( + 'test_mode' => $request['test_mode'], + 'type' => $request['type'], + ); + $body = Client::wpcom_json_api_request_as_user( - 'help/authenticate/chat', + 'help/authenticate/chat?' . http_build_query( $query_parameters ), '2', array( 'method' => 'POST', diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-availability.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-availability.php index c2817c86dfed2..43df6f3a6d25d 100644 --- a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-availability.php +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-availability.php @@ -44,6 +44,26 @@ public function register_rest_route() { 'permission_callback' => array( $this, 'permission_callback' ), ) ); + + register_rest_route( + $this->namespace, + $this->rest_base . '/messaging', + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_messaging_support_eligibility' ), + 'permission_callback' => array( $this, 'permission_callback' ), + 'args' => array( + 'group' => array( + 'type' => 'string', + 'required' => true, + ), + 'environment' => array( + 'type' => 'string', + 'required' => true, + ), + ), + ) + ); } /** @@ -88,6 +108,27 @@ public function get_all_support_eligibility() { return rest_ensure_response( $response ); } + /** + * Should return messaging eligibility + * + * @param \WP_REST_Request $request The request sent to the API. + * + * @return WP_REST_Response + */ + public function get_messaging_support_eligibility( \WP_REST_Request $request ) { + $query_parameters = array( + 'group' => $request['group'], + 'environment' => $request['environment'], + ); + $body = Client::wpcom_json_api_request_as_user( 'help/messaging/is-available?' . http_build_query( $query_parameters ) ); + if ( is_wp_error( $body ) ) { + return $body; + } + $response = json_decode( wp_remote_retrieve_body( $body ) ); + + return rest_ensure_response( $response ); + } + /** * Callback to determine whether the request can proceed. * diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-user-fields.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-user-fields.php new file mode 100644 index 0000000000000..e14a16efb5c28 --- /dev/null +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-user-fields.php @@ -0,0 +1,75 @@ +namespace = 'help-center'; + $this->rest_base = '/zendesk/user-fields'; + } + + /** + * Register available routes. + */ + public function register_rest_route() { + register_rest_route( + $this->namespace, + $this->rest_base, + array( + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'update_user_fields' ), + 'permission_callback' => array( $this, 'permission_callback' ), + 'args' => array( + 'fields' => array( + 'type' => 'object', + 'required' => true, + ), + ), + ) + ); + } + + /** + * Callback to update user fields in Zendesk + * + * @param \WP_REST_Request $request The request sent to the API. + * + * @return WP_REST_Response + */ + public function update_user_fields( \WP_REST_Request $request ) { + $body = Client::wpcom_json_api_request_as_user( + 'help/zendesk/update-user-fields', + '2', + array( + 'method' => 'POST', + ), + $request['fields'] + ); + + if ( is_wp_error( $body ) ) { + return $body; + } + $response = json_decode( wp_remote_retrieve_body( $body ) ); + return rest_ensure_response( $response ); + } + + /** + * Callback to determine whether the user has permission to access. + */ + public function permission_callback() { + return is_user_logged_in(); + } +} diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/src/config.js b/apps/editing-toolkit/editing-toolkit-plugin/help-center/src/config.js index 10c344ff98457..ab1ac348b0a45 100644 --- a/apps/editing-toolkit/editing-toolkit-plugin/help-center/src/config.js +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/src/config.js @@ -1,7 +1,8 @@ window.configData = { - env_id: 'development', + env_id: 'production', i18n_default_locale_slug: 'en', google_analytics_key: 'UA-10673494-15', + zendesk_support_chat_key: 'cec07bc9-4da6-4dd2-afa7-c7e01ae73584', client_slug: 'browser', twemoji_cdn_url: 'https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/', site_filter: [], @@ -39,7 +40,7 @@ window.configData = { is_running_in_jetpack_site: false, gutenboarding_url: '/new', features: { - happychat: true, + happychat: false, }, signup_url: '/', discover_blog_id: 53424024, diff --git a/apps/happychat/src/index.ejs b/apps/happychat/src/index.ejs index b7864cf30b271..48853f0fa109b 100644 --- a/apps/happychat/src/index.ejs +++ b/apps/happychat/src/index.ejs @@ -39,7 +39,7 @@ gutenboarding_url: '/new', hostname: 'widgets.wp.com', features: { - happychat: true, + happychat: false, }, }; diff --git a/client/components/presales-zendesk-chat/index.tsx b/client/components/presales-zendesk-chat/index.tsx index 222ad05acf09e..66a5dbc0316fb 100644 --- a/client/components/presales-zendesk-chat/index.tsx +++ b/client/components/presales-zendesk-chat/index.tsx @@ -5,16 +5,22 @@ interface Props { chatKey: string | false; } +const ZENDESK_SCRIPT_ID = 'ze-snippet'; + const ZendeskChat = ( { chatKey }: Props ) => { useEffect( () => { if ( ! chatKey ) { return; } + if ( document.getElementById( ZENDESK_SCRIPT_ID ) ) { + return; + } + loadScript( 'https://static.zdassets.com/ekr/snippet.js?key=' + encodeURIComponent( chatKey ), undefined, - { id: 'ze-snippet' } + { id: ZENDESK_SCRIPT_ID } ); }, [ chatKey ] ); diff --git a/client/me/happychat/index.jsx b/client/me/happychat/index.jsx index e956131b35831..91cb06715c3ea 100644 --- a/client/me/happychat/index.jsx +++ b/client/me/happychat/index.jsx @@ -1,25 +1,11 @@ -import config from '@automattic/calypso-config'; -import { translate } from 'i18n-calypso'; import page from 'page'; import { makeLayout, render as clientRender } from 'calypso/controller'; -import PageViewTracker from 'calypso/lib/analytics/page-view-tracker'; import { sidebar } from 'calypso/me/controller'; -import { setDocumentHeadTitle } from 'calypso/state/document-head/actions'; -import Happychat from './main'; -const renderChat = ( context, next ) => { - context.store.dispatch( setDocumentHeadTitle( translate( 'Chat', { textOnly: true } ) ) ); - context.primary = ( -
- - -
- ); - next(); +const redirectToHelp = () => { + page.redirect( '/help' ); }; export default () => { - if ( config.isEnabled( 'happychat' ) ) { - page( '/me/chat', sidebar, renderChat, makeLayout, clientRender ); - } + page( '/me/chat', sidebar, redirectToHelp, makeLayout, clientRender ); }; diff --git a/config/_shared.json b/config/_shared.json index a21649b25e498..a329bd0d725fe 100644 --- a/config/_shared.json +++ b/config/_shared.json @@ -39,6 +39,7 @@ "zendesk_presales_chat_key_akismet": false, "zendesk_presales_chat_key_jp_checkout": false, "zendesk_presales_chat_key_jp_agency_dashboard": false, + "zendesk_support_chat_key": false, "upwork_support_locales": [ "de", "de-at", diff --git a/config/development.json b/config/development.json index 691014994e075..9a167004e5e7b 100644 --- a/config/development.json +++ b/config/development.json @@ -27,6 +27,7 @@ "zendesk_presales_chat_key": "216bf91d-f10f-4f66-bf65-a0cba220cd38", "zendesk_presales_chat_key_akismet": "7ce13115-7b34-4069-9d64-228d90f148d1", "zendesk_presales_chat_key_jp_checkout": "7c42153f-f579-49ba-a33e-246b2d27fb93", + "zendesk_support_chat_key": "cec07bc9-4da6-4dd2-afa7-c7e01ae73584", "features": { "ad-tracking": false, "akismet/siteless-checkout": true, @@ -68,7 +69,7 @@ "google-drive": true, "google-my-business": true, "gutenboarding/alpha-templates": false, - "happychat": true, + "happychat": false, "help": true, "help/gpt-response": true, "home/layout-dev": true, diff --git a/config/production.json b/config/production.json index 00b5341935d1e..ca5f02dfefb6e 100644 --- a/config/production.json +++ b/config/production.json @@ -17,6 +17,7 @@ "zendesk_presales_chat_key": "216bf91d-f10f-4f66-bf65-a0cba220cd38", "zendesk_presales_chat_key_akismet": "7ce13115-7b34-4069-9d64-228d90f148d1", "zendesk_presales_chat_key_jp_checkout": "7c42153f-f579-49ba-a33e-246b2d27fb93", + "zendesk_support_chat_key": "cec07bc9-4da6-4dd2-afa7-c7e01ae73584", "features": { "ad-tracking": true, "akismet/siteless-checkout": true, diff --git a/config/stage.json b/config/stage.json index c28fd1e4b76a8..d94bccf04738e 100644 --- a/config/stage.json +++ b/config/stage.json @@ -15,6 +15,7 @@ "zendesk_presales_chat_key": "216bf91d-f10f-4f66-bf65-a0cba220cd38", "zendesk_presales_chat_key_akismet": "7ce13115-7b34-4069-9d64-228d90f148d1", "zendesk_presales_chat_key_jp_checkout": "7c42153f-f579-49ba-a33e-246b2d27fb93", + "zendesk_support_chat_key": "cec07bc9-4da6-4dd2-afa7-c7e01ae73584", "features": { "ad-tracking": false, "akismet/siteless-checkout": true, diff --git a/config/wpcalypso.json b/config/wpcalypso.json index 6e04856462ef7..311ee4c8bb06b 100644 --- a/config/wpcalypso.json +++ b/config/wpcalypso.json @@ -15,6 +15,7 @@ "zendesk_presales_chat_key": "216bf91d-f10f-4f66-bf65-a0cba220cd38", "zendesk_presales_chat_key_akismet": "7ce13115-7b34-4069-9d64-228d90f148d1", "zendesk_presales_chat_key_jp_checkout": "7c42153f-f579-49ba-a33e-246b2d27fb93", + "zendesk_support_chat_key": "cec07bc9-4da6-4dd2-afa7-c7e01ae73584", "features": { "ad-tracking": false, "akismet/siteless-checkout": true, @@ -50,7 +51,7 @@ "cookie-banner": true, "google-my-business": true, "gutenboarding/alpha-templates": false, - "happychat": true, + "happychat": false, "help": true, "help/gpt-response": true, "home/layout-dev": true, diff --git a/packages/data-stores/src/help-center/actions.ts b/packages/data-stores/src/help-center/actions.ts index ac06d0e2876bc..6f6f9314f6cb4 100644 --- a/packages/data-stores/src/help-center/actions.ts +++ b/packages/data-stores/src/help-center/actions.ts @@ -61,10 +61,24 @@ export const setIsMinimized = ( minimized: boolean ) => minimized, } as const ); +export const setShowMessagingLauncher = ( show: boolean ) => + ( { + type: 'HELP_CENTER_SET_SHOW_MESSAGING_LAUNCHER', + show, + } as const ); + +export const setShowMessagingWidget = ( show: boolean ) => + ( { + type: 'HELP_CENTER_SET_SHOW_MESSAGING_WIDGET', + show, + } as const ); + export const setShowHelpCenter = function* ( show: boolean ) { if ( ! show ) { yield setInitialRoute( undefined ); yield setIsMinimized( false ); + } else { + yield setShowMessagingWidget( false ); } return { @@ -128,6 +142,8 @@ export const resetStore = () => export type HelpCenterAction = | ReturnType< + | typeof setShowMessagingLauncher + | typeof setShowMessagingWidget | typeof setSite | typeof setSubject | typeof resetStore diff --git a/packages/data-stores/src/help-center/reducer.ts b/packages/data-stores/src/help-center/reducer.ts index f4596b6035abf..292df98dda622 100644 --- a/packages/data-stores/src/help-center/reducer.ts +++ b/packages/data-stores/src/help-center/reducer.ts @@ -13,6 +13,25 @@ const showHelpCenter: Reducer< boolean | undefined, HelpCenterAction > = ( state return state; }; +const showMessagingLauncher: Reducer< boolean | undefined, HelpCenterAction > = ( + state, + action +) => { + switch ( action.type ) { + case 'HELP_CENTER_SET_SHOW_MESSAGING_LAUNCHER': + return action.show; + } + return state; +}; + +const showMessagingWidget: Reducer< boolean | undefined, HelpCenterAction > = ( state, action ) => { + switch ( action.type ) { + case 'HELP_CENTER_SET_SHOW_MESSAGING_WIDGET': + return action.show; + } + return state; +}; + const hasSeenWhatsNewModal: Reducer< boolean | undefined, HelpCenterAction > = ( state, action @@ -119,6 +138,8 @@ const initialRoute: Reducer< InitialEntry | undefined, HelpCenterAction > = ( st const reducer = combineReducers( { showHelpCenter, + showMessagingLauncher, + showMessagingWidget, site, subject, message, diff --git a/packages/data-stores/src/help-center/selectors.ts b/packages/data-stores/src/help-center/selectors.ts index d40f8d0873d1f..ec439d44333cf 100644 --- a/packages/data-stores/src/help-center/selectors.ts +++ b/packages/data-stores/src/help-center/selectors.ts @@ -1,6 +1,8 @@ import type { State } from './reducer'; export const isHelpCenterShown = ( state: State ) => state.showHelpCenter; +export const isMessagingLauncherShown = ( state: State ) => state.showMessagingLauncher; +export const isMessagingWidgetShown = ( state: State ) => state.showMessagingWidget; export const getSite = ( state: State ) => state.site; export const getSubject = ( state: State ) => state.subject; export const getMessage = ( state: State ) => state.message; diff --git a/packages/data-stores/src/index.ts b/packages/data-stores/src/index.ts index 7a0f14619cde9..e6a782454ca55 100644 --- a/packages/data-stores/src/index.ts +++ b/packages/data-stores/src/index.ts @@ -21,7 +21,8 @@ export { useSiteIntent } from './queries/use-site-intent'; export { useSupportAvailability } from './support-queries/use-support-availability'; export { useSubmitTicketMutation } from './support-queries/use-submit-support-ticket'; export { useSubmitForumsMutation } from './support-queries/use-submit-forums-topic'; -export { useHasActiveSupport } from './support-queries/use-support-history'; +export { useUpdateZendeskUserFieldsMutation } from './support-queries/use-update-zendesk-user-fields'; +export { useSupportHistory } from './support-queries/use-support-history'; export * from './starter-designs-queries'; export * from './support-queries/types'; export * from './site/types'; diff --git a/packages/data-stores/src/support-queries/types.ts b/packages/data-stores/src/support-queries/types.ts index b32367d6d6bab..75a3cdee18159 100644 --- a/packages/data-stores/src/support-queries/types.ts +++ b/packages/data-stores/src/support-queries/types.ts @@ -36,4 +36,5 @@ export interface SupportSession { type: string; url: string; when: string; + channel: string; } diff --git a/packages/data-stores/src/support-queries/use-support-history.ts b/packages/data-stores/src/support-queries/use-support-history.ts index 0d5ff4707ca55..884169fe627d7 100644 --- a/packages/data-stores/src/support-queries/use-support-history.ts +++ b/packages/data-stores/src/support-queries/use-support-history.ts @@ -14,7 +14,7 @@ const ACTIVE_STATUSES = [ 'New', 'Open', 'Hold' ]; * * NOTE: Chat mode isn't functional at the moment. */ -export function useHasActiveSupport( type: 'chat' | 'ticket', email: string, show = true ) { +export function useSupportHistory( type: 'chat' | 'ticket', email: string, show = true ) { return useQuery( [ 'help-support-history', type, email ], () => @@ -37,10 +37,12 @@ export function useHasActiveSupport( type: 'chat' | 'ticket', email: string, sho refetchOnMount: true, enabled: show, select: ( response ) => { - const recentSession = response.data[ 0 ]; - return ACTIVE_STATUSES.includes( recentSession.status ) ? recentSession : null; + return response.data.filter( ( session ) => ACTIVE_STATUSES.includes( session.status ) ); }, staleTime: 30 * 60 * 1000, + meta: { + persist: false, + }, } ); } diff --git a/packages/data-stores/src/support-queries/use-update-zendesk-user-fields.ts b/packages/data-stores/src/support-queries/use-update-zendesk-user-fields.ts new file mode 100644 index 0000000000000..82082face3241 --- /dev/null +++ b/packages/data-stores/src/support-queries/use-update-zendesk-user-fields.ts @@ -0,0 +1,29 @@ +import { useMutation } from '@tanstack/react-query'; +import apiFetch, { APIFetchOptions } from '@wordpress/api-fetch'; +import wpcomRequest, { canAccessWpcomApis } from 'wpcom-proxy-request'; + +type ZendeskUserFields = { + messaging_initial_message?: string; + messaging_plan?: string; + messaging_source?: string; + messaging_url?: string; +}; + +export function useUpdateZendeskUserFieldsMutation() { + return useMutation( ( userFields: ZendeskUserFields ) => { + return canAccessWpcomApis() + ? wpcomRequest( { + path: 'help/zendesk/update-user-fields', + apiNamespace: 'wpcom/v2/', + apiVersion: '2', + method: 'POST', + body: { fields: userFields }, + } ) + : apiFetch( { + global: true, + path: '/help-center/ticket/new', + method: 'POST', + data: { fields: userFields }, + } as APIFetchOptions ); + } ); +} diff --git a/packages/help-center/src/components/help-center-contact-form.tsx b/packages/help-center/src/components/help-center-contact-form.tsx index 490ec50abfc95..4f1417c873207 100644 --- a/packages/help-center/src/components/help-center-contact-form.tsx +++ b/packages/help-center/src/components/help-center-contact-form.tsx @@ -9,12 +9,14 @@ import { FormInputValidation, Popover } from '@automattic/components'; import { useSubmitTicketMutation, useSubmitForumsMutation, + useUpdateZendeskUserFieldsMutation, useSiteAnalysis, useUserSites, AnalysisReport, SiteDetails, HelpCenterSite, useJetpackSearchAIQuery, + useSupportAvailability, } from '@automattic/data-stores'; import { useLocale } from '@automattic/i18n-utils'; import { SitePickerDropDown, SitePickerSite } from '@automattic/site-picker'; @@ -35,6 +37,7 @@ import { getSectionName } from 'calypso/state/ui/selectors'; /** * Internal Dependencies */ +import useZendeskConfig from '../hooks/use-zendesk-config'; import { HELP_CENTER_STORE } from '../stores'; import { getSupportVariationFromMode } from '../support-variations'; import { SitePicker } from '../types'; @@ -42,6 +45,7 @@ import { BackButton } from './back-button'; import { HelpCenterGPT } from './help-center-gpt'; import { HelpCenterOwnershipNotice } from './help-center-notice'; import HelpCenterSearchResults from './help-center-search-results'; +import ThirdPartyCookiesNotice from './help-center-third-party-cookies-notice'; import type { HelpCenterSelect } from '@automattic/data-stores'; import './help-center-contact-form.scss'; @@ -160,6 +164,8 @@ export const HelpCenterContactForm = () => { const locale = useLocale(); const { isLoading: submittingTicket, mutateAsync: submitTicket } = useSubmitTicketMutation(); const { isLoading: submittingTopic, mutateAsync: submitTopic } = useSubmitForumsMutation(); + const { isLoading: submittingZendeskUserFields, mutateAsync: submitZendeskUserFields } = + useUpdateZendeskUserFieldsMutation(); const userId = useSelector( getCurrentUserId ); const { data: userSites } = useUserSites( userId ); const userWithNoSites = userSites?.sites.length === 0; @@ -185,8 +191,14 @@ export const HelpCenterContactForm = () => { setUserDeclaredSite, setSubject, setMessage, + setShowHelpCenter, + setShowMessagingLauncher, + setShowMessagingWidget, } = useDispatch( HELP_CENTER_STORE ); + const { data: chatStatus } = useSupportAvailability( 'CHAT' ); + const { status: zendeskStatus } = useZendeskConfig( Boolean( chatStatus?.is_user_eligible ) ); + useEffect( () => { const supportVariation = getSupportVariationFromMode( mode ); recordTracksEvent( 'calypso_inlinehelp_contact_view', { @@ -213,7 +225,7 @@ export const HelpCenterContactForm = () => { ); const ownershipStatusLoading = ownershipResult?.result === 'LOADING'; - const isSubmitting = submittingTicket || submittingTopic; + const isSubmitting = submittingTicket || submittingTopic || submittingZendeskUserFields; // if the user picked a site from the picker, we don't need to analyze the ownership if ( currentSite && sitePickerChoice === 'CURRENT_SITE' ) { @@ -348,7 +360,7 @@ export const HelpCenterContactForm = () => { case 'CHAT': if ( supportSite ) { recordTracksEvent( 'calypso_inlinehelp_contact_submit', { - support_variation: 'happychat', + support_variation: 'messaging', force_site_id: true, location: 'help-center', section: sectionName, @@ -361,7 +373,22 @@ export const HelpCenterContactForm = () => { location: 'help-center', section: sectionName, } ); - navigate( '/inline-chat' ); + + submitZendeskUserFields( { + messaging_source: sectionName, + messaging_initial_message: message, + messaging_plan: '', // Will be filled out by backend + messaging_url: supportSite?.URL, + } ) + .then( () => { + setShowHelpCenter( false ); + setShowMessagingLauncher( true ); + setShowMessagingWidget( true ); + resetStore(); + } ) + .catch( () => { + setHasSubmittingError( true ); + } ); break; } break; @@ -542,6 +569,10 @@ export const HelpCenterContactForm = () => { return isSubmitting ? formTitles.buttonSubmittingLabel : formTitles.buttonLabel; }; + if ( mode === 'CHAT' && zendeskStatus === 'error' ) { + return ; + } + // TODO: A/B test if ( enableGPTResponse && showingGPTResponse ) { return ( diff --git a/packages/help-center/src/components/help-center-contact-page.tsx b/packages/help-center/src/components/help-center-contact-page.tsx index 3ce3e3dd68dde..ee27a54be2b0d 100644 --- a/packages/help-center/src/components/help-center-contact-page.tsx +++ b/packages/help-center/src/components/help-center-contact-page.tsx @@ -5,9 +5,8 @@ import { recordTracksEvent } from '@automattic/calypso-analytics'; import config from '@automattic/calypso-config'; import { Spinner, GMClosureNotice } from '@automattic/components'; -import { useSupportAvailability, useHasActiveSupport } from '@automattic/data-stores'; +import { useSupportAvailability, useSupportHistory } from '@automattic/data-stores'; import { isDefaultLocale, getLanguage, useLocale } from '@automattic/i18n-utils'; -import { Notice } from '@wordpress/components'; import { useEffect, useMemo } from '@wordpress/element'; import { hasTranslation, sprintf } from '@wordpress/i18n'; import { comment, Icon } from '@wordpress/icons'; @@ -42,12 +41,12 @@ export const HelpCenterContactPage: FC = () => { const renderEmail = useShouldRenderEmailOption(); const renderChat = useShouldRenderChatOption(); const email = useSelector( getCurrentUserEmail ); - const { data: hasActiveTickets, isLoading: isLoadingTickets } = useHasActiveSupport( + const { data: supportHistory, isLoading: isLoadingSupportHistory } = useSupportHistory( 'ticket', email ); const { data: supportAvailability } = useSupportAvailability( 'CHAT' ); - const isLoading = renderChat.isLoading || renderEmail.isLoading || isLoadingTickets; + const isLoading = renderChat.isLoading || renderEmail.isLoading || isLoadingSupportHistory; useEffect( () => { if ( isLoading ) { @@ -121,7 +120,7 @@ export const HelpCenterContactPage: FC = () => {

{ __( 'Contact our WordPress.com experts', __i18n_text_domain__ ) }

- { hasActiveTickets && } + { supportHistory && } { /* Easter */ } { reopensAt="2023-04-10 07:00Z" enabled={ hasAccessToLivechat } /> - { renderChat.env === 'staging' && ( - - Targeting HappyChat staging - - ) }
diff --git a/packages/help-center/src/components/help-center-container.tsx b/packages/help-center/src/components/help-center-container.tsx index 2ee5aa1df01bd..8aebccfae46a5 100644 --- a/packages/help-center/src/components/help-center-container.tsx +++ b/packages/help-center/src/components/help-center-container.tsx @@ -1,15 +1,13 @@ /** * External Dependencies */ -import { useSupportAvailability } from '@automattic/data-stores'; -import { useHappychatAvailable } from '@automattic/happychat-connection'; import { useMobileBreakpoint } from '@automattic/viewport-react'; import { Card } from '@wordpress/components'; import { useSelect, useDispatch } from '@wordpress/data'; import classnames from 'classnames'; -import { useState, useRef, FC, useEffect } from 'react'; +import { useState, useRef, FC } from 'react'; import Draggable, { DraggableProps } from 'react-draggable'; -import { MemoryRouter, useLocation, useNavigate } from 'react-router-dom'; +import { MemoryRouter } from 'react-router-dom'; /** * Internal Dependencies */ @@ -32,20 +30,6 @@ const OptionalDraggable: FC< OptionalDraggableProps > = ( { draggable, ...props return ; }; -const RedirectAssigned = ( { status }: { status?: string } ) => { - const navigate = useNavigate(); - const { pathname } = useLocation(); - const assigned = status === 'assigned'; - - useEffect( () => { - if ( assigned && ! pathname.startsWith( '/inline-chat' ) ) { - navigate( '/inline-chat?session=continued', { replace: true } ); - } - }, [ assigned, navigate, pathname ] ); - - return null; -}; - const HelpCenterContainer: React.FC< Container > = ( { handleClose, hidden } ) => { const { show, isMinimized, initialRoute } = useSelect( ( select ) => ( { @@ -63,8 +47,6 @@ const HelpCenterContainer: React.FC< Container > = ( { handleClose, hidden } ) = const classNames = classnames( 'help-center__container', isMobile ? 'is-mobile' : 'is-desktop', { 'is-minimized': isMinimized, } ); - const { data: supportAvailability } = useSupportAvailability( 'CHAT' ); - const { data } = useHappychatAvailable( Boolean( supportAvailability?.is_user_eligible ) ); const onDismiss = () => { setIsVisible( false ); @@ -94,7 +76,6 @@ const HelpCenterContainer: React.FC< Container > = ( { handleClose, hidden } ) = return ( - { + const { __ } = useI18n(); + const sectionName = useSelector( getSectionName ); + + useEffect( () => { + recordTracksEvent( 'calypso_helpcenter_third_party_cookies_notice_open', { + force_site_id: true, + location: 'help-center', + section: sectionName, + } ); + }, [] ); // Dependencies do not include sectionName on purpose - we just care about reporting it once + + return ( +
+ +
+

{ __( 'Action needed', __i18n_text_domain__ ) }

+

+ { __( + 'In order to access the live chat widget, you will need to enable third-party cookies for WordPress.com.', + __i18n_text_domain__ + ) } +   + + { __( 'Learn more in this support guide.', __i18n_text_domain__ ) } + +

+
+
+ ); +}; + +export default ThirdPartyCookiesNotice; diff --git a/packages/help-center/src/components/help-center.tsx b/packages/help-center/src/components/help-center.tsx index 335b8644996bf..b14dc93cff3b4 100644 --- a/packages/help-center/src/components/help-center.tsx +++ b/packages/help-center/src/components/help-center.tsx @@ -2,51 +2,128 @@ /** * External Dependencies */ -import { useSupportAvailability } from '@automattic/data-stores'; -import { useHappychatAvailable } from '@automattic/happychat-connection'; +import config from '@automattic/calypso-config'; +import { useSupportAvailability, useSupportHistory } from '@automattic/data-stores'; +import { loadScript } from '@automattic/load-script'; import { useSelect, useDispatch } from '@wordpress/data'; import { createPortal, useEffect, useRef } from '@wordpress/element'; import { useSelector } from 'react-redux'; +import { getCurrentUserEmail } from 'calypso/state/current-user/selectors'; import getPrimarySiteId from 'calypso/state/selectors/get-primary-site-id'; import { getSelectedSiteId } from 'calypso/state/ui/selectors'; /** * Internal Dependencies */ -import { useHCWindowCommunicator } from '../happychat-window-communicator'; +import useMessagingAuth from '../hooks/use-messaging-auth'; import { useStillNeedHelpURL } from '../hooks/use-still-need-help-url'; +import useZendeskConfig from '../hooks/use-zendesk-config'; import { HELP_CENTER_STORE, USER_STORE, SITE_STORE } from '../stores'; import { Container } from '../types'; import HelpCenterContainer from './help-center-container'; import type { HelpCenterSelect, SiteSelect, UserSelect } from '@automattic/data-stores'; import '../styles.scss'; +const ZENDESK_SCRIPT_ID = 'ze-snippet'; + const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { const portalParent = useRef( document.createElement( 'div' ) ).current; const { data: chatStatus } = useSupportAvailability( 'CHAT' ); - const { data } = useHappychatAvailable( Boolean( chatStatus?.is_user_eligible ) ); - const { setShowHelpCenter } = useDispatch( HELP_CENTER_STORE ); - const { setUnreadCount } = useDispatch( HELP_CENTER_STORE ); const { setSite } = useDispatch( HELP_CENTER_STORE ); + const { setShowMessagingLauncher } = useDispatch( HELP_CENTER_STORE ); + const { setShowMessagingWidget } = useDispatch( HELP_CENTER_STORE ); - const { show, isMinimized } = useSelect( - ( select ) => ( { - isMinimized: ( select( HELP_CENTER_STORE ) as HelpCenterSelect ).getIsMinimized(), - show: ( select( HELP_CENTER_STORE ) as HelpCenterSelect ).isHelpCenterShown(), - } ), - [] - ); + useEffect( () => { + if ( ! chatStatus?.is_user_eligible ) { + return; + } + + const zendeskKey: string | false = config( 'zendesk_support_chat_key' ); + if ( ! zendeskKey ) { + return; + } - const { unreadCount, closeChat } = useHCWindowCommunicator( isMinimized || ! show ); + if ( document.getElementById( ZENDESK_SCRIPT_ID ) ) { + return; + } + + function setUpMessagingEventHandlers() { + if ( typeof window.zE !== 'function' ) { + return; + } + + window.zE( 'messenger', 'hide' ); + + window.zE( 'messenger:on', 'open', function () { + setShowMessagingWidget( true ); + } ); + window.zE( 'messenger:on', 'close', function () { + setShowMessagingWidget( false ); + } ); + window.zE( 'messenger:on', 'unreadMessages', function ( count ) { + if ( Number( count ) > 0 ) { + setShowMessagingLauncher( true ); + } + } ); + } + loadScript( + 'https://static.zdassets.com/ekr/snippet.js?key=' + encodeURIComponent( zendeskKey ), + setUpMessagingEventHandlers, + { id: ZENDESK_SCRIPT_ID } + ); + }, [ setShowMessagingLauncher, setShowMessagingWidget, chatStatus ] ); + + const { data: messagingAuth } = useMessagingAuth( Boolean( chatStatus?.is_user_eligible ) ); useEffect( () => { - setUnreadCount( unreadCount ); - }, [ unreadCount, setUnreadCount ] ); + const jwt = messagingAuth?.user.jwt; + if ( typeof window.zE !== 'function' || ! jwt ) { + return; + } + + window.zE( 'messenger', 'loginUser', function ( callback ) { + callback( jwt ); + } ); + }, [ messagingAuth ] ); + + const { showMessagingLauncher, showMessagingWidget } = useSelect( ( select ) => { + const helpCenterSelect: HelpCenterSelect = select( HELP_CENTER_STORE ); + return { + showMessagingLauncher: helpCenterSelect.isMessagingLauncherShown(), + showMessagingWidget: helpCenterSelect.isMessagingWidgetShown(), + }; + }, [] ); + + useEffect( () => { + if ( typeof window.zE !== 'function' ) { + return; + } + if ( showMessagingLauncher ) { + window.zE( 'messenger', 'show' ); + } else { + window.zE( 'messenger', 'hide' ); + } + }, [ showMessagingLauncher ] ); useEffect( () => { - if ( data?.status === 'assigned' ) { - setShowHelpCenter( true ); + if ( typeof window.zE !== 'function' ) { + return; } - }, [ data, setShowHelpCenter ] ); + if ( showMessagingWidget ) { + window.zE( 'messenger', 'open' ); + } else { + window.zE( 'messenger', 'close' ); + } + }, [ showMessagingWidget ] ); + + const email = useSelector( getCurrentUserEmail ); + const { data: supportHistory } = useSupportHistory( 'ticket', email ); + useEffect( () => { + if ( supportHistory?.some( ( ticket ) => ticket.channel === 'native_messaging' ) ) { + setShowMessagingLauncher( true ); + } + }, [ setShowMessagingLauncher, supportHistory ] ); + + useZendeskConfig( Boolean( chatStatus?.is_user_eligible ) ); // Pre-fetch const siteId = useSelector( ( state ) => getSelectedSiteId( state ) ); const primarySiteId = useSelector( ( state ) => getPrimarySiteId( state ) ); @@ -60,7 +137,6 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { ); setSite( currentSite ? currentSite : site ); - useSupportAvailability( 'CHAT' ); useStillNeedHelpURL(); @@ -75,7 +151,6 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { return () => { document.body.removeChild( portalParent ); - closeChat(); handleClose(); }; }, [ portalParent ] ); diff --git a/packages/help-center/src/components/types.d.ts b/packages/help-center/src/components/types.d.ts index eb3fc9b5f18e4..054a2e10b81dc 100644 --- a/packages/help-center/src/components/types.d.ts +++ b/packages/help-center/src/components/types.d.ts @@ -2,4 +2,9 @@ declare const __i18n_text_domain__: string; interface Window { helpCenterData: any; + zE?: ( + action: string, + value: string, + handler?: ( callback: ( data: string | number ) => void ) => void + ) => void; } diff --git a/packages/help-center/src/hooks/use-messaging-auth.ts b/packages/help-center/src/hooks/use-messaging-auth.ts new file mode 100644 index 0000000000000..9e05a75e8d435 --- /dev/null +++ b/packages/help-center/src/hooks/use-messaging-auth.ts @@ -0,0 +1,40 @@ +import config from '@automattic/calypso-config'; +import { useQuery } from '@tanstack/react-query'; +import apiFetch from '@wordpress/api-fetch'; +import { addQueryArgs } from '@wordpress/url'; +import wpcomRequest, { canAccessWpcomApis } from 'wpcom-proxy-request'; +import type { MessagingAuth } from '../types'; + +interface APIFetchOptions { + global: boolean; + path: string; +} + +function requestMessagingAuth() { + const currentEnvironment = config( 'env_id' ); + const params = { type: 'zendesk', test_mode: String( currentEnvironment === 'development' ) }; + const wpcomParams = new URLSearchParams( params ); + return canAccessWpcomApis() + ? wpcomRequest< MessagingAuth >( { + path: '/help/authenticate/chat', + query: wpcomParams.toString(), + apiNamespace: 'wpcom/v2', + apiVersion: '2', + method: 'POST', + } ) + : apiFetch< MessagingAuth >( { + path: addQueryArgs( '/help-center/authenticate/chat', params ), + method: 'POST', + global: true, + } as APIFetchOptions ); +} + +export default function useMessagingAuth( enabled: boolean ) { + return useQuery< MessagingAuth >( [ 'getMessagingAuth' ], requestMessagingAuth, { + staleTime: 10 * 60 * 1000, // 10 minutes + meta: { + persist: false, + }, + enabled, + } ); +} diff --git a/packages/help-center/src/hooks/use-messaging-availability.ts b/packages/help-center/src/hooks/use-messaging-availability.ts new file mode 100644 index 0000000000000..89bc1274b5d31 --- /dev/null +++ b/packages/help-center/src/hooks/use-messaging-availability.ts @@ -0,0 +1,47 @@ +import config from '@automattic/calypso-config'; +import { useQuery } from '@tanstack/react-query'; +import apiFetch from '@wordpress/api-fetch'; +import { addQueryArgs } from '@wordpress/url'; +import wpcomRequest, { canAccessWpcomApis } from 'wpcom-proxy-request'; +import type { MessagingAvailability } from '../types'; + +interface APIFetchOptions { + global: boolean; + path: string; +} + +function requestMessagingAvailability() { + const currentEnvironment = config( 'env_id' ); + const params = { + group: 'wpcom_messaging', + environment: currentEnvironment === 'development' ? 'development' : 'production', + }; + const wpcomParams = new URLSearchParams( params ); + return canAccessWpcomApis() + ? wpcomRequest< MessagingAvailability >( { + path: '/help/messaging/is-available', + query: wpcomParams.toString(), + apiNamespace: 'wpcom/v2', + apiVersion: '2', + method: 'GET', + } ) + : apiFetch< MessagingAvailability >( { + path: addQueryArgs( '/help-center/support-availability/messaging', params ), + method: 'GET', + global: true, + } as APIFetchOptions ); +} + +export default function useMessagingAvailability( enabled = true ) { + return useQuery< MessagingAvailability >( + [ 'getMessagingAvailability' ], + requestMessagingAvailability, + { + staleTime: 60 * 1000, // 1 minute + meta: { + persist: false, + }, + enabled, + } + ); +} diff --git a/packages/help-center/src/hooks/use-should-render-chat-option.tsx b/packages/help-center/src/hooks/use-should-render-chat-option.tsx index 5e539ae708835..9d550497282dd 100644 --- a/packages/help-center/src/hooks/use-should-render-chat-option.tsx +++ b/packages/help-center/src/hooks/use-should-render-chat-option.tsx @@ -1,22 +1,16 @@ import { useSupportAvailability } from '@automattic/data-stores'; -import { useHappychatAvailable } from '@automattic/happychat-connection'; +import useMessagingAvailability from './use-messaging-availability'; type Result = { render: boolean; state: 'AVAILABLE' | 'UNAVAILABLE' | 'CLOSED'; isLoading: boolean; eligible: boolean; - env?: 'staging' | 'production'; }; export function useShouldRenderChatOption(): Result { const { data: chatStatus } = useSupportAvailability( 'CHAT' ); - // when the user is looking at the help page, we want to be extra sure they don't start a chat without available operators - // so in this case, let's make stale time 1 minute. - const { data, isLoading } = useHappychatAvailable( - Boolean( chatStatus?.is_user_eligible ), - 60 * 1000 - ); + const { data, isLoading } = useMessagingAvailability( Boolean( chatStatus?.is_user_eligible ) ); if ( ! chatStatus?.is_user_eligible ) { return { @@ -24,7 +18,6 @@ export function useShouldRenderChatOption(): Result { isLoading, state: chatStatus?.is_chat_closed ? 'CLOSED' : 'UNAVAILABLE', eligible: false, - env: data?.env, }; } else if ( chatStatus?.is_chat_closed ) { return { @@ -32,15 +25,13 @@ export function useShouldRenderChatOption(): Result { state: 'CLOSED', isLoading, eligible: true, - env: data?.env, }; - } else if ( data?.available ) { + } else if ( data?.is_available ) { return { render: true, state: 'AVAILABLE', isLoading, eligible: true, - env: data.env, }; } return { @@ -48,6 +39,5 @@ export function useShouldRenderChatOption(): Result { state: 'UNAVAILABLE', isLoading, eligible: true, - env: data?.env, }; } diff --git a/packages/help-center/src/hooks/use-zendesk-config.ts b/packages/help-center/src/hooks/use-zendesk-config.ts new file mode 100644 index 0000000000000..95e3764a80357 --- /dev/null +++ b/packages/help-center/src/hooks/use-zendesk-config.ts @@ -0,0 +1,19 @@ +import { useQuery } from '@tanstack/react-query'; + +function requestZendeskConfig() { + return window.fetch( 'https://wpcom.zendesk.com/embeddable/config' ); +} + +export default function useZendeskConfig( enabled: boolean ) { + return useQuery( [ 'getZendeskConfig' ], requestZendeskConfig, { + staleTime: Infinity, + retry: false, + refetchOnMount: false, + retryOnMount: false, + refetchOnWindowFocus: false, + meta: { + persist: false, + }, + enabled, + } ); +} diff --git a/packages/help-center/src/index.ts b/packages/help-center/src/index.ts index 239b70f422f74..4c71f8eb6c08b 100644 --- a/packages/help-center/src/index.ts +++ b/packages/help-center/src/index.ts @@ -4,7 +4,6 @@ export { SuccessIcon } from './components/success-icon'; export { SuccessScreen } from './components/ticket-success-screen'; export { BackButton } from './components/back-button'; export { HelpCenterContactForm } from './components/help-center-contact-form'; -export { useHCWindowCommunicator } from './happychat-window-communicator'; export { default as Mail } from './icons/mail'; export { default as NewReleases } from './icons/new-releases'; export * from './support-variations'; diff --git a/packages/help-center/src/types.ts b/packages/help-center/src/types.ts index cd36b7d88c5da..ce0f928f208e8 100644 --- a/packages/help-center/src/types.ts +++ b/packages/help-center/src/types.ts @@ -60,3 +60,13 @@ export interface SupportTicket { url: string; when: string; } + +export interface MessagingAuth { + user: { + jwt: string; + }; +} + +export interface MessagingAvailability { + is_available: boolean; +} From b290b39d048f972a88be75d68eee803b6fb68835 Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Wed, 17 May 2023 18:57:26 +0000 Subject: [PATCH 2/7] Use support activities instead of history This is much faster and avoids pinging Zendesk --- ...s-wp-rest-help-center-support-activity.php | 53 +++++++++ ...ss-wp-rest-help-center-support-history.php | 72 ------------ packages/data-stores/src/index.ts | 2 +- .../data-stores/src/support-queries/types.ts | 8 +- .../support-queries/use-support-activity.ts | 36 ++++++ .../support-queries/use-support-history.ts | 48 -------- .../components/help-center-contact-page.tsx | 18 +-- .../components/help-center-inline-chat.scss | 6 - .../components/help-center-inline-chat.tsx | 103 ++---------------- .../src/components/help-center-notice.tsx | 4 +- .../src/components/help-center.tsx | 10 +- .../hooks/use-should-render-chat-option.tsx | 18 ++- 12 files changed, 127 insertions(+), 251 deletions(-) create mode 100644 apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-activity.php delete mode 100644 apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-history.php create mode 100644 packages/data-stores/src/support-queries/use-support-activity.ts delete mode 100644 packages/data-stores/src/support-queries/use-support-history.ts delete mode 100644 packages/help-center/src/components/help-center-inline-chat.scss diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-activity.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-activity.php new file mode 100644 index 0000000000000..10cdc0cd14c6f --- /dev/null +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-activity.php @@ -0,0 +1,53 @@ +namespace = 'help-center'; + $this->rest_base = '/support-activity'; + } + + /** + * Register available routes. + */ + public function register_rest_route() { + register_rest_route( + $this->namespace, + $this->rest_base, + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_support_activity' ), + 'permission_callback' => 'is_user_logged_in', + ) + ); + } + + /** + * Get support activity through Jetpack. + */ + public function get_support_activity() { + $body = Client::wpcom_json_api_request_as_user( '/support-activity' ); + + if ( is_wp_error( $body ) ) { + return $body; + } + + $response = json_decode( wp_remote_retrieve_body( $body ) ); + + return rest_ensure_response( $response ); + } +} diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-history.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-history.php deleted file mode 100644 index 6156af39aae01..0000000000000 --- a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-wp-rest-help-center-support-history.php +++ /dev/null @@ -1,72 +0,0 @@ -namespace = 'help-center'; - $this->rest_base = '/support-history'; - } - - /** - * Register available routes. - */ - public function register_rest_route() { - register_rest_route( - $this->namespace, - $this->rest_base . '/ticket', - array( - 'methods' => \WP_REST_Server::READABLE, - 'callback' => array( $this, 'support_history_ticket' ), - 'permission_callback' => 'is_user_logged_in', - 'args' => array( - 'email' => array( - 'type' => 'string', - ), - ), - ) - ); - } - - /** - * Get support history tickets through Jetpack. - * - * @param \WP_REST_Request $request Request object. - */ - public function support_history_ticket( $request ) { - if ( isset( $request['email'] ) ) { - $params = array( 'email' => $request['email'] ); - } else { - $params = array(); - } - - $body = Client::wpcom_json_api_request_as_user( - '/support-history/ticket?' . http_build_query( $params ), - '2', - array( - 'method' => 'GET', - ) - ); - - if ( is_wp_error( $body ) ) { - return $body; - } - - $response = json_decode( wp_remote_retrieve_body( $body ) ); - - return rest_ensure_response( $response ); - } -} diff --git a/packages/data-stores/src/index.ts b/packages/data-stores/src/index.ts index e6a782454ca55..f3f2ddff1a1ce 100644 --- a/packages/data-stores/src/index.ts +++ b/packages/data-stores/src/index.ts @@ -22,7 +22,7 @@ export { useSupportAvailability } from './support-queries/use-support-availabili export { useSubmitTicketMutation } from './support-queries/use-submit-support-ticket'; export { useSubmitForumsMutation } from './support-queries/use-submit-forums-topic'; export { useUpdateZendeskUserFieldsMutation } from './support-queries/use-update-zendesk-user-fields'; -export { useSupportHistory } from './support-queries/use-support-history'; +export { useSupportActivity } from './support-queries/use-support-activity'; export * from './starter-designs-queries'; export * from './support-queries/types'; export * from './site/types'; diff --git a/packages/data-stores/src/support-queries/types.ts b/packages/data-stores/src/support-queries/types.ts index 75a3cdee18159..36ef0789ef61e 100644 --- a/packages/data-stores/src/support-queries/types.ts +++ b/packages/data-stores/src/support-queries/types.ts @@ -27,14 +27,10 @@ export interface OtherSupportAvailability { is_user_eligible_for_chat: boolean; } -export interface SupportSession { - id?: number; +export interface SupportActivity { + id: number; status: string; subject: string; - time: Date; timestamp: number; - type: string; - url: string; - when: string; channel: string; } diff --git a/packages/data-stores/src/support-queries/use-support-activity.ts b/packages/data-stores/src/support-queries/use-support-activity.ts new file mode 100644 index 0000000000000..db27e0c15b1c1 --- /dev/null +++ b/packages/data-stores/src/support-queries/use-support-activity.ts @@ -0,0 +1,36 @@ +import { useQuery } from '@tanstack/react-query'; +import apiFetch, { APIFetchOptions } from '@wordpress/api-fetch'; +import wpcomRequest, { canAccessWpcomApis } from 'wpcom-proxy-request'; +import type { SupportActivity } from './types'; + +const ACTIVE_STATUSES = [ 'New', 'Open', 'Hold' ]; + +export function useSupportActivity( enabled = true ) { + return useQuery( + [ 'help-support-activity' ], + () => + canAccessWpcomApis() + ? wpcomRequest< SupportActivity[] >( { + path: 'support-activity', + apiNamespace: 'wpcom/v2/', + apiVersion: '2', + } ) + : apiFetch< SupportActivity[] >( { + path: 'help-center/support-activity', + global: true, + } as APIFetchOptions ), + { + refetchOnWindowFocus: false, + keepPreviousData: false, + refetchOnMount: true, + enabled, + select: ( activities ) => { + return activities.filter( ( activity ) => ACTIVE_STATUSES.includes( activity.status ) ); + }, + staleTime: 30 * 60 * 1000, + meta: { + persist: false, + }, + } + ); +} diff --git a/packages/data-stores/src/support-queries/use-support-history.ts b/packages/data-stores/src/support-queries/use-support-history.ts deleted file mode 100644 index 884169fe627d7..0000000000000 --- a/packages/data-stores/src/support-queries/use-support-history.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import apiFetch, { APIFetchOptions } from '@wordpress/api-fetch'; -import wpcomRequest, { canAccessWpcomApis } from 'wpcom-proxy-request'; -import type { SupportSession } from './types'; - -interface Response { - data: SupportSession[]; -} - -const ACTIVE_STATUSES = [ 'New', 'Open', 'Hold' ]; - -/** - * Checks if the user has an active support session or a recent ticket. - * - * NOTE: Chat mode isn't functional at the moment. - */ -export function useSupportHistory( type: 'chat' | 'ticket', email: string, show = true ) { - return useQuery( - [ 'help-support-history', type, email ], - () => - canAccessWpcomApis() - ? wpcomRequest< Response >( { - path: `support-history/${ encodeURIComponent( type ) }`, - apiNamespace: 'wpcom/v2/', - apiVersion: '2', - query: email ? `email=${ encodeURIComponent( email ) }` : '', - } ) - : apiFetch< Response >( { - path: - `help-center/support-history/${ encodeURIComponent( type ) }/` + - ( email ? `?email=${ encodeURIComponent( email ) }` : '' ), - global: true, - } as APIFetchOptions ), - { - refetchOnWindowFocus: false, - keepPreviousData: false, - refetchOnMount: true, - enabled: show, - select: ( response ) => { - return response.data.filter( ( session ) => ACTIVE_STATUSES.includes( session.status ) ); - }, - staleTime: 30 * 60 * 1000, - meta: { - persist: false, - }, - } - ); -} diff --git a/packages/help-center/src/components/help-center-contact-page.tsx b/packages/help-center/src/components/help-center-contact-page.tsx index ee27a54be2b0d..3140d8ead3d18 100644 --- a/packages/help-center/src/components/help-center-contact-page.tsx +++ b/packages/help-center/src/components/help-center-contact-page.tsx @@ -5,7 +5,7 @@ import { recordTracksEvent } from '@automattic/calypso-analytics'; import config from '@automattic/calypso-config'; import { Spinner, GMClosureNotice } from '@automattic/components'; -import { useSupportAvailability, useSupportHistory } from '@automattic/data-stores'; +import { useSupportAvailability, useSupportActivity } from '@automattic/data-stores'; import { isDefaultLocale, getLanguage, useLocale } from '@automattic/i18n-utils'; import { useEffect, useMemo } from '@wordpress/element'; import { hasTranslation, sprintf } from '@wordpress/i18n'; @@ -15,7 +15,6 @@ import classnames from 'classnames'; import { FC } from 'react'; import { useSelector } from 'react-redux'; import { Link, LinkProps } from 'react-router-dom'; -import { getCurrentUserEmail } from 'calypso/state/current-user/selectors'; import { getSectionName } from 'calypso/state/ui/selectors'; /** * Internal Dependencies @@ -40,13 +39,9 @@ export const HelpCenterContactPage: FC = () => { const renderEmail = useShouldRenderEmailOption(); const renderChat = useShouldRenderChatOption(); - const email = useSelector( getCurrentUserEmail ); - const { data: supportHistory, isLoading: isLoadingSupportHistory } = useSupportHistory( - 'ticket', - email - ); + const { data: supportActivity, isLoading: isLoadingSupportActivity } = useSupportActivity(); const { data: supportAvailability } = useSupportAvailability( 'CHAT' ); - const isLoading = renderChat.isLoading || renderEmail.isLoading || isLoadingSupportHistory; + const isLoading = renderChat.isLoading || renderEmail.isLoading || isLoadingSupportActivity; useEffect( () => { if ( isLoading ) { @@ -120,7 +115,7 @@ export const HelpCenterContactPage: FC = () => {

{ __( 'Contact our WordPress.com experts', __i18n_text_domain__ ) }

- { supportHistory && } + { supportActivity && } { /* Easter */ } { { renderChat.render && (
- +
( null ); - - useEffect( () => { - if ( ! container.current ) { - return; - } - const containerElement = container.current; - - let isMouseDown = false; - - function handler( event: MouseEvent | ResizeObserverEntry[] | UIEvent | null ) { - // when it's an array, it means it came from ResizeObserver - if ( isMouseDown || Array.isArray( event ) || event?.type === 'resize' ) { - const box = containerElement.getBoundingClientRect(); - theIframe.style.display = 'block'; - theIframe.style.left = box.left + 'px'; - theIframe.style.top = box.top + 'px'; - theIframe.style.width = box.width + 'px'; - theIframe.style.height = box.height + 'px'; - } - } - - handler( [] ); - - // this is the only I could come up with to monitor dragging - // since React-draggable is not propagating the drag event. - function mouseDownHandler() { - isMouseDown = true; - } - - function mouseUpHandler() { - isMouseDown = false; - } - - window.addEventListener( 'resize', handler ); - window.addEventListener( 'mousemove', handler ); - window.addEventListener( 'mouseup', mouseUpHandler ); - window.addEventListener( 'mousedown', mouseDownHandler ); - - const resizeObserver = new ResizeObserver( handler ); - resizeObserver.observe( containerElement ); - - return () => { - theIframe.style.display = 'none'; - window.removeEventListener( 'resize', handler ); - window.removeEventListener( 'mousemove', handler ); - window.removeEventListener( 'mouseup', mouseUpHandler ); - window.removeEventListener( 'mousedown', mouseDownHandler ); - resizeObserver.unobserve( containerElement ); - }; - }, [ container ] ); - - useEffect( () => { - setIframe( theIframe ); - // rewriting the same src will reload the iframe - if ( theIframe.src !== src ) { - theIframe.src = src; - } - }, [ src, setIframe ] ); - - return
; -} - const InlineChat: React.FC = () => { - const { search } = useLocation(); - const params = new URLSearchParams( search ); - const session = params.get( 'session' ) === 'continued' ? 'continued' : 'new'; - // "ref" is used to track where the user came from so we can show the right message - // See happychat/getUserInfo for more info. - const ref = new URLSearchParams( window.location.search ).get( 'ref' ) || ''; - - return ( - - ); + const { setShowMessagingLauncher } = useDispatch( HELP_CENTER_STORE ); + const { setShowMessagingWidget } = useDispatch( HELP_CENTER_STORE ); + const { setShowHelpCenter } = useDispatch( HELP_CENTER_STORE ); + setShowMessagingLauncher( true ); + setShowMessagingWidget( true ); + setShowHelpCenter( false ); + + return null; }; export default InlineChat; diff --git a/packages/help-center/src/components/help-center-notice.tsx b/packages/help-center/src/components/help-center-notice.tsx index 4b9fe3507cc17..414a84224b18b 100644 --- a/packages/help-center/src/components/help-center-notice.tsx +++ b/packages/help-center/src/components/help-center-notice.tsx @@ -1,4 +1,4 @@ -import { SupportSession } from '@automattic/data-stores'; +import { SupportActivity } from '@automattic/data-stores'; import { localizeUrl, useLocale, getRelativeTimeString } from '@automattic/i18n-utils'; import { ExternalLink } from '@wordpress/components'; import { createInterpolateElement } from '@wordpress/element'; @@ -97,7 +97,7 @@ export function HelpCenterOwnershipNotice( { ownershipResult }: Props ) { export function HelpCenterActiveTicketNotice( { tickets, }: { - tickets: SupportSession[] | undefined; + tickets: SupportActivity[] | undefined; } ) { const locale = useLocale(); diff --git a/packages/help-center/src/components/help-center.tsx b/packages/help-center/src/components/help-center.tsx index b14dc93cff3b4..81d31ea8d9d77 100644 --- a/packages/help-center/src/components/help-center.tsx +++ b/packages/help-center/src/components/help-center.tsx @@ -3,12 +3,11 @@ * External Dependencies */ import config from '@automattic/calypso-config'; -import { useSupportAvailability, useSupportHistory } from '@automattic/data-stores'; +import { useSupportAvailability, useSupportActivity } from '@automattic/data-stores'; import { loadScript } from '@automattic/load-script'; import { useSelect, useDispatch } from '@wordpress/data'; import { createPortal, useEffect, useRef } from '@wordpress/element'; import { useSelector } from 'react-redux'; -import { getCurrentUserEmail } from 'calypso/state/current-user/selectors'; import getPrimarySiteId from 'calypso/state/selectors/get-primary-site-id'; import { getSelectedSiteId } from 'calypso/state/ui/selectors'; /** @@ -115,13 +114,12 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { } }, [ showMessagingWidget ] ); - const email = useSelector( getCurrentUserEmail ); - const { data: supportHistory } = useSupportHistory( 'ticket', email ); + const { data: supportActivity } = useSupportActivity(); useEffect( () => { - if ( supportHistory?.some( ( ticket ) => ticket.channel === 'native_messaging' ) ) { + if ( supportActivity?.some( ( ticket ) => ticket.channel === 'Messaging' ) ) { setShowMessagingLauncher( true ); } - }, [ setShowMessagingLauncher, supportHistory ] ); + }, [ setShowMessagingLauncher, supportActivity ] ); useZendeskConfig( Boolean( chatStatus?.is_user_eligible ) ); // Pre-fetch diff --git a/packages/help-center/src/hooks/use-should-render-chat-option.tsx b/packages/help-center/src/hooks/use-should-render-chat-option.tsx index 9d550497282dd..c6a9fabe5d324 100644 --- a/packages/help-center/src/hooks/use-should-render-chat-option.tsx +++ b/packages/help-center/src/hooks/use-should-render-chat-option.tsx @@ -1,4 +1,4 @@ -import { useSupportAvailability } from '@automattic/data-stores'; +import { useSupportAvailability, useSupportActivity } from '@automattic/data-stores'; import useMessagingAvailability from './use-messaging-availability'; type Result = { @@ -6,11 +6,19 @@ type Result = { state: 'AVAILABLE' | 'UNAVAILABLE' | 'CLOSED'; isLoading: boolean; eligible: boolean; + to: string; }; export function useShouldRenderChatOption(): Result { const { data: chatStatus } = useSupportAvailability( 'CHAT' ); - const { data, isLoading } = useMessagingAvailability( Boolean( chatStatus?.is_user_eligible ) ); + const { data, isLoading: isLoadingAvailability } = useMessagingAvailability( + Boolean( chatStatus?.is_user_eligible ) + ); + const { data: supportActivity, isLoading: isLoadingSupportActivity } = useSupportActivity( + Boolean( chatStatus?.is_user_eligible ) + ); + + const isLoading = isLoadingAvailability || isLoadingSupportActivity; if ( ! chatStatus?.is_user_eligible ) { return { @@ -18,6 +26,7 @@ export function useShouldRenderChatOption(): Result { isLoading, state: chatStatus?.is_chat_closed ? 'CLOSED' : 'UNAVAILABLE', eligible: false, + to: '', }; } else if ( chatStatus?.is_chat_closed ) { return { @@ -25,13 +34,17 @@ export function useShouldRenderChatOption(): Result { state: 'CLOSED', isLoading, eligible: true, + to: '', }; } else if ( data?.is_available ) { + const hasActiveChats = supportActivity?.some( ( ticket ) => ticket.channel === 'Messaging' ); + const to = hasActiveChats ? '/inline-chat' : '/contact-form?mode=CHAT'; return { render: true, state: 'AVAILABLE', isLoading, eligible: true, + to, }; } return { @@ -39,5 +52,6 @@ export function useShouldRenderChatOption(): Result { state: 'UNAVAILABLE', isLoading, eligible: true, + to: '', }; } From ab00d76f9f8f9acb8da3d62410b59973d35b06c8 Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Wed, 17 May 2023 19:14:55 +0000 Subject: [PATCH 3/7] Fix the Support Activity endpoint for ETK --- .../editing-toolkit-plugin/help-center/class-help-center.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php index 308479703c651..6a029e99ddeda 100644 --- a/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php +++ b/apps/editing-toolkit/editing-toolkit-plugin/help-center/class-help-center.php @@ -207,8 +207,8 @@ public function register_rest_api() { $controller = new WP_REST_Help_Center_Forum(); $controller->register_rest_route(); - require_once __DIR__ . '/class-wp-rest-help-center-support-history.php'; - $controller = new WP_REST_Help_Center_Support_History(); + require_once __DIR__ . '/class-wp-rest-help-center-support-activity.php'; + $controller = new WP_REST_Help_Center_Support_Activity(); $controller->register_rest_route(); require_once __DIR__ . '/class-wp-rest-help-center-user-fields.php'; From e5fa3aec7102c54e4647e96d71fb8f22cbf9ed4a Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Wed, 17 May 2023 19:44:07 +0000 Subject: [PATCH 4/7] Safeguard against fetching support activity when we don't need it --- packages/help-center/src/components/help-center.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/help-center/src/components/help-center.tsx b/packages/help-center/src/components/help-center.tsx index 81d31ea8d9d77..5d215b1be2a47 100644 --- a/packages/help-center/src/components/help-center.tsx +++ b/packages/help-center/src/components/help-center.tsx @@ -114,7 +114,7 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { } }, [ showMessagingWidget ] ); - const { data: supportActivity } = useSupportActivity(); + const { data: supportActivity } = useSupportActivity( Boolean( chatStatus?.is_user_eligible ) ); useEffect( () => { if ( supportActivity?.some( ( ticket ) => ticket.channel === 'Messaging' ) ) { setShowMessagingLauncher( true ); From 3745095c3926a531d13357e75d2fcb2a4352feec Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Wed, 17 May 2023 19:58:48 +0000 Subject: [PATCH 5/7] Prevent unnecessary query when not in the JP presales context --- .../jetpack/jetpack-presales-chat-widget/index.tsx | 2 +- client/lib/jetpack/use-jp-presales-availability-query.ts | 6 +++++- .../composite-checkout/components/checkout-help-link.tsx | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/components/jetpack/jetpack-presales-chat-widget/index.tsx b/client/components/jetpack/jetpack-presales-chat-widget/index.tsx index b62d09209ecfa..424634461b783 100644 --- a/client/components/jetpack/jetpack-presales-chat-widget/index.tsx +++ b/client/components/jetpack/jetpack-presales-chat-widget/index.tsx @@ -30,7 +30,7 @@ function get_config_chat_key( keyType: KeyType ): keyof ConfigData { export const ZendeskJetpackChat: React.VFC< { keyType: KeyType } > = ( { keyType } ) => { const [ error, setError ] = useState( false ); - const { data: isStaffed } = useJpPresalesAvailabilityQuery( setError ); + const { data: isStaffed } = useJpPresalesAvailabilityQuery( true, setError ); const zendeskChatKey: string | false = useMemo( () => { return config( get_config_chat_key( keyType ) ); }, [ keyType ] ); diff --git a/client/lib/jetpack/use-jp-presales-availability-query.ts b/client/lib/jetpack/use-jp-presales-availability-query.ts index cb024d63e08bc..0bf857673ed2f 100644 --- a/client/lib/jetpack/use-jp-presales-availability-query.ts +++ b/client/lib/jetpack/use-jp-presales-availability-query.ts @@ -31,7 +31,10 @@ async function fetchWithRetry( } } -export function useJpPresalesAvailabilityQuery( setError?: Dispatch< SetStateAction< boolean > > ) { +export function useJpPresalesAvailabilityQuery( + enabled = true, + setError?: Dispatch< SetStateAction< boolean > > +) { //adding a safeguard to ensure if there's an unkown error with the widget it won't crash the whole app try { return useQuery< boolean, Error >( @@ -58,6 +61,7 @@ export function useJpPresalesAvailabilityQuery( setError?: Dispatch< SetStateAct return data.is_available; }, { + enabled, meta: { persist: false }, } ); diff --git a/client/my-sites/checkout/composite-checkout/components/checkout-help-link.tsx b/client/my-sites/checkout/composite-checkout/components/checkout-help-link.tsx index a4cf4234131ae..dac8f723dec66 100644 --- a/client/my-sites/checkout/composite-checkout/components/checkout-help-link.tsx +++ b/client/my-sites/checkout/composite-checkout/components/checkout-help-link.tsx @@ -146,7 +146,6 @@ export default function CheckoutHelpLink() { const translate = useTranslate(); const { setShowHelpCenter } = useDataStoreDispatch( HELP_CENTER_STORE ); const isEnglishLocale = useIsEnglishLocale(); - const { data: isJpPresalesStaffed } = useJpPresalesAvailabilityQuery(); const cartKey = useCartKey(); const { responseCart } = useShoppingCart( cartKey ); @@ -165,6 +164,9 @@ export default function CheckoutHelpLink() { supportVariation: getSupportVariation( state ), }; } ); + const { data: isJpPresalesStaffed } = useJpPresalesAvailabilityQuery( + presalesZendeskChatAvailable + ); const userAllowedToHelpCenter = config.isEnabled( 'calypso/help-center' ); From d96bb9d9b0bff002bb34e3b7efb133e8767578a6 Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Thu, 18 May 2023 10:33:17 +0000 Subject: [PATCH 6/7] Ensure we don't run into race conditions when loading scripts Otherwise, if we cache the Messaging auth, we could try to login to Messaging before its scripts were loaded. --- .../help-center/src/components/help-center.tsx | 16 +++++++++------- .../help-center/src/hooks/use-messaging-auth.ts | 5 +---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/help-center/src/components/help-center.tsx b/packages/help-center/src/components/help-center.tsx index 5d215b1be2a47..dae68079e0774 100644 --- a/packages/help-center/src/components/help-center.tsx +++ b/packages/help-center/src/components/help-center.tsx @@ -6,7 +6,7 @@ import config from '@automattic/calypso-config'; import { useSupportAvailability, useSupportActivity } from '@automattic/data-stores'; import { loadScript } from '@automattic/load-script'; import { useSelect, useDispatch } from '@wordpress/data'; -import { createPortal, useEffect, useRef } from '@wordpress/element'; +import { createPortal, useEffect, useRef, useState } from '@wordpress/element'; import { useSelector } from 'react-redux'; import getPrimarySiteId from 'calypso/state/selectors/get-primary-site-id'; import { getSelectedSiteId } from 'calypso/state/ui/selectors'; @@ -30,6 +30,7 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { const { setSite } = useDispatch( HELP_CENTER_STORE ); const { setShowMessagingLauncher } = useDispatch( HELP_CENTER_STORE ); const { setShowMessagingWidget } = useDispatch( HELP_CENTER_STORE ); + const [ isMessagingScriptLoaded, setMessagingScriptLoaded ] = useState( false ); useEffect( () => { if ( ! chatStatus?.is_user_eligible ) { @@ -46,6 +47,7 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { } function setUpMessagingEventHandlers() { + setMessagingScriptLoaded( true ); if ( typeof window.zE !== 'function' ) { return; } @@ -75,14 +77,14 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { const { data: messagingAuth } = useMessagingAuth( Boolean( chatStatus?.is_user_eligible ) ); useEffect( () => { const jwt = messagingAuth?.user.jwt; - if ( typeof window.zE !== 'function' || ! jwt ) { + if ( typeof window.zE !== 'function' || ! jwt || ! isMessagingScriptLoaded ) { return; } window.zE( 'messenger', 'loginUser', function ( callback ) { callback( jwt ); } ); - }, [ messagingAuth ] ); + }, [ messagingAuth, isMessagingScriptLoaded ] ); const { showMessagingLauncher, showMessagingWidget } = useSelect( ( select ) => { const helpCenterSelect: HelpCenterSelect = select( HELP_CENTER_STORE ); @@ -93,7 +95,7 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { }, [] ); useEffect( () => { - if ( typeof window.zE !== 'function' ) { + if ( typeof window.zE !== 'function' || ! isMessagingScriptLoaded ) { return; } if ( showMessagingLauncher ) { @@ -101,10 +103,10 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { } else { window.zE( 'messenger', 'hide' ); } - }, [ showMessagingLauncher ] ); + }, [ showMessagingLauncher, isMessagingScriptLoaded ] ); useEffect( () => { - if ( typeof window.zE !== 'function' ) { + if ( typeof window.zE !== 'function' || ! isMessagingScriptLoaded ) { return; } if ( showMessagingWidget ) { @@ -112,7 +114,7 @@ const HelpCenter: React.FC< Container > = ( { handleClose, hidden } ) => { } else { window.zE( 'messenger', 'close' ); } - }, [ showMessagingWidget ] ); + }, [ showMessagingWidget, isMessagingScriptLoaded ] ); const { data: supportActivity } = useSupportActivity( Boolean( chatStatus?.is_user_eligible ) ); useEffect( () => { diff --git a/packages/help-center/src/hooks/use-messaging-auth.ts b/packages/help-center/src/hooks/use-messaging-auth.ts index 9e05a75e8d435..23410796143f3 100644 --- a/packages/help-center/src/hooks/use-messaging-auth.ts +++ b/packages/help-center/src/hooks/use-messaging-auth.ts @@ -31,10 +31,7 @@ function requestMessagingAuth() { export default function useMessagingAuth( enabled: boolean ) { return useQuery< MessagingAuth >( [ 'getMessagingAuth' ], requestMessagingAuth, { - staleTime: 10 * 60 * 1000, // 10 minutes - meta: { - persist: false, - }, + staleTime: 7 * 24 * 60 * 60 * 1000, // 1 week (JWT is actually 2 weeks, but lets be on the safe side) enabled, } ); } From 93ac65a38d609264bd63936f7ed2a9efba80e009 Mon Sep 17 00:00:00 2001 From: Igor Klimer Date: Thu, 18 May 2023 11:11:34 +0000 Subject: [PATCH 7/7] Ensure Happy Chat is not loaded in production and staging --- config/production.json | 2 +- config/stage.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/production.json b/config/production.json index ca5f02dfefb6e..687aa0a9c59ed 100644 --- a/config/production.json +++ b/config/production.json @@ -46,7 +46,7 @@ "fullstory": true, "cookie-banner": true, "google-my-business": true, - "happychat": true, + "happychat": false, "help": true, "help/gpt-response": false, "hosting-onboarding-i2": false, diff --git a/config/stage.json b/config/stage.json index d94bccf04738e..9de90ef716af0 100644 --- a/config/stage.json +++ b/config/stage.json @@ -44,7 +44,7 @@ "fullstory": true, "cookie-banner": false, "google-my-business": true, - "happychat": true, + "happychat": false, "help": true, "help/gpt-response": true, "i18n/empathy-mode": true,