Skip to content

Commit

Permalink
Help Center: Open Zendesk with link (#96448)
Browse files Browse the repository at this point in the history
Co-authored-by: Tony Arcangelini <[email protected]>
Co-authored-by: heavyweight <[email protected]>
Co-authored-by: Kosta <[email protected]>
  • Loading branch information
4 people authored Jan 22, 2025
1 parent 248ffbc commit afe6165
Show file tree
Hide file tree
Showing 17 changed files with 200 additions and 119 deletions.
30 changes: 19 additions & 11 deletions client/components/chat-button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,25 @@ const ChatButton: FC< Props > = ( {

const handleClick = () => {
if ( canConnectToZendesk ) {
openZendeskWidget( {
message: initialMessage,
siteUrl,
siteId,
onError,
onSuccess: () => {
onClick?.();
resetStore();
setShowHelpCenter( false );
},
} );
if ( chatIntent === 'PRECANCELLATION' ) {
onClick?.();
setShowHelpCenter( true );
setNavigateToRoute(
`/odie?provider=zendesk&userFieldMessage=${ initialMessage }&siteUrl=${ siteUrl }&siteId=${ siteId }`
);
} else {
openZendeskWidget( {
message: initialMessage,
siteUrl,
siteId,
onError,
onSuccess: () => {
onClick?.();
resetStore();
setShowHelpCenter( false );
},
} );
}
} else {
setNavigateToRoute( '/contact-form?mode=CHAT' );
setShowHelpCenter( true );
Expand Down
20 changes: 6 additions & 14 deletions client/me/purchases/cancel-purchase/support-link.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,30 @@ const HELP_CENTER_STORE = HelpCenter.register();
const CancelPurchaseSupportLink = ( { purchase } ) => {
const translate = useTranslate();
const { siteId, siteUrl } = purchase;
const { setShowHelpCenter, setNavigateToRoute, resetStore } =
useDataStoreDispatch( HELP_CENTER_STORE );
const { setShowHelpCenter, setNavigateToRoute } = useDataStoreDispatch( HELP_CENTER_STORE );
const { isEligibleForChat } = useChatStatus();
const { data: canConnectToZendeskMessaging } = useCanConnectToZendeskMessaging();
const { data: isMessagingAvailable } = useZendeskMessagingAvailability(
'wpcom_messaging',
isEligibleForChat
);
const { openZendeskWidget, isOpeningZendeskWidget } = useOpenZendeskMessaging(
const { isOpeningZendeskWidget } = useOpenZendeskMessaging(
'migration-error',
'zendesk_support_chat_key',
isEligibleForChat
);

const getHelp = useCallback( () => {
if ( isMessagingAvailable && canConnectToZendeskMessaging ) {
openZendeskWidget( {
siteUrl: siteUrl,
siteId: siteId,
message: `${ status }: Purchase cancellation flow`,
onSuccess: () => {
resetStore();
setShowHelpCenter( false );
},
} );
setShowHelpCenter( true );
setNavigateToRoute(
`/odie?provider=zendesk&userFieldMessage=${ 'Purchase cancellation flow' }&siteUrl=${ siteUrl }&siteId=${ siteId }`
);
} else {
setNavigateToRoute( '/contact-options' );
setShowHelpCenter( true );
}
}, [
resetStore,
openZendeskWidget,
siteId,
isMessagingAvailable,
siteUrl,
Expand Down
2 changes: 2 additions & 0 deletions packages/help-center/src/components/back-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const BackButton = () => {
navigate( '/' );
} else if ( searchParams.get( 'query' ) ) {
navigate( `/?query=${ searchParams.get( 'query' ) }` );
} else if ( searchParams.get( 'direct-zd-chat' ) ) {
navigate( '/' );
} else {
navigate( -1 );
}
Expand Down
14 changes: 9 additions & 5 deletions packages/help-center/src/components/help-center-chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { recordTracksEvent } from '@automattic/calypso-analytics';
import OdieAssistantProvider, { OdieAssistant } from '@automattic/odie-client';
import { useEffect } from '@wordpress/element';
import { useNavigate, useParams } from 'react-router-dom';
import { useLocation, useNavigate } from 'react-router-dom';
import { useHelpCenterContext } from '../contexts/HelpCenterContext';
import { useShouldUseWapuu } from '../hooks';
import { ExtraContactOptions } from './help-center-extra-contact-option';
Expand All @@ -24,7 +24,11 @@ export function HelpCenterChat( {
const shouldUseWapuu = useShouldUseWapuu();
const preventOdieAccess = ! shouldUseWapuu && ! isUserEligibleForPaidSupport;
const { currentUser, site, canConnectToZendesk } = useHelpCenterContext();
const { id: conversationId = null } = useParams();
const { search } = useLocation();
const params = new URLSearchParams( search );
const userFieldMessage = params.get( 'userFieldMessage' );
const siteUrl = params.get( 'siteUrl' );
const siteId = params.get( 'siteId' );

useEffect( () => {
if ( preventOdieAccess ) {
Expand All @@ -40,9 +44,9 @@ export function HelpCenterChat( {
<OdieAssistantProvider
currentUser={ currentUser }
canConnectToZendesk={ canConnectToZendesk }
selectedSiteId={ site?.ID as number }
selectedSiteURL={ site?.URL as string }
selectedConversationId={ conversationId }
selectedSiteId={ Number( siteId ) || ( site?.ID as number ) }
selectedSiteURL={ siteUrl || ( site?.URL as string ) }
userFieldMessage={ userFieldMessage }
isUserEligibleForPaidSupport={ isUserEligibleForPaidSupport }
extraContactOptions={
<ExtraContactOptions isUserEligible={ isUserEligibleForPaidSupport } />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const HelpCenterContent: React.FC< { isRelative?: boolean; currentRoute?: string
event_source: 'help-center',
event_external_id: uuidv4(),
} );
} else if ( openSupportInteraction ) {
} else if ( openSupportInteraction && ! currentSupportInteraction ) {
setCurrentSupportInteraction( openSupportInteraction[ 0 ] );
}
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { recordTracksEvent } from '@automattic/calypso-analytics';
import { GetSupport } from '@automattic/odie-client/src/components/message/get-support';
import { useManageSupportInteraction } from '@automattic/odie-client/src/data';
import { useI18n } from '@wordpress/react-i18n';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { v4 as uuidv4 } from 'uuid';
import { useHelpCenterContext } from '../contexts/HelpCenterContext';
import { useSupportStatus } from '../data/use-support-status';
import { useResetSupportInteraction } from '../hooks/use-reset-support-interaction';
Expand All @@ -23,7 +21,6 @@ const HelpCenterFeedbackForm = ( { postId }: { postId: number } ) => {
const { canConnectToZendesk } = useHelpCenterContext();
const navigate = useNavigate();
const resetSupportInteraction = useResetSupportInteraction();
const { startNewInteraction } = useManageSupportInteraction();

const handleFeedbackClick = ( value: number ) => {
setStartedFeedback( true );
Expand Down Expand Up @@ -66,10 +63,6 @@ const HelpCenterFeedbackForm = ( { postId }: { postId: number } ) => {
generateContactOnClickEvent( 'chat', 'calypso_helpcenter_feedback_contact_support' );
if ( isUserEligibleForPaidSupport ) {
await resetSupportInteraction();
startNewInteraction( {
event_source: 'help-center',
event_external_id: uuidv4(),
} );
navigate( '/odie' );
}
};
Expand Down
7 changes: 0 additions & 7 deletions packages/help-center/src/components/help-center-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import { recordTracksEvent } from '@automattic/calypso-analytics';
import { Gridicon } from '@automattic/components';
import { EllipsisMenu } from '@automattic/odie-client';
import { useManageSupportInteraction } from '@automattic/odie-client/src/data';
import { clearHelpCenterZendeskConversationStarted } from '@automattic/odie-client/src/utils/storage-utils';
import { CardHeader, Button, Flex } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
Expand All @@ -11,7 +10,6 @@ import { closeSmall, chevronUp, lineSolid, commentContent, page, Icon } from '@w
import { useI18n } from '@wordpress/react-i18n';
import clsx from 'clsx';
import { Route, Routes, useLocation, useSearchParams } from 'react-router-dom';
import { v4 as uuidv4 } from 'uuid';
import { usePostByUrl } from '../hooks';
import { useResetSupportInteraction } from '../hooks/use-reset-support-interaction';
import { DragIcon } from '../icons';
Expand Down Expand Up @@ -68,14 +66,9 @@ const SupportModeTitle = () => {
const ChatEllipsisMenu = () => {
const { __ } = useI18n();
const resetSupportInteraction = useResetSupportInteraction();
const { startNewInteraction } = useManageSupportInteraction();

const clearChat = async () => {
await resetSupportInteraction();
startNewInteraction( {
event_source: 'help-center',
event_external_id: uuidv4(),
} );
clearHelpCenterZendeskConversationStarted();
recordTracksEvent( 'calypso_inlinehelp_clear_conversation' );
};
Expand Down
15 changes: 15 additions & 0 deletions packages/help-center/src/hooks/use-action-hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const useActionHooks = () => {
);
},
},

/**
* Open Help Center.
*/
Expand All @@ -37,6 +38,7 @@ export const useActionHooks = () => {
setShowHelpCenter( true );
},
},

/**
* Open to Wapuu chat.
*/
Expand All @@ -49,6 +51,19 @@ export const useActionHooks = () => {
setShowHelpCenter( true );
},
},

/**
* Open to Chat with Happiness Engineer.
*/
{
condition() {
return queryParams.get( 'help-center' ) === 'happiness-engineer';
},
action() {
setNavigateToRoute( '/odie?provider=zendesk' );
setShowHelpCenter( true );
},
},
];

useEffect( () => {
Expand Down
17 changes: 10 additions & 7 deletions packages/help-center/src/hooks/use-reset-support-interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { HelpCenterSelect } from '@automattic/data-stores';
import { HELP_CENTER_STORE } from '@automattic/help-center/src/stores';
import { useManageSupportInteraction } from '@automattic/odie-client/src/data';
import { useQueryClient } from '@tanstack/react-query';
import { useSelect, useDispatch } from '@wordpress/data';
import { useSelect } from '@wordpress/data';
import { v4 as uuidv4 } from 'uuid';

export const useResetSupportInteraction = () => {
const { currentSupportInteraction } = useSelect( ( select ) => {
Expand All @@ -11,19 +12,21 @@ export const useResetSupportInteraction = () => {
currentSupportInteraction: store.getCurrentSupportInteraction(),
};
}, [] );
const { setCurrentSupportInteraction } = useDispatch( HELP_CENTER_STORE );
const { resolveInteraction } = useManageSupportInteraction();
const { startNewInteraction, resolveInteraction } = useManageSupportInteraction();
const queryClient = useQueryClient();

const reset = async () => {
return async () => {
if ( currentSupportInteraction ) {
resolveInteraction( { interactionId: currentSupportInteraction.uuid } );

await queryClient.invalidateQueries( {
queryKey: [ 'support-interactions', 'get-interactions', 'help-center' ],
} );
setCurrentSupportInteraction( null );

return await startNewInteraction( {
event_source: 'help-center',
event_external_id: uuidv4(),
} );
}
};

return reset;
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const JumpToRecent = ( {
if (
! containerReference.current ||
isMinimized ||
chat.messages.length < 2 ||
! chat.messages.length ||
chat.status !== 'loaded'
) {
return;
Expand Down
78 changes: 66 additions & 12 deletions packages/odie-client/src/components/message/messages-container.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { useResetSupportInteraction } from '@automattic/help-center/src/hooks/use-reset-support-interaction';
import { getShortDateString } from '@automattic/i18n-utils';
import { Spinner } from '@wordpress/components';
import { useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { ThumbsDown } from '../../assets/thumbs-down';
import { useOdieAssistantContext } from '../../context';
import { useAutoScroll, useZendeskMessageListener } from '../../hooks';
import {
useAutoScroll,
useCreateZendeskConversation,
useZendeskMessageListener,
} from '../../hooks';
import { getOdieInitialMessage } from '../../utils';
import { DislikeFeedbackMessage } from './dislike-feedback-message';
import { JumpToRecent } from './jump-to-recent';
Expand All @@ -18,6 +24,7 @@ const DislikeThumb = () => {
</div>
);
};

const LoadingChatSpinner = () => {
return (
<div className="chatbox-loading-chat__spinner">
Expand All @@ -38,14 +45,59 @@ interface ChatMessagesProps {
}

export const MessagesContainer = ( { currentUser }: ChatMessagesProps ) => {
const { chat, botNameSlug } = useOdieAssistantContext();
const [ chatMessagesLoaded, setChatLoaded ] = useState( false );
const { chat, botNameSlug, isChatLoaded } = useOdieAssistantContext();
const createZendeskConversation = useCreateZendeskConversation();
const resetSupportInteraction = useResetSupportInteraction();
const [ searchParams, setSearchParams ] = useSearchParams();
const isForwardingToZendesk =
searchParams.get( 'provider' ) === 'zendesk' && chat.provider !== 'zendesk';
const [ hasForwardedToZendesk, setHasForwardedToZendesk ] = useState( false );
const [ chatMessagesLoaded, setChatMessagesLoaded ] = useState( false );
const messagesContainerRef = useRef< HTMLDivElement >( null );
useZendeskMessageListener();
useAutoScroll( messagesContainerRef );

useEffect( () => {
if ( isForwardingToZendesk || hasForwardedToZendesk ) {
return;
}

( chat?.status === 'loaded' || chat?.status === 'closed' ) && setChatMessagesLoaded( true );
}, [ chat, isForwardingToZendesk, hasForwardedToZendesk ] );

/**
* Handle the case where we are forwarding to Zendesk.
*/
useEffect( () => {
( chat?.status === 'loaded' || chat?.status === 'closed' ) && setChatLoaded( true );
}, [ chat ] );
if (
isForwardingToZendesk &&
! hasForwardedToZendesk &&
! chat.conversationId &&
createZendeskConversation &&
resetSupportInteraction &&
isChatLoaded
) {
searchParams.delete( 'provider' );
searchParams.set( 'direct-zd-chat', '1' );
setSearchParams( searchParams );
setHasForwardedToZendesk( true );

resetSupportInteraction().then( ( interaction ) => {
if ( isChatLoaded ) {
createZendeskConversation( true, interaction?.uuid ).then( () => {
setChatMessagesLoaded( true );
} );
}
} );
}
}, [
isForwardingToZendesk,
hasForwardedToZendesk,
isChatLoaded,
chat?.conversationId,
resetSupportInteraction,
createZendeskConversation,
] );

// Used to apply the correct styling on messages
const isNextMessageFromSameSender = ( currentMessage: string, nextMessage: string ) => {
Expand All @@ -60,13 +112,15 @@ export const MessagesContainer = ( { currentUser }: ChatMessagesProps ) => {
<LoadingChatSpinner />
) : (
<>
<ChatMessage
message={ getOdieInitialMessage( botNameSlug ) }
key={ 0 }
currentUser={ currentUser }
isNextMessageFromSameSender={ false }
displayChatWithSupportLabel={ false }
/>
{ ( chat.odieId || chat.provider === 'odie' ) && (
<ChatMessage
message={ getOdieInitialMessage( botNameSlug ) }
key={ 0 }
currentUser={ currentUser }
isNextMessageFromSameSender={ false }
displayChatWithSupportLabel={ false }
/>
) }
{ chat.messages.map( ( message, index ) => (
<ChatMessage
message={ message }
Expand Down
Loading

0 comments on commit afe6165

Please sign in to comment.