Skip to content

Commit b02caa1

Browse files
authored
Merge pull request #4 from Cognigy/bug/74555-fix-sessions-related-issues
Improving sessions logic and start conversation button
2 parents d48395d + 554455e commit b02caa1

File tree

18 files changed

+194
-101
lines changed

18 files changed

+194
-101
lines changed

cypress/e2e/engagement.cy.ts

+6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ describe("Engagement Message", () => {
7979
unreadMessages: {
8080
enablePreview: false,
8181
},
82+
homeScreen: {
83+
enabled: false,
84+
}
8285
},
8386
});
8487
cy.get("[data-cognigy-webchat-toggle]").click().click();
@@ -137,6 +140,9 @@ describe("Engagement Message", () => {
137140
unreadMessages: {
138141
enablePreview: false,
139142
},
143+
homeScreen: {
144+
enabled: false,
145+
}
140146
},
141147
});
142148
cy.wait(500);

src/common/interfaces/message.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface IBaseMessage {
66
prevMessage?: IMessage;
77
source: string;
88
text?: string;
9-
timestamp: number;
9+
timestamp?: number;
1010
}
1111

1212
export interface IUserMessage extends IBaseMessage {

src/webchat-ui/components/WebchatUI.tsx

+50-16
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ export interface WebchatUIProps {
128128
fileUploadError: boolean;
129129
onSetFileUploadError: (hasError: boolean) => void;
130130

131+
onShowChatScreen: () => void;
131132
showPrevConversations: boolean;
132133
onSetShowPrevConversations: (show: boolean) => void;
133134
prevConversations: PrevConversationsState;
@@ -740,31 +741,63 @@ export class WebchatUI extends React.PureComponent<
740741
options,
741742
});
742743
} else {
744+
this.props.onSwitchSession();
743745
this.props.onSendMessage(text, data, options);
744746
}
745747
};
746748

