Skip to content

Commit

Permalink
[Odie] Give Wapuu a chance (#98419)
Browse files Browse the repository at this point in the history
* [Odie] Give Wapuu a chance

* Fix thumbs down issue

* Rename variable from removeDislike to removeDislikeStatus

* Fix autoscroll when using the experiment

* HasUserEverEscalated was lost during merge/conflicts

* Fix TSC error

* Separate logic for show extra contact options and show direct escalation link
  • Loading branch information
AllTerrainDeveloper authored Jan 24, 2025
1 parent 1da852b commit 7cc0499
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useI18n } from '@wordpress/react-i18n';
import clsx from 'clsx';
import Markdown from 'react-markdown';
import { useOdieAssistantContext } from '../../context';
import { zendeskMessageConverter } from '../../utils';
import ChatWithSupportLabel from '../chat-with-support';
import CustomALink from './custom-a-link';
Expand All @@ -24,6 +25,7 @@ export const MessageContent = ( {
displayChatWithSupportLabel?: boolean;
} ) => {
const { __ } = useI18n();
const { experimentVariationName } = useOdieAssistantContext();
const messageClasses = clsx(
'odie-chatbox-message',
`odie-chatbox-message-${ message.role }`,
Expand All @@ -35,6 +37,9 @@ export const MessageContent = ( {
isNextMessageFromSameSender && 'next-chat-message-same-sender'
);

const stopConflatingNegativeRatingWithContactSupport =
experimentVariationName === 'give_wapuu_a_chance';

const isMessageWithOnlyText =
message.context?.flags?.hide_disclaimer_content ||
message.context?.question_tags?.inquiry_type === 'user-is-greeting';
Expand Down Expand Up @@ -97,7 +102,8 @@ export const MessageContent = ( {
</p>
</div>
) }
{ message.type === 'dislike-feedback' && <DislikeFeedbackMessage /> }
{ ! stopConflatingNegativeRatingWithContactSupport &&
message.type === 'dislike-feedback' && <DislikeFeedbackMessage /> }
</div>
</div>
{ displayChatWithSupportLabel && <ChatWithSupportLabel /> }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ interface ChatMessagesProps {
}

export const MessagesContainer = ( { currentUser }: ChatMessagesProps ) => {
const { chat, botNameSlug, isChatLoaded } = useOdieAssistantContext();
const { chat, botNameSlug, experimentVariationName, isChatLoaded } = useOdieAssistantContext();
const createZendeskConversation = useCreateZendeskConversation();
const resetSupportInteraction = useResetSupportInteraction();
const [ searchParams, setSearchParams ] = useSearchParams();
Expand Down Expand Up @@ -104,6 +104,12 @@ export const MessagesContainer = ( { currentUser }: ChatMessagesProps ) => {
return currentMessage === nextMessage;
};

const removeDislikeStatus = experimentVariationName === 'give_wapuu_a_chance';

const availableStatusWithFeedback = removeDislikeStatus
? [ 'sending', 'transfer' ]
: [ 'sending', 'dislike', 'transfer' ];

return (
<>
<div className="chatbox-messages" ref={ messagesContainerRef }>
Expand Down Expand Up @@ -134,8 +140,8 @@ export const MessagesContainer = ( { currentUser }: ChatMessagesProps ) => {
/>
) ) }
<JumpToRecent containerReference={ messagesContainerRef } />
{ chat.status === 'dislike' && <DislikeThumb /> }
{ [ 'sending', 'dislike', 'transfer' ].includes( chat.status ) && (
{ chat.status === 'dislike' && ! removeDislikeStatus && <DislikeThumb /> }
{ availableStatusWithFeedback.includes( chat.status ) && (
<div className="odie-chatbox__action-message">
{ chat.status === 'sending' && <ThinkingPlaceholder /> }
{ chat.status === 'dislike' && <DislikeFeedbackMessage /> }
Expand Down
27 changes: 22 additions & 5 deletions packages/odie-client/src/components/message/user-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,34 @@ export const UserMessage = ( {
message: Message;
isMessageWithoutEscalationOption?: boolean;
} ) => {
const { isUserEligibleForPaidSupport, trackEvent, chat } = useOdieAssistantContext();
const {
isUserEligibleForPaidSupport,
hasUserEverEscalatedToHumanSupport,
trackEvent,
chat,
experimentVariationName,
} = useOdieAssistantContext();

const hasCannedResponse = message.context?.flags?.canned_response;
const isRequestingHumanSupport = message.context?.flags?.forward_to_human_support;
const isRequestingHumanSupport = message.context?.flags?.forward_to_human_support ?? false;
const hasFeedback = !! message?.rating_value;
const isBot = message.role === 'bot';
const isConnectedToZendesk = chat?.provider === 'zendesk';
const isPositiveFeedback =
hasFeedback && message && message.rating_value && +message.rating_value === 1;
const showExtraContactOptions =
( hasFeedback && ! isPositiveFeedback ) || isRequestingHumanSupport;

const isExperimentGiveWapuuAChance = experimentVariationName === 'give_wapuu_a_chance';

let showExtraContactOptions = false;
if ( isExperimentGiveWapuuAChance ) {
showExtraContactOptions = isRequestingHumanSupport;
} else {
showExtraContactOptions = ( hasFeedback && ! isPositiveFeedback ) || isRequestingHumanSupport;
}

const showDirectEscalationLink = isExperimentGiveWapuuAChance
? hasUserEverEscalatedToHumanSupport
: ! ( hasFeedback && ! isPositiveFeedback ) || isRequestingHumanSupport;

const forwardMessage = isUserEligibleForPaidSupport
? ODIE_FORWARD_TO_ZENDESK_MESSAGE
Expand Down Expand Up @@ -83,7 +100,7 @@ export const UserMessage = ( {
}
) }
</div>
{ ! showExtraContactOptions && <DirectEscalationLink messageId={ message.message_id } /> }
{ showDirectEscalationLink && <DirectEscalationLink messageId={ message.message_id } /> }
{ ! isConnectedToZendesk && (
<WasThisHelpfulButtons message={ message } isDisliked={ isDisliked } />
) }
Expand Down
17 changes: 17 additions & 0 deletions packages/odie-client/src/context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,15 @@ export const OdieAssistantContext = createContext< OdieAssistantContextInterface
canConnectToZendesk: false,
clearChat: noop,
currentUser: { display_name: 'Me' },
experimentVariationName: null,
hasUserEverEscalatedToHumanSupport: false,
isChatLoaded: false,
isMinimized: false,
isUserEligibleForPaidSupport: false,
odieBroadcastClientId: '',
setChat: noop,
setChatStatus: noop,
setExperimentVariationName: noop,
setMessageLikedStatus: noop,
setWaitAnswerToFirstMessageFromHumanSupport: noop,
trackEvent: noop,
Expand Down Expand Up @@ -84,12 +87,23 @@ export const OdieAssistantProvider: React.FC< OdieAssistantProviderProps > = ( {
};
}, [] );

const [ experimentVariationName, setExperimentVariationName ] = useState<
string | null | undefined
>( null );

/**
* The main chat thread.
* This is where we manage the state of the chat.
*/
const { mainChatState, setMainChatState } = useGetCombinedChat( canConnectToZendesk );

/**
* Has the user ever escalated to get human support?
*/
const hasUserEverEscalatedToHumanSupport = mainChatState?.messages.some(
( message ) => message.context?.flags?.forward_to_human_support
);

/**
* Tracking event.
* Handler to make sure all requests are the same.
Expand Down Expand Up @@ -176,13 +190,16 @@ export const OdieAssistantProvider: React.FC< OdieAssistantProviderProps > = ( {
extraContactOptions,
isChatLoaded,
isMinimized,
experimentVariationName,
isUserEligibleForPaidSupport,
canConnectToZendesk,
hasUserEverEscalatedToHumanSupport,
odieBroadcastClientId,
selectedSiteId,
selectedSiteURL,
userFieldMessage,
setChatStatus,
setExperimentVariationName,
setMessageLikedStatus,
setWaitAnswerToFirstMessageFromHumanSupport,
trackEvent,
Expand Down
13 changes: 10 additions & 3 deletions packages/odie-client/src/data/use-send-odie-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,15 @@ export const useSendOdieMessage = () => {
const internal_message_id = generateUUID();
const queryClient = useQueryClient();

const { botNameSlug, selectedSiteId, version, setChat, odieBroadcastClientId, setChatStatus } =
useOdieAssistantContext();
const {
botNameSlug,
selectedSiteId,
version,
setChat,
odieBroadcastClientId,
setChatStatus,
setExperimentVariationName,
} = useOdieAssistantContext();

const addMessage = ( message: Message | Message[], props?: Partial< Chat > ) => {
setChat( ( prevChat ) => ( {
Expand Down Expand Up @@ -111,7 +118,7 @@ export const useSendOdieMessage = () => {
type: 'message',
context: returnedChat.messages[ 0 ].context,
};

setExperimentVariationName( returnedChat.experiment_name );
addMessage( botMessage, { odieId: returnedChat.chat_id } );
broadcastOdieMessage( botMessage, odieBroadcastClientId );
},
Expand Down
6 changes: 5 additions & 1 deletion packages/odie-client/src/hooks/use-auto-scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { RefObject, useEffect, useRef } from 'react';
import { useOdieAssistantContext } from '../context';

export const useAutoScroll = ( messagesContainerRef: RefObject< HTMLDivElement > ) => {
const { chat } = useOdieAssistantContext();
const { chat, experimentVariationName } = useOdieAssistantContext();
const debounceTimeoutRef = useRef< number >( 500 );
const debounceTimeoutIdRef = useRef< number | null >( null );
const lastChatStatus = useRef< string | null >( null );
Expand All @@ -12,6 +12,10 @@ export const useAutoScroll = ( messagesContainerRef: RefObject< HTMLDivElement >
return;
}

if ( experimentVariationName === 'give_wapuu_a_chance' && chat.status === 'dislike' ) {
return;
}

if ( debounceTimeoutIdRef.current ) {
clearTimeout( debounceTimeoutIdRef.current );
}
Expand Down
10 changes: 9 additions & 1 deletion packages/odie-client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export type OdieAssistantContextInterface = {
chat: Chat;
clearChat: () => void;
currentUser: CurrentUser;
experimentVariationName: string | undefined | null;
hasUserEverEscalatedToHumanSupport: boolean;
isMinimized?: boolean;
isUserEligibleForPaidSupport: boolean;
extraContactOptions?: ReactNode;
Expand All @@ -18,6 +20,7 @@ export type OdieAssistantContextInterface = {
selectedSiteURL?: string | null;
userFieldMessage?: string | null;
waitAnswerToFirstMessageFromHumanSupport: boolean;
setExperimentVariationName: ( variationName: string | null | undefined ) => void;
setMessageLikedStatus: ( message: Message, liked: boolean ) => void;
setChat: ( chat: Chat | SetStateAction< Chat > ) => void;
setChatStatus: ( status: ChatStatus ) => void;
Expand Down Expand Up @@ -156,7 +159,12 @@ export type Message = {

export type ChatStatus = 'loading' | 'loaded' | 'sending' | 'dislike' | 'transfer' | 'closed';

export type ReturnedChat = { chat_id: number; messages: Message[]; wpcom_user_id: number };
export type ReturnedChat = {
chat_id: number;
messages: Message[];
wpcom_user_id: number;
experiment_name: string | undefined | null;
};

export type OdieChat = {
messages: Message[];
Expand Down

0 comments on commit 7cc0499

Please sign in to comment.