Skip to content

Commit

Permalink
feat(livechat): Persistent after-guest-registration Trigger Message…
Browse files Browse the repository at this point in the history
…s (livechat client) (#32233)
  • Loading branch information
MartinSchoeler committed May 10, 2024
1 parent bf4b4cc commit e26397a
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 10 deletions.
6 changes: 6 additions & 0 deletions .changeset/gorgeous-lizards-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": minor
"@rocket.chat/livechat": minor
---

Makes the triggers fired by the condition `after-guest-registration` persist on the livechat client, it will persist through reloads and pagination, only reseting when a conversation is closed (no changes were done on the agent side of the conversation)
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,39 @@ test.describe('OC - Livechat New Chat Triggers - After Registration', () => {
});
});

test.describe('OC - Livechat Triggers - After Registration - Reload', async () => {
test('expect trigger message after registration', async () => {
await test.step('expect trigger message after registration to be visible', async () => {
await poLiveChat.page.goto('/livechat');
await poLiveChat.openAnyLiveChat();
await poLiveChat.sendMessage(newUser, false);
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
})

await test.step('expect trigger message after registration to be visible after reload', async () => {
await poLiveChat.page.reload();
await poLiveChat.openAnyLiveChat();
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
})

await test.step('expect to close room and reload', async () => {
await poLiveChat.onlineAgentMessage.type('message_after_trigger');
await poLiveChat.btnSendMessageToOnlineAgent.click();
await expect(poLiveChat.txtChatMessage('message_after_trigger')).toBeVisible();
await poLiveChat.closeChat();

await expect(poLiveChat.btnNewChat).toBeVisible();
await poLiveChat.startNewChat();
await poLiveChat.page.reload()
})

await test.step('expect trigger message after registration to be visible after reload on new chat', async () => {
await poLiveChat.openAnyLiveChat();
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
})
});
});

