Skip to content

Commit 9e8f247

Browse files
authored
Merge pull request #43 from PrajvalRaval/master
Adding pre-programmed button support in quick replies.
2 parents d51eb48 + d7c061f commit 9e8f247

6 files changed

Lines changed: 105 additions & 17 deletions

File tree

config/Settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export enum AppSetting {
1515

1616
export enum DefaultMessage {
1717
DEFAULT_DialogflowServiceUnavailableMessage = 'Sorry, I\'m having trouble answering your question.',
18+
DEFAULT_DialogflowRequestFailedMessage = 'Sorry, something went wrong.',
1819
DEFAULT_DialogflowHandoverMessage = 'Transferring to an online agent',
1920
DEFAULT_DialogflowCloseChatMessage = 'Closing the chat, Goodbye',
2021
}

docs/QuickReplies.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,59 @@
2626
| `text` | String | Title of the quick replies action. | Required | Any | ``` "text": "Start Chat" ``` |
2727
| `actionId` | String | Id of the quick replies action. | Optional | Any | ``` "actionId": "sflaia-start-chat" ``` |
2828
| `buttonStyle` | String | Button style of your quick replies action. Use `danger` to render a red colour action and `primary` for an action that matches your Livechat Bar colour. | Optional | `danger` or `primary` | ``` "buttonStyle": "primary" ``` |
29-
### Example
3029

31-
![Quick Replies Example](https://user-images.githubusercontent.com/41849970/91997140-62939c00-ed57-11ea-8b27-82e650a502f0.png)
30+
## Pre-Programmed Buttons
31+
32+
These buttons perform a specific action in the app. You can add them by simply pasting the following block in your Quick Replies payload. **Note**: You can change the `text` and `buttonStyle` parameters as per your requirements, but only use the provided `actionId` for the button you want to add.
33+
34+
### Handover Button
35+
36+
- On clicking this button, the visitor will be handed over to another departement. You can set the target department in the app setting called **Target Department for Handover** or add a `departmentName` param in your payload. On failing to provide a department name in either way, will send a request failure message back to the visitor, when visitor clicks the button.
37+
38+
- Add the following block in your Quick Replies payload, with **actionId** set as `df_perform_handover`, to include this button in your response:
39+
40+
- Parameters:
41+
42+
| Param Name | Dependency | Param Type | Acceptable Value |
43+
|:----------------:|:------------:|:----------:|:-----------------------------------:|
44+
| `actionId` | **Required** | String | `df_perform_handover` |
45+
| `text` | **Required** | String | **Any** |
46+
| `buttonStyle` | **Optional** | String | `primary` or `danger` |
47+
| `departmentName` | **Optional** | String | **Any Omnichannel department name** |
48+
49+
- Example Structure:
50+
51+
```
52+
{
53+
"text": "Perform Handover",
54+
"buttonStyle": "primary",
55+
"actionId": "df_perform_handover",
56+
"departmentName": "sales"
57+
}
58+
```
59+
60+
### Close Chat Button
61+
62+
- When visitor clicks this button, the chat session will be closed. Add the following block in your Quick Replies payload, with **actionId** set as `df_close_chat`, to include this button in your response:
63+
64+
- Parameters:
65+
66+
| Param Name | Dependency | Param Type | Acceptable Value |
67+
|:-------------:|:------------:|:----------:|:---------------------:|
68+
| `actionId` | **Required** | String | `df_close_chat` |
69+
| `text` | **Required** | String | **Any** |
70+
| `buttonStyle` | **Optional** | String | `primary` or `danger` |
71+
72+
- Example Structure:
73+
74+
```
75+
{
76+
"text": "Close Chat",
77+
"buttonStyle": "danger",
78+
"actionId": "df_close_chat"
79+
}
80+
```
81+
82+
## Example
83+
84+
![Pre-Programmed Example Payload](https://user-images.githubusercontent.com/41849970/92283593-d5e70a80-ef1d-11ea-8860-e91a4980515f.png)

enum/ActionIds.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum ActionIds {
2+
PERFORM_HANDOVER = 'df_perform_handover',
3+
CLOSE_CHAT = 'df_close_chat',
4+
}

enum/Dialogflow.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export interface IDialogflowQuickReplyOptions {
1515
text: string;
1616
actionId?: string;
1717
buttonStyle?: ButtonStyle;
18+
data?: {
19+
[prop: string]: any;
20+
};
1821
}
1922

2023
export interface IDialogflowAccessToken {

handler/ExecuteLivechatBlockActionHandler.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import { ILivechatRoom } from '@rocket.chat/apps-engine/definition/livechat';
44
import { IUIKitResponse, UIKitLivechatBlockInteractionContext } from '@rocket.chat/apps-engine/definition/uikit';
55
import { UIKitIncomingInteractionContainerType } from '@rocket.chat/apps-engine/definition/uikit/UIKitIncomingInteractionContainer';
66
import { IUser } from '@rocket.chat/apps-engine/definition/users';
7-
import { AppSetting } from '../config/Settings';
8-
import { createLivechatMessage, deleteAllActionBlocks } from '../lib/Message';
7+
import { AppSetting, DefaultMessage } from '../config/Settings';
8+
import { ActionIds } from '../enum/ActionIds';
9+
import { createLivechatMessage, createMessage, deleteAllActionBlocks } from '../lib/Message';
10+
import { closeChat, performHandover } from '../lib/Room';
911
import { getAppSettingValue } from '../lib/Settings';
1012

1113
export class ExecuteLivechatBlockActionHandler {
@@ -19,8 +21,7 @@ export class ExecuteLivechatBlockActionHandler {
1921
public async run(): Promise<IUIKitResponse> {
2022
try {
2123
const interactionData = this.context.getInteractionData();
22-
23-
const { visitor, room, container: { id, type }, value } = interactionData;
24+
const { visitor, room, container: { id, type }, value, actionId } = interactionData;
2425

2526
if (type !== UIKitIncomingInteractionContainerType.MESSAGE) {
2627
return this.context.getInteractionResponder().successResponse();
@@ -35,7 +36,24 @@ export class ExecuteLivechatBlockActionHandler {
3536

3637
const appUser = await this.read.getUserReader().getAppUser(this.app.getID()) as IUser;
3738

38-
await createLivechatMessage(rid, this.read, this.modify, { text: value }, visitor);
39+
switch (actionId) {
40+
case ActionIds.PERFORM_HANDOVER:
41+
const targetDepartment: string = value || await getAppSettingValue(this.read, AppSetting.FallbackTargetDepartment);
42+
if (!targetDepartment) {
43+
await createMessage(rid, this.read, this.modify, { text: DefaultMessage.DEFAULT_DialogflowRequestFailedMessage });
44+
break;
45+
}
46+
await performHandover(this.modify, this.read, rid, visitor.token, targetDepartment);
47+
break;
48+
49+
case ActionIds.CLOSE_CHAT:
50+
await closeChat(this.modify, this.read, rid);
51+
break;
52+
53+
default:
54+
await createLivechatMessage(rid, this.read, this.modify, { text: value }, visitor);
55+
break;
56+
}
3957

4058
const { value: hideQuickRepliesSetting } = await this.read.getEnvironmentReader().getSettings().getById(AppSetting.DialogflowHideQuickReplies);
4159
if (hideQuickRepliesSetting) {

lib/Message.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IVisitor } from '@rocket.chat/apps-engine/definition/livechat';
33
import { BlockElementType, BlockType, IActionsBlock, IButtonElement, TextObjectType } from '@rocket.chat/apps-engine/definition/uikit';
44
import { IUser } from '@rocket.chat/apps-engine/definition/users';
55
import { AppSetting } from '../config/Settings';
6+
import { ActionIds } from '../enum/ActionIds';
67
import { IDialogflowMessage, IDialogflowQuickReplies, IDialogflowQuickReplyOptions } from '../enum/Dialogflow';
78
import { Logs } from '../enum/Logs';
89
import { uuid } from './Helper';
@@ -14,16 +15,24 @@ export const createDialogflowMessage = async (rid: string, read: IRead, modify:
1415
for (const message of messages) {
1516
const { text, options } = message as IDialogflowQuickReplies;
1617
if (text && options) {
17-
const elements: Array<IButtonElement> = options.map((payload: IDialogflowQuickReplyOptions) => ({
18-
type: BlockElementType.BUTTON,
19-
text: {
20-
type: TextObjectType.PLAINTEXT,
21-
text: payload.text,
22-
},
23-
value: payload.text,
24-
actionId: payload.actionId || uuid(),
25-
...payload.buttonStyle && { style: payload.buttonStyle },
26-
} as IButtonElement));
18+
const elements: Array<IButtonElement> = options.map((payload: IDialogflowQuickReplyOptions) => {
19+
const buttonElement: IButtonElement = {
20+
type: BlockElementType.BUTTON,
21+
actionId: payload.actionId || uuid(),
22+
text: {
23+
text: payload.text,
24+
type: TextObjectType.PLAINTEXT,
25+
},
26+
value: payload.text,
27+
...payload.buttonStyle && { style: payload.buttonStyle },
28+
};
29+
30+
if (payload.actionId && payload.actionId === ActionIds.PERFORM_HANDOVER) {
31+
buttonElement.value = payload.data && payload.data.departmentName ? payload.data.departmentName : undefined;
32+
}
33+
34+
return buttonElement;
35+
});
2736

2837
const actionsBlock: IActionsBlock = { type: BlockType.ACTIONS, elements };
2938

0 commit comments

Comments
 (0)