Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help Center: add Zendesk to Odie Client #94799

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/data-stores/src/help-center/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ export const setShowHelpCenter = function* ( show: boolean ) {
} as const;
};

export const setSupportProvider = ( supportProvider: 'odie' | 'zendesk' ) =>
( {
type: 'HELP_CENTER_SET_SUPPORT_PROVIDER',
supportProvider,
} ) as const;

export const setSubject = ( subject: string ) =>
( {
type: 'HELP_CENTER_SET_SUBJECT',
Expand Down Expand Up @@ -145,6 +151,7 @@ export type HelpCenterAction =
| ReturnType<
| typeof setShowMessagingLauncher
| typeof setShowMessagingWidget
| typeof setSupportProvider
| typeof setSubject
| typeof resetStore
| typeof receiveHasSeenWhatsNewModal
Expand Down
8 changes: 7 additions & 1 deletion packages/data-stores/src/help-center/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ export function register(): typeof STORE_KEY {
reducer,
controls: { ...controls, ...wpcomRequestControls },
selectors,
persist: [ 'message', 'userDeclaredSite', 'userDeclaredSiteUrl', 'subject' ],
persist: [
'supportProvider',
'message',
'userDeclaredSite',
'userDeclaredSiteUrl',
'subject',
],
} );
isRegistered = true;
}
Expand Down
11 changes: 11 additions & 0 deletions packages/data-stores/src/help-center/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,18 @@ const odieBotNameSlug: Reducer< string | undefined, HelpCenterAction > = ( state
return state;
};

const supportProvider: Reducer< 'odie' | 'zendesk', HelpCenterAction > = (
state = 'odie',
action
) => {
if ( action.type === 'HELP_CENTER_SET_SUPPORT_PROVIDER' ) {
return action.supportProvider;
}
return state;
};