test.describe('OC - Livechat New Chat Triggers - After Registration, clear Local storage', async () => {
test.beforeAll(async ({ api }) => {
await api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: true });
Expand Down
10 changes: 10 additions & 0 deletions packages/livechat/src/definitions/triggerMessage.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { IOmnichannelAgent } from '@rocket.chat/core-typings';

export type TriggerMessage = {
msg?: string;
token: string;
u: Serialized<IOmnichannelAgent>;
ts: string;
_id: string;
trigger: boolean;
};
4 changes: 2 additions & 2 deletions packages/livechat/src/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const updateBusinessUnit = async (newBusinessUnit) => {
};

export const loadConfig = async () => {
const { token, businessUnit = null, iframe: { guest: { department } = {} } = {} } = store.state;
const { renderedTriggers, token, businessUnit = null, iframe: { guest: { department } = {} } = {} } = store.state;

Livechat.credentials.token = token;

Expand All @@ -60,7 +60,7 @@ export const loadConfig = async () => {
user,
queueInfo,
sound: { src, enabled: true, play: false },
messages: [],
messages: [...renderedTriggers],
typing: [],
noMoreMessages: false,
visible: true,
Expand Down
24 changes: 17 additions & 7 deletions packages/livechat/src/lib/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const closeChat = async ({ transcriptRequested } = {}) => {
return;
}

await store.setState({ room: null });
await store.setState({ room: null, renderedTriggers: [] });

if (clearLocalStorageWhenChatEnded) {
// exclude UI-affecting flags
Expand Down Expand Up @@ -255,17 +255,23 @@ export const getGreetingMessages = (messages) => messages && messages.filter((ms
export const getLatestCallMessage = (messages) => messages && messages.filter((msg) => isVideoCallMessage(msg)).pop();

export const loadMessages = async () => {
const { ongoingCall, messages: storedMessages, room } = store.state;
const { ongoingCall, messages: storedMessages, room, renderedTriggers } = store.state;

if (!room?._id) {
return;
}

const { _id: rid, callStatus } = room;
const previousMessages = getGreetingMessages(storedMessages);

await store.setState({ loading: true });
const rawMessages = (await Livechat.loadMessages(rid)).concat(previousMessages);

const rawMessages = (await Livechat.loadMessages(rid)) ?? [];

if (rawMessages?.length < 20) {
const triggers = previousMessages.length === 0 ? renderedTriggers : previousMessages;
rawMessages.push(...triggers.reverse());
}

const messages = (await normalizeMessages(rawMessages)).map(transformAgentInformationOnMessage);

await initRoom();
Expand Down Expand Up @@ -315,7 +321,7 @@ export const loadMessages = async () => {
};

export const loadMoreMessages = async () => {
const { room, messages = [], noMoreMessages = false } = store.state;
const { room, messages = [], noMoreMessages = false, renderedTriggers } = store.state;
const { _id: rid } = room || {};

if (!rid || noMoreMessages) {
Expand All @@ -327,9 +333,13 @@ export const loadMoreMessages = async () => {
const rawMessages = await Livechat.loadMessages(rid, { limit: messages.length + 10 });
const moreMessages = (await normalizeMessages(rawMessages)).map(transformAgentInformationOnMessage);

const newNoMoreMessages = messages.length + 10 > moreMessages.length;
const triggers = newNoMoreMessages ? [...renderedTriggers] : [];
const newMessages = ([...moreMessages, ...triggers] || []).reverse();

await store.setState({
messages: (moreMessages || []).reverse(),
noMoreMessages: messages.length + 10 > moreMessages.length,
messages: newMessages,
noMoreMessages: newNoMoreMessages,
loading: false,
});
};
Expand Down
19 changes: 18 additions & 1 deletion packages/livechat/src/lib/triggerActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ export const sendMessageAction = async (_: string, action: ILivechatSendMessageA

await upsertMessage(message);

// Save the triggers for subsequent renders
if (condition.name === 'after-guest-registration') {
store.setState({
renderedTriggers: [...store.state.renderedTriggers, message],
});
}

if (agent && '_id' in agent) {
await store.setState({ agent });
parentCall('callback', 'assign-agent', normalizeAgent(agent));
Expand Down Expand Up @@ -78,7 +85,17 @@ export const sendMessageExternalServiceAction = async (
trigger: true,
}));

await Promise.all(messages.map((message) => upsertMessage(message)));
await Promise.all(
messages.map((message) => {
if (condition.name === 'after-guest-registration') {
store.setState({
renderedTriggers: [...store.state.renderedTriggers, message],
});
}

return upsertMessage(message);
}),
);

if (agent && '_id' in agent) {
await store.setState({ agent });
Expand Down
5 changes: 5 additions & 0 deletions packages/livechat/src/lib/triggerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ export const removeMessage = async (messageId: string) => {
await store.setState({ messages: messages.filter(({ _id }) => _id !== messageId) });
};

export const removeTriggerMessage = async (messageId: string) => {
const { renderedTriggers } = store.state;
await store.setState({ renderedTriggers: renderedTriggers.filter(({ _id }) => _id !== messageId) });
};

export const hasTriggerCondition = (conditionName: ILivechatTriggerType) => (trigger: ILivechatTrigger) => {
return trigger.conditions.some((condition) => condition.name === conditionName);
};
Expand Down
3 changes: 3 additions & 0 deletions packages/livechat/src/store/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useContext } from 'preact/hooks';
import type { CustomField } from '../components/Form/CustomFields';
import type { Agent } from '../definitions/agents';
import type { Department } from '../definitions/departments';
import type { TriggerMessage } from '../definitions/triggerMessage';
import { parentCall } from '../lib/parentCall';
import { createToken } from '../lib/random';
import Store from './Store';
Expand Down Expand Up @@ -120,6 +121,7 @@ export type StoreState = {
parentUrl?: string;
connecting?: boolean;
messageListPosition?: 'top' | 'bottom' | 'free';
renderedTriggers: TriggerMessage[];
};

export const initialState = (): StoreState => ({
Expand Down Expand Up @@ -160,6 +162,7 @@ export const initialState = (): StoreState => ({
incomingCallAlert: null,
ongoingCall: null, // TODO: store call info like url, startTime, timeout, etc here
businessUnit: null,
renderedTriggers: [],
});

const dontPersist = [
Expand Down

0 comments on commit e26397a

Please sign in to comment.