747-
handleStartConversation = () => {
748-
if (!this.props.config.settings.privacyNotice.enabled || this.props.hasAcceptedTerms) {
749-
const { initialSessionId } = this.props.config;
750-
if (!initialSessionId) {
751-
this.props.onSwitchSession();
752-
}
753-
if (initialSessionId && initialSessionId !== this.props.currentSession) {
754-
this.props.onSwitchSession(initialSessionId);
755-
}
749+
handleSendActionButtonMessageFromTeaser = (
750+
text?: string,
751+
data?: any,
752+
options?: Partial<ISendMessageOptions>,
753+
) => {
754+
this.props.onSetShowHomeScreen(false);
755+
this.props.onSetShowChatOptionsScreen(false);
756+
757+
if (this.props.config.settings.privacyNotice.enabled && !this.props.hasAcceptedTerms) {
758+
this.props.onSetStoredMessage({
759+
text,
760+
data,
761+
options,
762+
});
763+
} else {
764+
this.props.onShowChatScreen();
765+
this.props.onSendMessage(text, data, options);
756766
}
767+
};
757768

758-
if (!this.props.open) this.props.onToggle();
769+
handleStartConversation = () => {
759770
this.props.onSetShowHomeScreen(false);
760771
this.props.onSetShowChatOptionsScreen(false);
772+
773+
const showPrivacyScreen = this.props.config.settings.privacyNotice.enabled && !this.props.hasAcceptedTerms;
774+
if (!showPrivacyScreen) {
775+
this.props.onShowChatScreen();
776+
}
761777
};
762778

779+
handleFabClick = () => {
780+
this.props.onToggle();
781+
782+
const homeScreenEnabled = this.props.config.settings.homeScreen.enabled === true;
783+
if (homeScreenEnabled) {
784+
this.setState({ lastUnseenMessageText: "" });
785+
} else {
786+
this.handleStartConversation();
787+
}
788+
}
789+
763790
openConversationFromTeaser = () => {
764-
// in this case we always open to current session
765791
this.props.onToggle();
766792
this.props.onSetShowHomeScreen(false);
767793
this.props.onSetShowChatOptionsScreen(false);
794+
795+
const showPrivacyScreen = this.props.config.settings.privacyNotice.enabled && !this.props.hasAcceptedTerms;
796+
if (showPrivacyScreen) {
797+
this.setState({ lastUnseenMessageText: "" });
798+
} else {
799+
this.props.onShowChatScreen();
800+
}
768801
};
769802

770803
render() {
@@ -800,6 +833,7 @@ export class WebchatUI extends React.PureComponent<
800833
onSetHasGivenRating,
801834
onSetShowPrevConversations,
802835
onSetShowChatOptionsScreen,
836+
onShowChatScreen,
803837
onSwitchSession,
804838
requestRatingScreenTitle,
805839
customRatingTitle,
@@ -946,7 +980,7 @@ export class WebchatUI extends React.PureComponent<
946980
config={config}
947981
onEmitAnalytics={onEmitAnalytics}
948982
onSendActionButtonMessage={
949-
this.handleSendActionButtonMessage
983+
this.handleSendActionButtonMessageFromTeaser
950984
}
951985
onHideTeaserMessage={onHideTeaserMessage}
952986
wasOpen={wasOpen}
@@ -974,7 +1008,7 @@ export class WebchatUI extends React.PureComponent<
9741008
) : (
9751009
<FAB
9761010
data-cognigy-webchat-toggle
977-
onClick={onToggle}
1011+
onClick={this.handleFabClick}
9781012
{...webchatToggleProps}
9791013
type="button"
9801014
className="webchat-toggle-button"
@@ -1025,6 +1059,7 @@ export class WebchatUI extends React.PureComponent<
10251059
requestRatingEventBannerText,
10261060
showRatingScreen,
10271061
onShowRatingScreen,
1062+
onShowChatScreen,
10281063
onSwitchSession,
10291064
onClose,
10301065
onEmitAnalytics,
@@ -1072,14 +1107,12 @@ export class WebchatUI extends React.PureComponent<
10721107
};
10731108

10741109
const handleCloseAndReset = () => {
1075-
onSwitchSession();
10761110
onSetShowHomeScreen(true);
10771111
onClose();
10781112
// Restore focus to chat toggle button
10791113
this.chatToggleButtonRef?.current?.focus?.();
10801114
}
10811115

1082-
// TODO implement proper navigation solution
10831116
const handleOnGoBack = () => {
10841117
if (!showChatOptionsScreen && !showRatingScreen) {
10851118
onSetShowPrevConversations(false);
@@ -1100,13 +1133,13 @@ export class WebchatUI extends React.PureComponent<
11001133

11011134
const handleAcceptTerms = () => {
11021135
onAcceptTerms(this.props?.options?.userId || "");
1136+
onShowChatScreen();
11031137

11041138
const data = {
11051139
_cognigy: {
11061140
controlCommands: [{ type: "acceptPrivacyPolicy" }],
11071141
},
11081142
};
1109-
11101143
this.props.onSendMessage("", data);
11111144
};
11121145

@@ -1141,6 +1174,7 @@ export class WebchatUI extends React.PureComponent<
11411174
onSetShowPrevConversations={onSetShowPrevConversations}
11421175
onSwitchSession={onSwitchSession}
11431176
config={config}
1177+
currentSession={currentSession}
11441178
/>
11451179
);
11461180

src/webchat-ui/components/presentational/HomeScreen.tsx

+20-14
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,12 @@ export const HomeScreen: React.FC<IHomeScreenProps> = props => {
210210
}, [showHomeScreen]);
211211

212212
return (
213-
<HomeScreenRoot className="webchat-homescreen-root" aria-hidden={!showHomeScreen} ref={homeScreenRef}>
214-
<h2 className="sr-only">Home Screen</h2>
213+
<HomeScreenRoot
214+
className="webchat-homescreen-root"
215+
aria-hidden={!showHomeScreen}
216+
ref={homeScreenRef}
217+
>
218+
<h2 className="sr-only">Home Screen</h2>
215219
<HomeScreenContent className="webchat-homescreen-content" settings={config?.settings}>
216220
<HomeScreenHeader className="webchat-homescreen-header">
217221
{config?.settings?.layout?.logoUrl ? (
@@ -244,18 +248,20 @@ export const HomeScreen: React.FC<IHomeScreenProps> = props => {
244248
>
245249
{homeScreen.welcomeText || "Welcome to the Cognigy Webchat"}
246250
</HomeScreenTitle>
247-
<HomeScreenButtons className="webchat-homescreen-buttons">
248-
<ActionButtons
249-
size="large"
250-
showUrlIcon
251-
buttonClassName="webchat-homescreen-button"
252-
containerClassName="webchat-homescreen-button-container"
253-
payload={buttons}
254-
config={config}
255-
action={showHomeScreen ? onSendActionButtonMessage : undefined}
256-
onEmitAnalytics={onEmitAnalytics}
257-
/>
258-
</HomeScreenButtons>
251+
{homeScreen?.conversationStarters?.enabled && (
252+
<HomeScreenButtons className="webchat-homescreen-buttons">
253+
<ActionButtons
254+
size="large"
255+
showUrlIcon
256+
buttonClassName="webchat-homescreen-button"
257+
containerClassName="webchat-homescreen-button-container"
258+
payload={buttons}
259+
config={config}
260+
action={showHomeScreen ? onSendActionButtonMessage : undefined}
261+
onEmitAnalytics={onEmitAnalytics}
262+
/>
263+
</HomeScreenButtons>
264+
)}
259265
</HomeScreenContent>
260266
<HomeScreenActions className="webchat-homescreen-actions">
261267
<StartButton

src/webchat-ui/components/presentational/TeaserMessage.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export const TeaserMessage = (props: ITeaserMessageProps) => {
8888
wasOpen,
8989
} = props;
9090

91-
const buttons: IWebchatButton[] = config.settings.teaserMessage.conversationStarters.starters;
91+
const { teaserMessage } = config.settings;
92+
93+
const buttons: IWebchatButton[] = teaserMessage.conversationStarters.starters;
9294

9395
const isDesktopMedia = useMediaQuery({ query: "(min-width: 576px)" });
9496

@@ -155,7 +157,7 @@ export const TeaserMessage = (props: ITeaserMessageProps) => {
155157
{messageText}
156158
</Typography>
157159
</UnreadMessagePreview>
158-
{!wasOpen && (
160+
{!wasOpen && teaserMessage?.conversationStarters?.enabled && (
159161
<ButtonContainer className="webchat-teaser-message-action-buttons">
160162
<ActionButtons
161163
showUrlIcon

src/webchat-ui/components/presentational/previous-conversations/ConversationsList.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,14 @@ const StartButton = styled(PrimaryButton)(() => ({
5555

5656
interface IPrevConversationsListProps {
5757
config: IWebchatConfig;
58+
currentSession?: string;
5859
conversations: PrevConversationsState;
5960
onSetShowPrevConversations: (show: boolean) => void;
6061
onSwitchSession: (sessionId?: string, conversation?: PrevConversationsState[string]) => void;
6162
}
6263

6364
export const PrevConversationsList = (props: IPrevConversationsListProps) => {
64-
const { conversations, config, onSetShowPrevConversations, onSwitchSession } = props;
65+
const { conversations, config, onSetShowPrevConversations, onSwitchSession, currentSession } = props;
6566

6667
// we sort the conversation based on last message timestamp
6768
// result: the last updated conversation goes on top
@@ -91,7 +92,9 @@ export const PrevConversationsList = (props: IPrevConversationsListProps) => {
9192

9293
const switchSession = useCallback(
9394
(sessionId?: string, conversation?: PrevConversationsState[string]) => {
94-
onSwitchSession(sessionId, conversation);
95+
if (sessionId && sessionId !== currentSession) {
96+
onSwitchSession(sessionId, conversation);
97+
}
9598
onSetShowPrevConversations(false);
9699
},
97100
[],

src/webchat-ui/components/presentational/previous-conversations/ConversationsListItem.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { getAvatars, getLastMessagePreview, getParticipants, getRelativeTime } f
77
import { IWebchatConfig } from "../../../../common/interfaces/webchat-config";
88
import { PrevConversationsState } from "../../../../webchat/store/previous-conversations/previous-conversations-reducer";
99
import { Typography } from "@cognigy/chat-components";
10+
import { IMessage } from "../../../../common/interfaces/message";
1011

1112
const ListItem = styled.div(({ theme }) => ({
1213
display: "flex",
@@ -101,7 +102,9 @@ interface IConversationsListItemProps {
101102
export const ConversationsListItem = (props: IConversationsListItemProps) => {
102103
const { sessionId, conversation, config, index, switchSession } = props;
103104

104-
const avatars = getAvatars(conversation.messages);
105+
const messages = conversation.messages as IMessage[]
106+
107+
const avatars = getAvatars(messages);
105108

106109
const handleClick = () => {
107110
switchSession(sessionId, conversation);
@@ -136,12 +139,12 @@ export const ConversationsListItem = (props: IConversationsListItemProps) => {
136139
</Left>
137140
<Center>
138141
<CenterTitle variant="body-regular" component="div">
139-
{getLastMessagePreview(conversation.messages)}
142+
{getLastMessagePreview(messages)}
140143
</CenterTitle>
141144
<CenterMeta variant="title2-regular" component="div">
142-
<MetaNames>{getParticipants(conversation.messages, config)}</MetaNames>
145+
<MetaNames>{getParticipants(messages, config)}</MetaNames>
143146
<Ellipsis />
144-
<MetaTime>{getRelativeTime(conversation.messages)}</MetaTime>
147+
<MetaTime>{getRelativeTime(messages)}</MetaTime>
145148
</CenterMeta>
146149
</Center>
147150
<Right>

src/webchat/components/ConnectedWebchatUI.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { WebchatUI, WebchatUIProps } from "../../webchat-ui";
22
import { connect } from "react-redux";
33
import { StoreState } from "../store/store";
44
import { sendMessage, triggerEngagementMessage } from '../store/messages/message-middleware';
5-
import { setInputMode, setFullscreenMessage, setOpen, toggleOpen, setScrollToPosition, setLastScrolledPosition, setShowHomeScreen, setShowPrevConversations, setShowChatOptionsScreen, setHasAcceptedTerms, UIState, setStoredMessage } from '../store/ui/ui-reducer';
5+
import { setInputMode, setFullscreenMessage, setOpen, toggleOpen, setScrollToPosition, setLastScrolledPosition, setShowHomeScreen, showChatScreen, setShowPrevConversations, setShowChatOptionsScreen, setHasAcceptedTerms, UIState, setStoredMessage } from '../store/ui/ui-reducer';
66
import { getPluginsForMessage, isFullscreenPlugin } from '../../plugins/helper';
77
import { connect as doConnect } from "../store/connection/connection-middleware";
88
import { setHasGivenRating, showRatingScreen } from "../store/rating/rating-reducer";
@@ -79,6 +79,7 @@ export const ConnectedWebchatUI = connect<FromState, FromDispatch, FromProps, Me
7979
onSetShowHomeScreen: (show: boolean) => dispatch(setShowHomeScreen(show)),
8080
onSetShowPrevConversations: (show: boolean) => dispatch(setShowPrevConversations(show)),
8181
onSetShowChatOptionsScreen: (show: boolean) => dispatch(setShowChatOptionsScreen(show)),
82+
onShowChatScreen: () => dispatch(showChatScreen()),
8283
onSwitchSession: (sessionId?: string, conversation?: PrevConversationsState[string]) => dispatch(switchSession(sessionId, conversation)),
8384
onAcceptTerms: (userId: string) => dispatch(setHasAcceptedTerms(userId)),
8485
onSetStoredMessage: (message: UIState['storedMessage']) => dispatch(setStoredMessage(message)),

src/webchat/components/Webchat.tsx

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ConnectedWebchatUI, FromProps } from './ConnectedWebchatUI';
66
import { MessagePlugin } from '../../common/interfaces/message-plugin';
77
import { sendMessage } from '../store/messages/message-middleware';
88
import { MessageSender } from '../../webchat-ui/interfaces';
9-
import { setHasAcceptedTerms, setOpen, setShowHomeScreen, toggleOpen } from '../store/ui/ui-reducer';
9+
import { setHasAcceptedTerms, setOpen, setShowHomeScreen, showChatScreen, toggleOpen } from '../store/ui/ui-reducer';
1010
import { loadConfig } from '../store/config/config-middleware';
1111
import { connect } from '../store/connection/connection-middleware';
1212
import { EventEmitter } from 'events';
@@ -22,6 +22,7 @@ import { isDisabledDueToConnectivity } from '../helper/connectivity';
2222
import { createNotification } from '../../webchat-ui/components/presentational/Notifications';
2323
import { getStorage } from '../helper/storage';
2424
import { hasAcceptedTermsInStorage } from '../helper/privacyPolicy';
25+
import { setUserId } from '../store/options/options-reducer';
2526

2627
export interface WebchatProps extends FromProps {
2728
url: string;
@@ -73,6 +74,9 @@ export class Webchat extends React.PureComponent<WebchatProps> {
7374
if (this.props.options?.sessionId) {
7475
this.store.dispatch(setInitialSessionId(this.props.options.sessionId));
7576
}
77+
if (this.props.options?.userId) {
78+
this.store.dispatch(setUserId(this.props.options?.userId));
79+
}
7680
}
7781

7882
componentWillUnmount() {
@@ -135,7 +139,8 @@ export class Webchat extends React.PureComponent<WebchatProps> {
135139
}
136140

137141
startConversation = () => {
138-
this.store.dispatch(setShowHomeScreen(false));
142+
this.store.dispatch(setShowHomeScreen(false));
143+
this.store.dispatch(showChatScreen());
139144
}
140145

141146
on = (event, handler) => {

src/webchat/helper/storage.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export const getAllConversations = (
2525
currentURLtoken?: string,
2626
) => {
2727
return Object.keys(storage).reduce((acc, item) => {
28-
// skip missing userId or sessionId
29-
if (!currentSessionId || !currentUserId || !currentURLtoken) return acc;
28+
// skip missing userId or URLtoken
29+
if (!currentUserId || !currentURLtoken) return acc;
3030

3131
const data = storage.getItem(item) || "";
3232

0 commit comments

Comments
 (0)