@botonic/plugin-flow-builder 0.22.3 → 0.22.4-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/{action.d.ts → action/index.d.ts} +2 -3
- package/lib/cjs/action/index.js +72 -0
- package/lib/cjs/action/index.js.map +1 -0
- package/lib/cjs/action/intent.d.ts +4 -0
- package/lib/cjs/action/intent.js +33 -0
- package/lib/cjs/action/intent.js.map +1 -0
- package/lib/cjs/action/keyword.d.ts +3 -0
- package/lib/cjs/action/keyword.js +21 -0
- package/lib/cjs/action/keyword.js.map +1 -0
- package/lib/cjs/action/tracking.d.ts +3 -0
- package/lib/cjs/action/tracking.js +13 -0
- package/lib/cjs/action/tracking.js.map +1 -0
- package/lib/cjs/action/user-input.d.ts +4 -0
- package/lib/cjs/action/user-input.js +28 -0
- package/lib/cjs/action/user-input.js.map +1 -0
- package/lib/cjs/api.d.ts +4 -4
- package/lib/cjs/api.js +4 -10
- package/lib/cjs/api.js.map +1 -1
- package/lib/cjs/content-fields/content-fields-base.d.ts +2 -1
- package/lib/cjs/content-fields/content-fields-base.js +3 -0
- package/lib/cjs/content-fields/content-fields-base.js.map +1 -1
- package/lib/cjs/content-fields/flow-handoff.d.ts +15 -0
- package/lib/cjs/content-fields/flow-handoff.js +60 -0
- package/lib/cjs/content-fields/flow-handoff.js.map +1 -0
- package/lib/cjs/content-fields/index.d.ts +3 -1
- package/lib/cjs/content-fields/index.js +3 -1
- package/lib/cjs/content-fields/index.js.map +1 -1
- package/lib/cjs/functions/conditional-provider.d.ts +7 -4
- package/lib/cjs/functions/conditional-provider.js +1 -1
- package/lib/cjs/functions/conditional-provider.js.map +1 -1
- package/lib/cjs/functions/conditional-queue-status.d.ts +10 -1
- package/lib/cjs/functions/conditional-queue-status.js +11 -16
- package/lib/cjs/functions/conditional-queue-status.js.map +1 -1
- package/lib/cjs/functions/index.js +0 -1
- package/lib/cjs/functions/index.js.map +1 -1
- package/lib/cjs/helpers.d.ts +0 -2
- package/lib/cjs/helpers.js +1 -6
- package/lib/cjs/helpers.js.map +1 -1
- package/lib/cjs/index.d.ts +5 -7
- package/lib/cjs/index.js +16 -12
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/types.js.map +1 -1
- package/lib/esm/{action.d.ts → action/index.d.ts} +2 -3
- package/lib/esm/action/index.js +66 -0
- package/lib/esm/action/index.js.map +1 -0
- package/lib/esm/action/intent.d.ts +4 -0
- package/lib/esm/action/intent.js +29 -0
- package/lib/esm/action/intent.js.map +1 -0
- package/lib/esm/action/keyword.d.ts +3 -0
- package/lib/esm/action/keyword.js +17 -0
- package/lib/esm/action/keyword.js.map +1 -0
- package/lib/esm/action/tracking.d.ts +3 -0
- package/lib/esm/action/tracking.js +9 -0
- package/lib/esm/action/tracking.js.map +1 -0
- package/lib/esm/action/user-input.d.ts +4 -0
- package/lib/esm/action/user-input.js +24 -0
- package/lib/esm/action/user-input.js.map +1 -0
- package/lib/esm/api.d.ts +4 -4
- package/lib/esm/api.js +4 -10
- package/lib/esm/api.js.map +1 -1
- package/lib/esm/content-fields/content-fields-base.d.ts +2 -1
- package/lib/esm/content-fields/content-fields-base.js +3 -0
- package/lib/esm/content-fields/content-fields-base.js.map +1 -1
- package/lib/esm/content-fields/flow-handoff.d.ts +15 -0
- package/lib/esm/content-fields/flow-handoff.js +55 -0
- package/lib/esm/content-fields/flow-handoff.js.map +1 -0
- package/lib/esm/content-fields/index.d.ts +3 -1
- package/lib/esm/content-fields/index.js +1 -0
- package/lib/esm/content-fields/index.js.map +1 -1
- package/lib/esm/functions/conditional-provider.d.ts +7 -4
- package/lib/esm/functions/conditional-provider.js +1 -1
- package/lib/esm/functions/conditional-provider.js.map +1 -1
- package/lib/esm/functions/conditional-queue-status.d.ts +10 -1
- package/lib/esm/functions/conditional-queue-status.js +8 -14
- package/lib/esm/functions/conditional-queue-status.js.map +1 -1
- package/lib/esm/functions/index.js +0 -1
- package/lib/esm/functions/index.js.map +1 -1
- package/lib/esm/helpers.d.ts +0 -2
- package/lib/esm/helpers.js +0 -4
- package/lib/esm/helpers.js.map +1 -1
- package/lib/esm/index.d.ts +5 -7
- package/lib/esm/index.js +17 -13
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/types.js.map +1 -1
- package/package.json +2 -1
- package/src/action/index.tsx +104 -0
- package/src/action/intent.ts +48 -0
- package/src/action/keyword.ts +28 -0
- package/src/action/tracking.ts +12 -0
- package/src/action/user-input.ts +40 -0
- package/src/api.ts +6 -14
- package/src/content-fields/content-fields-base.ts +8 -0
- package/src/content-fields/flow-handoff.tsx +106 -0
- package/src/content-fields/index.ts +3 -0
- package/src/functions/conditional-provider.ts +11 -1
- package/src/functions/conditional-queue-status.ts +19 -16
- package/src/functions/index.ts +0 -1
- package/src/helpers.ts +0 -9
- package/src/index.ts +29 -21
- package/src/types.ts +0 -1
- package/lib/cjs/action.js +0 -52
- package/lib/cjs/action.js.map +0 -1
- package/lib/cjs/handoff.d.ts +0 -3
- package/lib/cjs/handoff.js +0 -53
- package/lib/cjs/handoff.js.map +0 -1
- package/lib/esm/action.js +0 -46
- package/lib/esm/action.js.map +0 -1
- package/lib/esm/handoff.d.ts +0 -3
- package/lib/esm/handoff.js +0 -49
- package/lib/esm/handoff.js.map +0 -1
- package/src/.DS_Store +0 -0
- package/src/action.tsx +0 -77
- package/src/content-fields/.DS_Store +0 -0
- package/src/handoff.ts +0 -76
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import { getFlowBuilderPlugin } from '../helpers';
|
|
3
2
|
import { getWebpackEnvVar } from '../utils';
|
|
4
3
|
const _HUBTYPE_API_URL_ = getWebpackEnvVar(
|
|
5
4
|
// @ts-ignore
|
|
6
5
|
typeof HUBTYPE_API_URL !== 'undefined' && HUBTYPE_API_URL, 'HUBTYPE_API_URL', 'https://api.hubtype.com');
|
|
7
|
-
export async function conditionalQueueStatus({
|
|
8
|
-
const
|
|
6
|
+
export async function conditionalQueueStatus({ queue_id, }) {
|
|
7
|
+
const data = await getQueueAvailability(queue_id);
|
|
8
|
+
const isAvailable = data.available;
|
|
9
|
+
return isAvailable ? 'open' : 'closed';
|
|
10
|
+
}
|
|
11
|
+
export async function getQueueAvailability(queueId) {
|
|
12
|
+
const response = await axios.get(`${_HUBTYPE_API_URL_}/v1/queues/${queueId}/availability/`,
|
|
9
13
|
// TODO: Make it configurable in the future
|
|
10
14
|
{
|
|
11
15
|
params: {
|
|
@@ -14,16 +18,6 @@ export async function conditionalQueueStatus({ request, queue_id, queue_name, })
|
|
|
14
18
|
check_available_agents: false,
|
|
15
19
|
},
|
|
16
20
|
});
|
|
17
|
-
|
|
18
|
-
const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins);
|
|
19
|
-
if (flowBuilderPlugin.trackEvent) {
|
|
20
|
-
const eventName = `QUEUE_${isAvailable ? 'OPEN' : 'CLOSED'}`;
|
|
21
|
-
const args = {
|
|
22
|
-
queue_id,
|
|
23
|
-
queue_name,
|
|
24
|
-
};
|
|
25
|
-
await flowBuilderPlugin.trackEvent(request, eventName, args);
|
|
26
|
-
}
|
|
27
|
-
return isAvailable ? 'open' : 'closed';
|
|
21
|
+
return response.data;
|
|
28
22
|
}
|
|
29
23
|
//# sourceMappingURL=conditional-queue-status.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditional-queue-status.js","sourceRoot":"","sources":["../../../src/functions/conditional-queue-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"conditional-queue-status.js","sourceRoot":"","sources":["../../../src/functions/conditional-queue-status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAE3C,MAAM,iBAAiB,GAAG,gBAAgB;AACxC,aAAa;AACb,OAAO,eAAe,KAAK,WAAW,IAAI,eAAe,EACzD,iBAAiB,EACjB,yBAAyB,CAC1B,CAAA;AAQD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,EAC3C,QAAQ,GACmB;IAC3B,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IACjD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAA;IAClC,OAAO,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAA;AACxC,CAAC;AAWD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe;IAEf,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAC9B,GAAG,iBAAiB,cAAc,OAAO,gBAAgB;IACzD,2CAA2C;IAC3C;QACE,MAAM,EAAE;YACN,oBAAoB,EAAE,IAAI;YAC1B,mBAAmB,EAAE,KAAK;YAC1B,sBAAsB,EAAE,KAAK;SAC9B;KACF,CACF,CAAA;IACD,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC"}
|
|
@@ -2,7 +2,6 @@ import { conditionalProvider } from './conditional-provider';
|
|
|
2
2
|
import { conditionalQueueStatus } from './conditional-queue-status';
|
|
3
3
|
export const DEFAULT_FUNCTIONS = {
|
|
4
4
|
// TODO: Rename api action name
|
|
5
|
-
// 'conditional-queue-status': conditionalQueueStatus,
|
|
6
5
|
'check-queue-status': conditionalQueueStatus,
|
|
7
6
|
'get-channel-type': conditionalProvider,
|
|
8
7
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAEnE,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,+BAA+B;IAC/B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AAEnE,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,+BAA+B;IAC/B,oBAAoB,EAAE,sBAAsB;IAC5C,kBAAkB,EAAE,mBAAmB;CACxC,CAAA"}
|
package/lib/esm/helpers.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Plugin } from '@botonic/core';
|
|
2
|
-
import { HtHandoffNode, HtNodeWithContent } from './content-fields/hubtype-fields';
|
|
3
2
|
import BotonicPluginFlowBuilder from './index';
|
|
4
3
|
export declare function getFlowBuilderPlugin(plugins: {
|
|
5
4
|
[id: string]: Plugin;
|
|
6
5
|
}): BotonicPluginFlowBuilder;
|
|
7
|
-
export declare function isHandoffNode(node: HtNodeWithContent): node is HtHandoffNode;
|
package/lib/esm/helpers.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { HtNodeWithContentType, } from './content-fields/hubtype-fields';
|
|
2
1
|
const FLOW_BUILDER_PLUGIN_NAME = 'BotonicPluginFlowBuilder';
|
|
3
2
|
export function getFlowBuilderPlugin(plugins) {
|
|
4
3
|
const flowBuilderPlugin = Object.values(plugins).find(
|
|
@@ -8,7 +7,4 @@ export function getFlowBuilderPlugin(plugins) {
|
|
|
8
7
|
throw new Error(`You must include '@botonic/plugin-flow-builder' in your plugins file.`);
|
|
9
8
|
return flowBuilderPlugin;
|
|
10
9
|
}
|
|
11
|
-
export function isHandoffNode(node) {
|
|
12
|
-
return node.type === HtNodeWithContentType.HANDOFF;
|
|
13
|
-
}
|
|
14
10
|
//# sourceMappingURL=helpers.js.map
|
package/lib/esm/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":"AAIA,MAAM,wBAAwB,GAAG,0BAA0B,CAAA;AAE3D,MAAM,UAAU,oBAAoB,CAAC,OAEpC;IACC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI;IACnD,aAAa;IACb,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAC7B,CAAA;IAC7B,IAAI,CAAC,iBAAiB;QACpB,MAAM,IAAI,KAAK,CACb,uEAAuE,CACxE,CAAA;IACH,OAAO,iBAAiB,CAAA;AAC1B,CAAC"}
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Plugin,
|
|
1
|
+
import { Plugin, PluginPreRequest, Session } from '@botonic/core';
|
|
2
2
|
import { ActionRequest } from '@botonic/react';
|
|
3
3
|
import { FlowBuilderApi } from './api';
|
|
4
4
|
import { FlowContent } from './content-fields';
|
|
5
|
-
import { HtFunctionNode,
|
|
5
|
+
import { HtFunctionNode, HtNodeWithContent } from './content-fields/hubtype-fields';
|
|
6
6
|
import { BotonicPluginFlowBuilderOptions } from './types';
|
|
7
7
|
export default class BotonicPluginFlowBuilder implements Plugin {
|
|
8
8
|
readonly options: BotonicPluginFlowBuilderOptions;
|
|
@@ -16,11 +16,9 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
16
16
|
trackEvent?: (request: ActionRequest, eventName: string, args?: Record<string, any>) => Promise<void>;
|
|
17
17
|
constructor(options: BotonicPluginFlowBuilderOptions);
|
|
18
18
|
pre(request: PluginPreRequest): Promise<void>;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
handoffNode?: HtHandoffNode;
|
|
23
|
-
}>;
|
|
19
|
+
getContentsByCode(code: string, locale: string, prevContents?: FlowContent[]): Promise<FlowContent[]>;
|
|
20
|
+
getContentsById(id: string, locale: string, prevContents?: FlowContent[]): Promise<FlowContent[]>;
|
|
21
|
+
getContentsByNode(node: HtNodeWithContent, locale: string, prevContents?: FlowContent[]): Promise<FlowContent[]>;
|
|
24
22
|
private getFlowContent;
|
|
25
23
|
callFunction(functionNode: HtFunctionNode, locale: string): Promise<string>;
|
|
26
24
|
}
|
package/lib/esm/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { FlowBuilderApi } from './api';
|
|
2
|
-
import { FlowCarousel, FlowImage, FlowText, FlowVideo, FlowWhatsappButtonList, } from './content-fields';
|
|
2
|
+
import { FlowCarousel, FlowHandoff, FlowImage, FlowText, FlowVideo, FlowWhatsappButtonList, } from './content-fields';
|
|
3
3
|
import { HtNodeWithContentType, } from './content-fields/hubtype-fields';
|
|
4
4
|
import { DEFAULT_FUNCTIONS } from './functions';
|
|
5
|
-
import { isHandoffNode } from './helpers';
|
|
6
5
|
import { resolveGetAccessToken } from './utils';
|
|
7
6
|
export default class BotonicPluginFlowBuilder {
|
|
8
7
|
constructor(options) {
|
|
@@ -23,26 +22,29 @@ export default class BotonicPluginFlowBuilder {
|
|
|
23
22
|
accessToken: this.getAccessToken(request.session),
|
|
24
23
|
});
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
getContentsByCode(code, locale, prevContents) {
|
|
26
|
+
const node = this.cmsApi.getNodeByCode(code);
|
|
27
|
+
return this.getContentsByNode(node, locale, prevContents);
|
|
28
|
+
}
|
|
29
|
+
async getContentsById(id, locale, prevContents) {
|
|
30
|
+
const node = this.cmsApi.getNodeById(id);
|
|
31
|
+
return this.getContentsByNode(node, locale, prevContents);
|
|
32
|
+
}
|
|
33
|
+
async getContentsByNode(node, locale, prevContents) {
|
|
28
34
|
const contents = prevContents || [];
|
|
29
|
-
|
|
30
|
-
if (typeof nodeOrId === 'string') {
|
|
31
|
-
node = this.cmsApi.getNodeById(nodeOrId);
|
|
32
|
-
}
|
|
33
|
-
const content = await this.getFlowContent(node, locale);
|
|
35
|
+
const content = this.getFlowContent(node, locale);
|
|
34
36
|
if (node.type === HtNodeWithContentType.FUNCTION) {
|
|
35
37
|
const targetId = await this.callFunction(node, locale);
|
|
36
|
-
return this.
|
|
38
|
+
return this.getContentsById(targetId, locale, contents);
|
|
37
39
|
}
|
|
38
40
|
else {
|
|
39
41
|
if (content)
|
|
40
42
|
contents.push(content);
|
|
41
43
|
// TODO: prevent infinite recursive calls
|
|
42
44
|
if (node.follow_up)
|
|
43
|
-
return this.
|
|
45
|
+
return this.getContentsById(node.follow_up.id, locale, contents);
|
|
44
46
|
}
|
|
45
|
-
return
|
|
47
|
+
return contents;
|
|
46
48
|
}
|
|
47
49
|
getFlowContent(hubtypeContent, locale) {
|
|
48
50
|
switch (hubtypeContent.type) {
|
|
@@ -56,6 +58,8 @@ export default class BotonicPluginFlowBuilder {
|
|
|
56
58
|
return FlowVideo.fromHubtypeCMS(hubtypeContent, locale);
|
|
57
59
|
case HtNodeWithContentType.WHATSAPP_BUTTON_LIST:
|
|
58
60
|
return FlowWhatsappButtonList.fromHubtypeCMS(hubtypeContent, locale);
|
|
61
|
+
case HtNodeWithContentType.HANDOFF:
|
|
62
|
+
return FlowHandoff.fromHubtypeCMS(hubtypeContent, locale, this.cmsApi);
|
|
59
63
|
default:
|
|
60
64
|
return undefined;
|
|
61
65
|
}
|
|
@@ -67,7 +71,7 @@ export default class BotonicPluginFlowBuilder {
|
|
|
67
71
|
.find(arg => arg.locale === locale)) === null || _a === void 0 ? void 0 : _a.values.map(value => ({ [value.name]: value.value }))) || [];
|
|
68
72
|
const args = Object.assign({
|
|
69
73
|
request: this.currentRequest,
|
|
70
|
-
results:
|
|
74
|
+
results: functionNode.content.result_mapping.map(r => r.result),
|
|
71
75
|
}, ...nameValues);
|
|
72
76
|
const functionResult = await this.functions[functionNode.content.action](args);
|
|
73
77
|
// TODO define result_mapping per locale??
|
package/lib/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAN,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC5B,+CAAyB,CAAA;IACzB,iDAA2B,CAAA;AAC7B,CAAC,EAHW,kBAAkB,KAAlB,kBAAkB,QAG7B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botonic/plugin-flow-builder",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.4-alpha.1",
|
|
4
4
|
"main": "./lib/cjs/index.js",
|
|
5
5
|
"module": "./lib/esm/index.js",
|
|
6
6
|
"description": "Use Flow Builder to show your contents",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@babel/runtime": "^7.21.0",
|
|
50
50
|
"@botonic/react": "^0.22.2",
|
|
51
|
+
"@botonic/plugin-hubtype-analytics": "0.22.0-alpha.5",
|
|
51
52
|
"axios": "^1.3.6"
|
|
52
53
|
}
|
|
53
54
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventBotFaq,
|
|
3
|
+
EventFallback,
|
|
4
|
+
EventName,
|
|
5
|
+
} from '@botonic/plugin-hubtype-analytics/lib/cjs/types'
|
|
6
|
+
import { ActionRequest, Multichannel, RequestContext } from '@botonic/react'
|
|
7
|
+
import React from 'react'
|
|
8
|
+
|
|
9
|
+
import { FlowBuilderApi } from '../api'
|
|
10
|
+
import { FlowContent, FlowHandoff } from '../content-fields'
|
|
11
|
+
import { HtNodeWithContent } from '../content-fields/hubtype-fields'
|
|
12
|
+
import { getFlowBuilderPlugin } from '../helpers'
|
|
13
|
+
import { trackEvent } from './tracking'
|
|
14
|
+
import { getNodeByUserInput } from './user-input'
|
|
15
|
+
|
|
16
|
+
type FlowBuilderActionProps = {
|
|
17
|
+
contents: FlowContent[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class FlowBuilderAction extends React.Component<FlowBuilderActionProps> {
|
|
21
|
+
static contextType = RequestContext
|
|
22
|
+
|
|
23
|
+
static async botonicInit(
|
|
24
|
+
request: ActionRequest
|
|
25
|
+
): Promise<FlowBuilderActionProps> {
|
|
26
|
+
const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
|
|
27
|
+
const locale = flowBuilderPlugin.getLocale(request.session)
|
|
28
|
+
|
|
29
|
+
const targetNode = await getTargetNode(
|
|
30
|
+
flowBuilderPlugin.cmsApi,
|
|
31
|
+
locale,
|
|
32
|
+
request
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const contents = await flowBuilderPlugin.getContentsByNode(
|
|
36
|
+
targetNode,
|
|
37
|
+
locale
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
const renderContents = contents.filter(async content => {
|
|
41
|
+
if (content instanceof FlowHandoff) {
|
|
42
|
+
await content.doHandoff(request)
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
return true
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
return { contents: renderContents }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render(): JSX.Element | JSX.Element[] {
|
|
52
|
+
const { contents } = this.props
|
|
53
|
+
return contents.map(content => content.toBotonic(content.id))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class FlowBuilderMultichannelAction extends FlowBuilderAction {
|
|
58
|
+
render(): JSX.Element | JSX.Element[] {
|
|
59
|
+
const { contents } = this.props
|
|
60
|
+
return (
|
|
61
|
+
<Multichannel text={{ buttonsAsText: false }}>
|
|
62
|
+
{contents.map(content => content.toBotonic(content.id))}
|
|
63
|
+
</Multichannel>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function getTargetNode(
|
|
69
|
+
cmsApi: FlowBuilderApi,
|
|
70
|
+
locale: string,
|
|
71
|
+
request: ActionRequest
|
|
72
|
+
) {
|
|
73
|
+
const contentId = request.input.payload
|
|
74
|
+
let targetNode: HtNodeWithContent | undefined
|
|
75
|
+
if (!contentId) {
|
|
76
|
+
targetNode = await getNodeByUserInput(cmsApi, locale, request)
|
|
77
|
+
} else {
|
|
78
|
+
targetNode = cmsApi.getNodeById(contentId) as HtNodeWithContent
|
|
79
|
+
}
|
|
80
|
+
if (targetNode) {
|
|
81
|
+
const event: EventBotFaq = {
|
|
82
|
+
event_type: EventName.botFaq,
|
|
83
|
+
event_data: {
|
|
84
|
+
faq_name: targetNode.code,
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
await trackEvent(request, event)
|
|
88
|
+
return targetNode
|
|
89
|
+
}
|
|
90
|
+
return await getFallbackNode(cmsApi, request)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function getFallbackNode(cmsApi: FlowBuilderApi, request: ActionRequest) {
|
|
94
|
+
const isFirstFallbackOption =
|
|
95
|
+
request.session.user.extra_data.isFirstFallbackOption || true
|
|
96
|
+
const fallbackNode = cmsApi.getFallbackNode(isFirstFallbackOption)
|
|
97
|
+
request.session.user.extra_data.isFirstFallbackOption = !isFirstFallbackOption
|
|
98
|
+
|
|
99
|
+
const event: EventFallback = {
|
|
100
|
+
event_type: EventName.fallback,
|
|
101
|
+
}
|
|
102
|
+
await trackEvent(request, event)
|
|
103
|
+
return fallbackNode
|
|
104
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventBotAiModel,
|
|
3
|
+
EventName,
|
|
4
|
+
} from '@botonic/plugin-hubtype-analytics/lib/cjs/types'
|
|
5
|
+
import { ActionRequest } from '@botonic/react'
|
|
6
|
+
|
|
7
|
+
import { FlowBuilderApi } from '../api'
|
|
8
|
+
import {
|
|
9
|
+
HtIntentNode,
|
|
10
|
+
HtNodeWithContent,
|
|
11
|
+
} from '../content-fields/hubtype-fields'
|
|
12
|
+
import { trackEvent } from './tracking'
|
|
13
|
+
|
|
14
|
+
export async function getNodeByIntent(
|
|
15
|
+
cmsApi: FlowBuilderApi,
|
|
16
|
+
locale: string,
|
|
17
|
+
request: ActionRequest
|
|
18
|
+
) {
|
|
19
|
+
const intentNode = cmsApi.getIntentNode(request.input, locale)
|
|
20
|
+
const eventBotAiModel: EventBotAiModel = {
|
|
21
|
+
event_type: EventName.botAiModel,
|
|
22
|
+
event_data: {
|
|
23
|
+
intent: request.input.intent as string,
|
|
24
|
+
confidence: request.input.confidence as number,
|
|
25
|
+
confidence_successful: true,
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
if (isIntentValid(intentNode, request, cmsApi) && intentNode?.target?.id) {
|
|
29
|
+
await trackEvent(request, eventBotAiModel)
|
|
30
|
+
return cmsApi.getNodeById<HtNodeWithContent>(intentNode.target.id)
|
|
31
|
+
} else {
|
|
32
|
+
eventBotAiModel.event_data.confidence_successful = false
|
|
33
|
+
await trackEvent(request, eventBotAiModel)
|
|
34
|
+
return undefined
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isIntentValid(
|
|
39
|
+
intentNode: HtIntentNode | undefined,
|
|
40
|
+
request: ActionRequest,
|
|
41
|
+
cmsApi: FlowBuilderApi
|
|
42
|
+
) {
|
|
43
|
+
return (
|
|
44
|
+
intentNode &&
|
|
45
|
+
request.input.confidence &&
|
|
46
|
+
cmsApi.hasMetConfidenceThreshold(intentNode, request.input.confidence)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventBotKeywordModel,
|
|
3
|
+
EventName,
|
|
4
|
+
} from '@botonic/plugin-hubtype-analytics/lib/cjs/types'
|
|
5
|
+
import { ActionRequest } from '@botonic/react'
|
|
6
|
+
|
|
7
|
+
import { FlowBuilderApi } from '../api'
|
|
8
|
+
import { trackEvent } from './tracking'
|
|
9
|
+
|
|
10
|
+
export async function getNodeByKeyword(
|
|
11
|
+
cmsApi: FlowBuilderApi,
|
|
12
|
+
locale: string,
|
|
13
|
+
request: ActionRequest,
|
|
14
|
+
userInput: string
|
|
15
|
+
) {
|
|
16
|
+
const keywordNode = cmsApi.getNodeByKeyword(userInput, locale)
|
|
17
|
+
const eventBotKeywordModel: EventBotKeywordModel = {
|
|
18
|
+
event_type: EventName.botKeywordsModel,
|
|
19
|
+
event_data: {
|
|
20
|
+
confidence_successful: true,
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
if (keywordNode) {
|
|
24
|
+
await trackEvent(request, eventBotKeywordModel)
|
|
25
|
+
return keywordNode
|
|
26
|
+
}
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HtEventProps } from '@botonic/plugin-hubtype-analytics/lib/cjs/types'
|
|
2
|
+
import { ActionRequest } from '@botonic/react'
|
|
3
|
+
|
|
4
|
+
import { getFlowBuilderPlugin } from '../helpers'
|
|
5
|
+
|
|
6
|
+
export async function trackEvent(request: ActionRequest, event: HtEventProps) {
|
|
7
|
+
const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
|
|
8
|
+
if (flowBuilderPlugin.trackEvent) {
|
|
9
|
+
await flowBuilderPlugin.trackEvent(request, event.event_type, event)
|
|
10
|
+
}
|
|
11
|
+
return
|
|
12
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EventBotStart,
|
|
3
|
+
EventName,
|
|
4
|
+
} from '@botonic/plugin-hubtype-analytics/lib/cjs/types'
|
|
5
|
+
import { ActionRequest } from '@botonic/react'
|
|
6
|
+
|
|
7
|
+
import { FlowBuilderApi } from '../api'
|
|
8
|
+
import { HtNodeWithContent } from '../content-fields/hubtype-fields'
|
|
9
|
+
import { getNodeByIntent } from './intent'
|
|
10
|
+
import { getNodeByKeyword } from './keyword'
|
|
11
|
+
import { trackEvent } from './tracking'
|
|
12
|
+
|
|
13
|
+
export async function getNodeByUserInput(
|
|
14
|
+
cmsApi: FlowBuilderApi,
|
|
15
|
+
locale: string,
|
|
16
|
+
request: ActionRequest
|
|
17
|
+
): Promise<HtNodeWithContent | undefined> {
|
|
18
|
+
if (request.session.is_first_interaction) {
|
|
19
|
+
const startNode = cmsApi.getStartNode()
|
|
20
|
+
const event: EventBotStart = {
|
|
21
|
+
event_type: EventName.botStart,
|
|
22
|
+
}
|
|
23
|
+
await trackEvent(request, event)
|
|
24
|
+
return startNode
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (request.input.data) {
|
|
28
|
+
const nodeByIntent = await getNodeByIntent(cmsApi, locale, request)
|
|
29
|
+
if (nodeByIntent) return nodeByIntent
|
|
30
|
+
|
|
31
|
+
const keywordNode = await getNodeByKeyword(
|
|
32
|
+
cmsApi,
|
|
33
|
+
locale,
|
|
34
|
+
request,
|
|
35
|
+
request.input.data
|
|
36
|
+
)
|
|
37
|
+
if (keywordNode) return keywordNode
|
|
38
|
+
}
|
|
39
|
+
return undefined
|
|
40
|
+
}
|
package/src/api.ts
CHANGED
|
@@ -78,24 +78,16 @@ export class FlowBuilderApi {
|
|
|
78
78
|
: this.getNodeById(fallbackSecondMessage.id)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
getIntentNode(input: Input, locale: string): HtIntentNode | undefined {
|
|
82
82
|
try {
|
|
83
|
-
const
|
|
83
|
+
const intentsNodes = this.flow.nodes.filter(
|
|
84
84
|
node => node.type === HtNodeWithContentType.INTENT
|
|
85
85
|
) as HtIntentNode[]
|
|
86
86
|
const inputIntent = input.intent
|
|
87
|
-
const inputConfidence = input.confidence
|
|
88
87
|
if (inputIntent) {
|
|
89
|
-
|
|
88
|
+
return intentsNodes.find(
|
|
90
89
|
node =>
|
|
91
|
-
inputIntent &&
|
|
92
|
-
this.hasIntent(node, inputIntent, locale) &&
|
|
93
|
-
inputConfidence &&
|
|
94
|
-
this.hasMetConfidenceThreshold(node, inputConfidence)
|
|
95
|
-
)
|
|
96
|
-
return (
|
|
97
|
-
matchedIntentNode?.target &&
|
|
98
|
-
this.getNodeById<HtNodeWithContent>(matchedIntentNode?.target.id)
|
|
90
|
+
inputIntent && this.nodeContainsIntent(node, inputIntent, locale)
|
|
99
91
|
)
|
|
100
92
|
}
|
|
101
93
|
} catch (error) {
|
|
@@ -105,7 +97,7 @@ export class FlowBuilderApi {
|
|
|
105
97
|
return undefined
|
|
106
98
|
}
|
|
107
99
|
|
|
108
|
-
private
|
|
100
|
+
private nodeContainsIntent(
|
|
109
101
|
node: HtIntentNode,
|
|
110
102
|
intent: string,
|
|
111
103
|
locale: string
|
|
@@ -115,7 +107,7 @@ export class FlowBuilderApi {
|
|
|
115
107
|
)
|
|
116
108
|
}
|
|
117
109
|
|
|
118
|
-
|
|
110
|
+
hasMetConfidenceThreshold(
|
|
119
111
|
node: HtIntentNode,
|
|
120
112
|
predictedConfidence: number
|
|
121
113
|
): boolean {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HtMediaFileLocale,
|
|
3
|
+
HtQueueLocale,
|
|
3
4
|
HtTextLocale,
|
|
4
5
|
HtVideoLocale,
|
|
5
6
|
} from './hubtype-fields'
|
|
@@ -21,4 +22,11 @@ export abstract class ContentFieldsBase {
|
|
|
21
22
|
const result = video.find(v => v.locale === locale)
|
|
22
23
|
return result?.url ?? ''
|
|
23
24
|
}
|
|
25
|
+
|
|
26
|
+
static getQueueByLocale(
|
|
27
|
+
locale: string,
|
|
28
|
+
queues: HtQueueLocale[]
|
|
29
|
+
): HtQueueLocale | undefined {
|
|
30
|
+
return queues.find(queue => queue.locale === locale)
|
|
31
|
+
}
|
|
24
32
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { HandOffBuilder } from '@botonic/core'
|
|
2
|
+
import {
|
|
3
|
+
EventHandoffSuccess,
|
|
4
|
+
EventName,
|
|
5
|
+
} from '@botonic/plugin-hubtype-analytics/lib/cjs/types'
|
|
6
|
+
import { ActionRequest } from '@botonic/react'
|
|
7
|
+
import React from 'react'
|
|
8
|
+
|
|
9
|
+
import { trackEvent } from '../action/tracking'
|
|
10
|
+
import { FlowBuilderApi } from '../api'
|
|
11
|
+
import { getQueueAvailability } from '../functions/conditional-queue-status'
|
|
12
|
+
import { ContentFieldsBase } from './content-fields-base'
|
|
13
|
+
import {
|
|
14
|
+
HtCarouselNode,
|
|
15
|
+
HtHandoffNode,
|
|
16
|
+
HtImageNode,
|
|
17
|
+
HtPayloadNode,
|
|
18
|
+
HtQueueLocale,
|
|
19
|
+
HtTextNode,
|
|
20
|
+
HtVideoNode,
|
|
21
|
+
HtWhatsappButtonListNode,
|
|
22
|
+
} from './hubtype-fields'
|
|
23
|
+
|
|
24
|
+
type HtAfterHandoff =
|
|
25
|
+
| HtTextNode
|
|
26
|
+
| HtImageNode
|
|
27
|
+
| HtVideoNode
|
|
28
|
+
| HtCarouselNode
|
|
29
|
+
| HtWhatsappButtonListNode
|
|
30
|
+
|
|
31
|
+
export class FlowHandoff extends ContentFieldsBase {
|
|
32
|
+
public code: string
|
|
33
|
+
public queue?: HtQueueLocale
|
|
34
|
+
public onFinishPayload?: string
|
|
35
|
+
public handoffAutoAssign: boolean
|
|
36
|
+
|
|
37
|
+
static fromHubtypeCMS(
|
|
38
|
+
cmsHandoff: HtHandoffNode,
|
|
39
|
+
locale: string,
|
|
40
|
+
cmsApi: FlowBuilderApi
|
|
41
|
+
): FlowHandoff {
|
|
42
|
+
const newHandoff = new FlowHandoff(cmsHandoff.id)
|
|
43
|
+
newHandoff.code = cmsHandoff.code
|
|
44
|
+
newHandoff.queue = this.getQueueByLocale(locale, cmsHandoff.content.queue)
|
|
45
|
+
newHandoff.onFinishPayload = this.getOnFinishPayload(
|
|
46
|
+
cmsHandoff,
|
|
47
|
+
locale,
|
|
48
|
+
cmsApi
|
|
49
|
+
)
|
|
50
|
+
newHandoff.handoffAutoAssign = cmsHandoff.content.has_auto_assign
|
|
51
|
+
|
|
52
|
+
return newHandoff
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private static getOnFinishPayload(
|
|
56
|
+
cmsHandoff: HtHandoffNode,
|
|
57
|
+
locale: string,
|
|
58
|
+
cmsApi: FlowBuilderApi
|
|
59
|
+
): string | undefined {
|
|
60
|
+
if (cmsHandoff.target?.id) {
|
|
61
|
+
const handoffTargetNode = cmsApi.getNodeById<HtAfterHandoff>(
|
|
62
|
+
cmsHandoff.target?.id
|
|
63
|
+
)
|
|
64
|
+
if (handoffTargetNode?.id) return handoffTargetNode?.id
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const payloadId = cmsHandoff.content.payload.find(
|
|
68
|
+
payload => payload.locale === locale
|
|
69
|
+
)?.id
|
|
70
|
+
|
|
71
|
+
if (!payloadId) return undefined
|
|
72
|
+
|
|
73
|
+
const actionPayload = cmsApi.getNodeById(payloadId)
|
|
74
|
+
|
|
75
|
+
return (actionPayload as HtPayloadNode).content.payload
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async doHandoff(request: ActionRequest) {
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
const handOffBuilder = new HandOffBuilder(request.session)
|
|
81
|
+
handOffBuilder.withAutoAssignOnWaiting(this.handoffAutoAssign)
|
|
82
|
+
if (this.onFinishPayload) {
|
|
83
|
+
handOffBuilder.withOnFinishPayload(this.onFinishPayload)
|
|
84
|
+
}
|
|
85
|
+
if (this.queue) {
|
|
86
|
+
const availabilityData = await getQueueAvailability(this.queue.id)
|
|
87
|
+
const event: EventHandoffSuccess = {
|
|
88
|
+
event_type: EventName.handoffSuccess,
|
|
89
|
+
event_data: {
|
|
90
|
+
queue_open: availabilityData.open,
|
|
91
|
+
available_agents: availabilityData.available_agents > 0,
|
|
92
|
+
threshold_reached:
|
|
93
|
+
availabilityData.availability_threshold_waiting_cases > 0,
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
await trackEvent(request, event)
|
|
97
|
+
|
|
98
|
+
handOffBuilder.withQueue(this.queue.id)
|
|
99
|
+
await handOffBuilder.handOff()
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
toBotonic(): JSX.Element {
|
|
104
|
+
return <></>
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FlowCarousel } from './flow-carousel'
|
|
2
|
+
import { FlowHandoff } from './flow-handoff'
|
|
2
3
|
import { FlowImage } from './flow-image'
|
|
3
4
|
import { FlowText } from './flow-text'
|
|
4
5
|
import { FlowVideo } from './flow-video'
|
|
@@ -8,6 +9,7 @@ export { ContentFieldsBase } from './content-fields-base'
|
|
|
8
9
|
export { FlowButton } from './flow-button'
|
|
9
10
|
export { FlowElement } from './flow-element'
|
|
10
11
|
export { FlowCarousel, FlowImage, FlowText, FlowVideo, FlowWhatsappButtonList }
|
|
12
|
+
export { FlowHandoff } from './flow-handoff'
|
|
11
13
|
|
|
12
14
|
export type FlowContent =
|
|
13
15
|
| FlowCarousel
|
|
@@ -15,3 +17,4 @@ export type FlowContent =
|
|
|
15
17
|
| FlowText
|
|
16
18
|
| FlowVideo
|
|
17
19
|
| FlowWhatsappButtonList
|
|
20
|
+
| FlowHandoff
|