const reducer = combineReducers( {
supportProvider,
showHelpCenter,
showMessagingLauncher,
showMessagingWidget,
Expand Down
1 change: 1 addition & 0 deletions packages/data-stores/src/help-center/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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 getSupportProvider = ( state: State ) => state.supportProvider;
export const getSubject = ( state: State ) => state.subject;
export const getMessage = ( state: State ) => state.message;
export const getUserDeclaredSiteUrl = ( state: State ) => state.userDeclaredSiteUrl;
Expand Down
46 changes: 35 additions & 11 deletions packages/help-center/src/components/help-center-odie.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,43 @@
/**
* Styles for '/odie' route.
*/
.help-center .help-center__container .help-center__container-content .help-center__container-content-wrapper .help-center__container-content-odie {
display: flex;
height: 100%;
max-height: 752px;
flex-direction: column;
max-width: 410px;
padding: 0;
.help-center__container-content-odie {
padding-bottom: 72px;
}

.help-center__container-footer.chat-footer {
background-color: var(--studio-white);
position: fixed;
bottom: 0;
left: 0;
right: 0;
border-top: 1px solid var(--studio-gray-5);

.odie-chat-message-input-container {
border-radius: 0;
.help-center__container-odie-send-button {
width: 100%;
display: flex;
flex-direction: row;
gap: 10px;

textarea {
box-sizing: border-box;
height: 40px;
padding: 10px 16px;
border: 1px solid var(--studio-gray-5);
border-radius: 2px;
flex: 2;
}

@media screen and (max-width: 660px) {
max-width: 100%;
button {
box-sizing: border-box;
display: flex;
width: 40px;
height: 40px;
padding: 8px 10px;
justify-content: center;
align-items: center;
background-color: var(--studio-wordpress-blue);
border-radius: 2px;
}
}
}
100 changes: 68 additions & 32 deletions packages/help-center/src/components/help-center-odie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,31 @@
import { recordTracksEvent } from '@automattic/calypso-analytics';
import { Gridicon } from '@automattic/components';
import OdieAssistantProvider, {
OdieAssistant,
useOdieAssistantContext,
EllipsisMenu,
isOdieAllowedBot,
useOdieSendMessage,
MessagesContainer,
} from '@automattic/odie-client';
import { useSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { useI18n } from '@wordpress/react-i18n';
import React, { useCallback } from 'react';
import { useNavigate, Navigate } from 'react-router-dom';
import React, {
useCallback,
useEffect,
useState,
type KeyboardEvent,
type MouseEvent,
} from 'react';
import { Navigate } from 'react-router-dom';
import PopoverMenuItem from 'calypso/components/popover-menu/item';
import { useHelpCenterContext } from '../contexts/HelpCenterContext';
import { useShouldUseWapuu } from '../hooks';
import { SendIcon } from '../icons/send';
import { HELP_CENTER_STORE } from '../stores';
/**
* Internal Dependencies
*/
import { BackButtonHeader } from './back-button';
import { ExtraContactOptions } from './help-center-extra-contact-option';
import './help-center-odie.scss';
import type { HelpCenterSelect } from '@automattic/data-stores';
import type { OdieAllowedBots } from '@automattic/odie-client/src/types/index';
Expand All @@ -33,6 +40,53 @@ interface ProtectedRouteProps {
children: React.ReactNode;
}

export const HelpCenterSendButton = () => {
const { setSupportProvider } = useDispatch( HELP_CENTER_STORE );
const { provider } = useOdieAssistantContext();
const [ messageString, setMessageString ] = useState< string >( '' );
const { mutateAsync: sendOdieMessage } = useOdieSendMessage();

useEffect( () => {
setSupportProvider( provider );
}, [ provider ] );

const handleSendMessage = async (
event: MouseEvent< HTMLButtonElement > | KeyboardEvent< HTMLTextAreaElement >
) => {
const isButtonClick = event.type === 'click';
const isEnterKey = ( event as KeyboardEvent ).key === 'Enter' && ! event.shiftKey;

if ( messageString.trim().length > 0 && ( isEnterKey || isButtonClick ) ) {
event.preventDefault();
setMessageString( '' );
await sendOdieMessage( {
message: {
content: messageString as string,
role: 'user',
type: 'message',
},
} );
}
};

return (
<div className="help-center__container-odie-send-button">
<textarea
className="odie-send-message-input"
rows={ 1 }
value={ messageString }
onChange={ ( event: React.ChangeEvent< HTMLTextAreaElement > ) =>
setMessageString( event.currentTarget.value )
}
onKeyDown={ handleSendMessage }
/>
<button onClick={ handleSendMessage }>
<SendIcon />
</button>
</div>
);
};

// Prevent not eligible users from accessing odie/wapuu.
const ProtectedRoute: React.FC< ProtectedRouteProps > = ( {
condition,
Expand Down Expand Up @@ -79,7 +133,6 @@ export function HelpCenterOdie( {
isUserEligible: boolean;
searchTerm: string;
} ): JSX.Element {
const navigate = useNavigate();
const shouldUseWapuu = useShouldUseWapuu();
const preventOdieAccess = ! shouldUseWapuu && ! isUserEligible;
const { currentUser, site } = useHelpCenterContext();
Expand All @@ -98,23 +151,6 @@ export function HelpCenterOdie( {
};
}, [] );

const navigateToSupportDocs = useCallback(
( blogId: string, postId: string, title: string, link: string ) => {
navigate(
`/post?blogId=${ blogId }&postId=${ postId }&title=${ title }&link=${ link }&backUrl=/odie`
);
},
[ navigate ]
);

const navigateToContactOptions = useCallback( () => {
if ( isUserEligible ) {
navigate( '/contact-options' );
} else {
navigate( '/contact-form?mode=FORUM' );
}
}, [ navigate, isUserEligible ] );

const trackEvent = useCallback(
( eventName: string, properties: Record< string, unknown > = {} ) => {
recordTracksEvent( eventName, properties );
Expand All @@ -135,18 +171,18 @@ export function HelpCenterOdie( {
logger={ trackEvent }
loggerEventNamePrefix="calypso_odie"
selectedSiteId={ site?.ID as number }
extraContactOptions={ <ExtraContactOptions isUserEligible={ isUserEligible } /> }
navigateToContactOptions={ navigateToContactOptions }
navigateToSupportDocs={ navigateToSupportDocs }
isUserEligible={ isUserEligible }
>
<div className="help-center__container-odie-header">
<BackButtonHeader className="help-center__container-odie-back-button">
<OdieEllipsisMenu />
</BackButtonHeader>
</div>
<div className="help-center__container-content-odie">
<div className="help-center__container-odie-header">
<BackButtonHeader className="help-center__container-odie-back-button">
<OdieEllipsisMenu />
</BackButtonHeader>
</div>
<OdieAssistant />
<MessagesContainer currentUser={ currentUser } />
</div>
<div className="help-center__container-footer chat-footer">
<HelpCenterSendButton />
</div>
</OdieAssistantProvider>
</ProtectedRoute>
Expand Down
48 changes: 35 additions & 13 deletions packages/help-center/src/components/help-center.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* External Dependencies
*/
import { initializeAnalytics } from '@automattic/calypso-analytics';
import { useZendeskMessagingBindings, useLoadZendeskMessaging } from '@automattic/zendesk-client';
import { useSelect } from '@wordpress/data';
import { useLoadZendeskMessaging, useSmooch } from '@automattic/zendesk-client';
import { useSelect, useDispatch } from '@wordpress/data';
import { createPortal, useEffect, useRef } from '@wordpress/element';
/**
* Internal Dependencies
Expand All @@ -28,13 +28,15 @@ const HelpCenter: React.FC< Container > = ( {
currentRoute = window.location.pathname + window.location.search,
} ) => {
const portalParent = useRef( document.createElement( 'div' ) ).current;
const { isHelpCenterShown, isMinimized } = useSelect( ( select ) => {
const { isHelpCenterShown, isMinimized, supportProvider } = useSelect( ( select ) => {
const helpCenterSelect: HelpCenterSelect = select( HELP_CENTER_STORE );
return {
isHelpCenterShown: helpCenterSelect.isHelpCenterShown(),
isMinimized: helpCenterSelect.getIsMinimized(),
supportProvider: helpCenterSelect.getSupportProvider(),
};
}, [] );
const { setUnreadCount } = useDispatch( HELP_CENTER_STORE );

const { currentUser } = useHelpCenterContext();

Expand All @@ -46,14 +48,31 @@ const HelpCenter: React.FC< Container > = ( {

useActionHooks();

const { hasActiveChats, isEligibleForChat } = useChatStatus();
const { isEligibleForChat } = useChatStatus();
const { isMessagingScriptLoaded } = useLoadZendeskMessaging(
'zendesk_support_chat_key',
( isHelpCenterShown && isEligibleForChat ) || hasActiveChats,
isEligibleForChat || hasActiveChats
isHelpCenterShown && isEligibleForChat,
isEligibleForChat
);
const { init, initSmooch, destroy, addUnreadCountListener } = useSmooch();
const ref = useRef( null );

useZendeskMessagingBindings( HELP_CENTER_STORE, hasActiveChats, isMessagingScriptLoaded );
useEffect( () => {
if ( isMessagingScriptLoaded && ref?.current ) {
initSmooch( ref.current );
}
return () => {
destroy();
};
}, [ isMessagingScriptLoaded, ref?.current ] );

useEffect( () => {
if ( init && supportProvider ) {
addUnreadCountListener( ( unreadCount: number ) => {
setUnreadCount( unreadCount );
} );
}
}, [ init, setUnreadCount, supportProvider ] );

const openingCoordinates = useOpeningCoordinates( isHelpCenterShown, isMinimized );

Expand All @@ -73,12 +92,15 @@ const HelpCenter: React.FC< Container > = ( {
}, [ portalParent, handleClose ] );

return createPortal(
<HelpCenterContainer
handleClose={ handleClose }
hidden={ hidden }
currentRoute={ currentRoute }
openingCoordinates={ openingCoordinates }
/>,
<>
<HelpCenterContainer
handleClose={ handleClose }
hidden={ hidden }
currentRoute={ currentRoute }
openingCoordinates={ openingCoordinates }
/>
<div ref={ ref } style={ { display: 'none' } }></div>
</>,
portalParent
);
};
Expand Down
10 changes: 10 additions & 0 deletions packages/help-center/src/icons/send.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const SendIcon = () => (
<svg width="24" height="24" viewBox="0 0 16 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M2.33236 0.748331C1.30236 0.322331 0.272363 1.35533 0.700363 2.38433L2.40236 6.31433L9.88336 6.88933C10.0064 6.89933 10.0064 7.07933 9.88336 7.08933L2.40036 7.66433L0.700363 11.5733C0.271363 12.6023 1.30236 13.6353 2.33236 13.2093L14.5974 8.13333C15.6274 7.70733 15.6274 6.24933 14.5974 5.82333L2.33236 0.748331Z"
fill="white"
/>
</svg>
);
Loading
Loading