@botonic/plugin-flow-builder 0.21.0-alpha.0
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/README.md +1 -0
- package/lib/action.d.ts +15 -0
- package/lib/action.js +62 -0
- package/lib/action.js.map +1 -0
- package/lib/content-fields/button.d.ts +10 -0
- package/lib/content-fields/button.js +33 -0
- package/lib/content-fields/button.js.map +1 -0
- package/lib/content-fields/carousel.d.ts +10 -0
- package/lib/content-fields/carousel.js +37 -0
- package/lib/content-fields/carousel.js.map +1 -0
- package/lib/content-fields/content-base.d.ts +10 -0
- package/lib/content-fields/content-base.js +15 -0
- package/lib/content-fields/content-base.js.map +1 -0
- package/lib/content-fields/element.d.ts +11 -0
- package/lib/content-fields/element.js +25 -0
- package/lib/content-fields/element.js.map +1 -0
- package/lib/content-fields/image.d.ts +9 -0
- package/lib/content-fields/image.js +28 -0
- package/lib/content-fields/image.js.map +1 -0
- package/lib/content-fields/text.d.ts +12 -0
- package/lib/content-fields/text.js +35 -0
- package/lib/content-fields/text.js.map +1 -0
- package/lib/functions/conditional-provider.d.ts +4 -0
- package/lib/functions/conditional-provider.js +11 -0
- package/lib/functions/conditional-provider.js.map +1 -0
- package/lib/functions/conditional-queue-status.d.ts +3 -0
- package/lib/functions/conditional-queue-status.js +25 -0
- package/lib/functions/conditional-queue-status.js.map +1 -0
- package/lib/functions/index.d.ts +6 -0
- package/lib/functions/index.js +10 -0
- package/lib/functions/index.js.map +1 -0
- package/lib/handoff.d.ts +2 -0
- package/lib/handoff.js +39 -0
- package/lib/handoff.js.map +1 -0
- package/lib/hubtype-models.d.ts +152 -0
- package/lib/hubtype-models.js +50 -0
- package/lib/hubtype-models.js.map +1 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.js +171 -0
- package/lib/index.js.map +1 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +10 -0
- package/lib/utils.js.map +1 -0
- package/package.json +53 -0
- package/src/action.tsx +62 -0
- package/src/content-fields/button.tsx +34 -0
- package/src/content-fields/carousel.tsx +42 -0
- package/src/content-fields/content-base.ts +15 -0
- package/src/content-fields/element.tsx +24 -0
- package/src/content-fields/image.tsx +22 -0
- package/src/content-fields/text.tsx +35 -0
- package/src/functions/conditional-provider.ts +5 -0
- package/src/functions/conditional-queue-status.ts +9 -0
- package/src/functions/index.ts +7 -0
- package/src/handoff.ts +27 -0
- package/src/hubtype-models.ts +190 -0
- package/src/index.ts +210 -0
- package/src/utils.ts +6 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NodeContentType = exports.InputType = exports.InputContentType = exports.StartFieldsType = exports.MediaContentType = exports.SubContentType = exports.NonMessageContentType = exports.MessageContentType = exports.ButtonStyle = void 0;
|
|
4
|
+
var ButtonStyle;
|
|
5
|
+
(function (ButtonStyle) {
|
|
6
|
+
ButtonStyle["BUTTON"] = "button";
|
|
7
|
+
ButtonStyle["QUICK_REPLY"] = "quick-reply";
|
|
8
|
+
})(ButtonStyle = exports.ButtonStyle || (exports.ButtonStyle = {}));
|
|
9
|
+
var MessageContentType;
|
|
10
|
+
(function (MessageContentType) {
|
|
11
|
+
MessageContentType["CAROUSEL"] = "carousel";
|
|
12
|
+
MessageContentType["IMAGE"] = "image";
|
|
13
|
+
MessageContentType["TEXT"] = "text";
|
|
14
|
+
MessageContentType["KEYWORD"] = "keyword";
|
|
15
|
+
MessageContentType["HANDOFF"] = "handoff";
|
|
16
|
+
MessageContentType["FUNCTION"] = "function";
|
|
17
|
+
MessageContentType["INTENT"] = "intent";
|
|
18
|
+
})(MessageContentType = exports.MessageContentType || (exports.MessageContentType = {}));
|
|
19
|
+
// TODO: refactor types correctly
|
|
20
|
+
var NonMessageContentType;
|
|
21
|
+
(function (NonMessageContentType) {
|
|
22
|
+
NonMessageContentType["INTENT"] = "intent";
|
|
23
|
+
NonMessageContentType["PAYLOAD"] = "payload";
|
|
24
|
+
NonMessageContentType["QUEUE"] = "queue";
|
|
25
|
+
NonMessageContentType["URL"] = "url";
|
|
26
|
+
})(NonMessageContentType = exports.NonMessageContentType || (exports.NonMessageContentType = {}));
|
|
27
|
+
var SubContentType;
|
|
28
|
+
(function (SubContentType) {
|
|
29
|
+
SubContentType["BUTTON"] = "button";
|
|
30
|
+
SubContentType["ELEMENT"] = "element";
|
|
31
|
+
})(SubContentType = exports.SubContentType || (exports.SubContentType = {}));
|
|
32
|
+
var MediaContentType;
|
|
33
|
+
(function (MediaContentType) {
|
|
34
|
+
MediaContentType["ASSET"] = "asset";
|
|
35
|
+
})(MediaContentType = exports.MediaContentType || (exports.MediaContentType = {}));
|
|
36
|
+
var StartFieldsType;
|
|
37
|
+
(function (StartFieldsType) {
|
|
38
|
+
StartFieldsType["STARTUP"] = "startUp";
|
|
39
|
+
})(StartFieldsType = exports.StartFieldsType || (exports.StartFieldsType = {}));
|
|
40
|
+
var InputContentType;
|
|
41
|
+
(function (InputContentType) {
|
|
42
|
+
InputContentType["INPUT"] = "user-input";
|
|
43
|
+
})(InputContentType = exports.InputContentType || (exports.InputContentType = {}));
|
|
44
|
+
var InputType;
|
|
45
|
+
(function (InputType) {
|
|
46
|
+
InputType["INTENTS"] = "intents";
|
|
47
|
+
InputType["KEYWORDS"] = "keywords";
|
|
48
|
+
})(InputType = exports.InputType || (exports.InputType = {}));
|
|
49
|
+
exports.NodeContentType = Object.assign(Object.assign({}, MessageContentType), InputContentType);
|
|
50
|
+
//# sourceMappingURL=hubtype-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hubtype-models.js","sourceRoot":"","sources":["../src/hubtype-models.ts"],"names":[],"mappings":";;;AAAA,IAAY,WAGX;AAHD,WAAY,WAAW;IACrB,gCAAiB,CAAA;IACjB,0CAA2B,CAAA;AAC7B,CAAC,EAHW,WAAW,GAAX,mBAAW,KAAX,mBAAW,QAGtB;AAED,IAAY,kBAQX;AARD,WAAY,kBAAkB;IAC5B,2CAAqB,CAAA;IACrB,qCAAe,CAAA;IACf,mCAAa,CAAA;IACb,yCAAmB,CAAA;IACnB,yCAAmB,CAAA;IACnB,2CAAqB,CAAA;IACrB,uCAAiB,CAAA;AACnB,CAAC,EARW,kBAAkB,GAAlB,0BAAkB,KAAlB,0BAAkB,QAQ7B;AAED,iCAAiC;AACjC,IAAY,qBAKX;AALD,WAAY,qBAAqB;IAC/B,0CAAiB,CAAA;IACjB,4CAAmB,CAAA;IACnB,wCAAe,CAAA;IACf,oCAAW,CAAA;AACb,CAAC,EALW,qBAAqB,GAArB,6BAAqB,KAArB,6BAAqB,QAKhC;AAED,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,mCAAiB,CAAA;IACjB,qCAAmB,CAAA;AACrB,CAAC,EAHW,cAAc,GAAd,sBAAc,KAAd,sBAAc,QAGzB;AAED,IAAY,gBAEX;AAFD,WAAY,gBAAgB;IAC1B,mCAAe,CAAA;AACjB,CAAC,EAFW,gBAAgB,GAAhB,wBAAgB,KAAhB,wBAAgB,QAE3B;AAED,IAAY,eAEX;AAFD,WAAY,eAAe;IACzB,sCAAmB,CAAA;AACrB,CAAC,EAFW,eAAe,GAAf,uBAAe,KAAf,uBAAe,QAE1B;AAED,IAAY,gBAEX;AAFD,WAAY,gBAAgB;IAC1B,wCAAoB,CAAA;AACtB,CAAC,EAFW,gBAAgB,GAAhB,wBAAgB,KAAhB,wBAAgB,QAE3B;AAED,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,gCAAmB,CAAA;IACnB,kCAAqB,CAAA;AACvB,CAAC,EAHW,SAAS,GAAT,iBAAS,KAAT,iBAAS,QAGpB;AAEY,QAAA,eAAe,mCACvB,kBAAkB,GAClB,gBAAgB,EACpB"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Input, Plugin, PluginPostRequest, PluginPreRequest } from '@botonic/core';
|
|
2
|
+
import { FlowContent } from './content-fields/content-base';
|
|
3
|
+
import { HtFlowBuilderData, HtFunctionNode, HtHandoffNode, HtIntentNode, HtKeywordNode, HtNodeComponent } from './hubtype-models';
|
|
4
|
+
declare type BotonicPluginFlowBuilderOptions = {
|
|
5
|
+
flowUrl: string;
|
|
6
|
+
flow: any;
|
|
7
|
+
customFunctions: Record<any, any>;
|
|
8
|
+
};
|
|
9
|
+
export default class BotonicPluginFlowBuilder implements Plugin {
|
|
10
|
+
readonly options: BotonicPluginFlowBuilderOptions;
|
|
11
|
+
private flowUrl;
|
|
12
|
+
private flow;
|
|
13
|
+
private functions;
|
|
14
|
+
private currentRequest;
|
|
15
|
+
constructor(options: BotonicPluginFlowBuilderOptions);
|
|
16
|
+
readFlowContent(): Promise<HtFlowBuilderData>;
|
|
17
|
+
pre(request: PluginPreRequest): Promise<void>;
|
|
18
|
+
post(_request: PluginPostRequest): Promise<void>;
|
|
19
|
+
getContent(id: string): Promise<HtNodeComponent>;
|
|
20
|
+
getHandoffContent(): Promise<HtHandoffNode>;
|
|
21
|
+
getFlowContent(hubtypeContent: HtNodeComponent, locale: string): FlowContent | undefined;
|
|
22
|
+
getContents(id: string, locale: string, prevContents?: FlowContent[]): Promise<FlowContent[]>;
|
|
23
|
+
getPayloadByInput(input: Input, locale: string): Promise<string | undefined>;
|
|
24
|
+
hasIntent(node: HtIntentNode, intent: string, locale: string): boolean;
|
|
25
|
+
getPayloadByKeyword(input: Input, locale: string): Promise<string | undefined>;
|
|
26
|
+
matchKeywords(node: HtKeywordNode, input: string, locale: string): boolean;
|
|
27
|
+
containsAnyKeywords(input: string, keywords: string[]): boolean;
|
|
28
|
+
callFunction(functionNode: HtFunctionNode, locale: string): Promise<string>;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const axios_1 = __importDefault(require("axios"));
|
|
16
|
+
const carousel_1 = require("./content-fields/carousel");
|
|
17
|
+
const image_1 = require("./content-fields/image");
|
|
18
|
+
const text_1 = require("./content-fields/text");
|
|
19
|
+
const functions_1 = require("./functions");
|
|
20
|
+
const hubtype_models_1 = require("./hubtype-models");
|
|
21
|
+
class BotonicPluginFlowBuilder {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.options = options;
|
|
24
|
+
this.flowUrl = options.flowUrl;
|
|
25
|
+
this.flow = options.flow || this.readFlowContent();
|
|
26
|
+
const customFunctions = options.customFunctions || {};
|
|
27
|
+
this.functions = Object.assign(Object.assign({}, functions_1.DEFAULT_FUNCTIONS), customFunctions);
|
|
28
|
+
}
|
|
29
|
+
readFlowContent() {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
const response = yield axios_1.default.get(this.flowUrl);
|
|
32
|
+
const data = yield response.data;
|
|
33
|
+
//@ts-ignore
|
|
34
|
+
return Promise.resolve(data);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
pre(request) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
this.currentRequest = request;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
post(_request) {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () { });
|
|
44
|
+
}
|
|
45
|
+
getContent(id) {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
const flow = yield this.flow;
|
|
48
|
+
const content = flow.nodes.find((c) => c.id === id);
|
|
49
|
+
if (!content)
|
|
50
|
+
throw Error(`text with id: '${id}' not found`);
|
|
51
|
+
return content;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
getHandoffContent() {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const flow = yield this.flow;
|
|
57
|
+
const content = flow.nodes.find((c) => c.type === 'handoff');
|
|
58
|
+
if (!content)
|
|
59
|
+
throw Error(`Handoff node not found`);
|
|
60
|
+
return content;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
getFlowContent(hubtypeContent, locale) {
|
|
64
|
+
switch (hubtypeContent.type) {
|
|
65
|
+
case hubtype_models_1.MessageContentType.TEXT:
|
|
66
|
+
return text_1.FlowText.fromHubtypeCMS(hubtypeContent, locale);
|
|
67
|
+
case hubtype_models_1.MessageContentType.IMAGE:
|
|
68
|
+
return image_1.FlowImage.fromHubtypeCMS(hubtypeContent, locale);
|
|
69
|
+
case hubtype_models_1.MessageContentType.CAROUSEL:
|
|
70
|
+
return carousel_1.FlowCarousel.fromHubtypeCMS(hubtypeContent, locale);
|
|
71
|
+
default:
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
getContents(id, locale, prevContents) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
const contents = prevContents || [];
|
|
78
|
+
const hubtypeContent = yield this.getContent(id);
|
|
79
|
+
const content = yield this.getFlowContent(hubtypeContent, locale);
|
|
80
|
+
if (hubtypeContent.type === hubtype_models_1.MessageContentType.FUNCTION) {
|
|
81
|
+
const targetId = yield this.callFunction(hubtypeContent, locale);
|
|
82
|
+
return this.getContents(targetId, locale, contents);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (content)
|
|
86
|
+
contents.push(content);
|
|
87
|
+
// TODO: prevent infinite recursive calls
|
|
88
|
+
if (hubtypeContent.follow_up)
|
|
89
|
+
return this.getContents(hubtypeContent.follow_up.id, locale, contents);
|
|
90
|
+
}
|
|
91
|
+
// execute function
|
|
92
|
+
// return this.getContents(function result_mapping target, locale, contents)
|
|
93
|
+
return contents;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
getPayloadByInput(input, locale) {
|
|
97
|
+
var _a;
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
try {
|
|
100
|
+
const flow = yield this.flow;
|
|
101
|
+
const intents = flow.nodes.filter(node => node.type == hubtype_models_1.MessageContentType.INTENT);
|
|
102
|
+
if (input.intent) {
|
|
103
|
+
const matchedIntents = intents.filter(node =>
|
|
104
|
+
//@ts-ignore
|
|
105
|
+
this.hasIntent(node, input.intent, locale));
|
|
106
|
+
if (matchedIntents.length > 0) {
|
|
107
|
+
return (_a = matchedIntents[0].target) === null || _a === void 0 ? void 0 : _a.id;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
console.error('Error getting payload by input: ', error);
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
hasIntent(node, intent, locale) {
|
|
118
|
+
const result = node.content.intents.find(i => i.locale === locale && i.values.includes(intent));
|
|
119
|
+
return Boolean(result);
|
|
120
|
+
}
|
|
121
|
+
getPayloadByKeyword(input, locale) {
|
|
122
|
+
var _a;
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
try {
|
|
125
|
+
const flow = yield this.flow;
|
|
126
|
+
const keywordNodes = flow.nodes.filter(node => node.type == hubtype_models_1.MessageContentType.KEYWORD);
|
|
127
|
+
const matchedKeywordNodes = keywordNodes.filter(node =>
|
|
128
|
+
//@ts-ignore
|
|
129
|
+
this.matchKeywords(node, input.data, locale));
|
|
130
|
+
if (matchedKeywordNodes.length > 0) {
|
|
131
|
+
return (_a = matchedKeywordNodes[0].target) === null || _a === void 0 ? void 0 : _a.id;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('Error getting payload by input: ', error);
|
|
136
|
+
}
|
|
137
|
+
return undefined;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
matchKeywords(node, input, locale) {
|
|
141
|
+
const result = node.content.keywords.find(i => i.locale === locale && this.containsAnyKeywords(input, i.values));
|
|
142
|
+
return Boolean(result);
|
|
143
|
+
}
|
|
144
|
+
containsAnyKeywords(input, keywords) {
|
|
145
|
+
for (let i = 0; i < keywords.length; i++) {
|
|
146
|
+
if (input.includes(keywords[i])) {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
callFunction(functionNode, locale) {
|
|
153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
154
|
+
// Check if target is missing or missing arguments
|
|
155
|
+
// TODO: get arguments by locale
|
|
156
|
+
const nameValues = functionNode.content.arguments
|
|
157
|
+
.find(arg => arg.locale === locale)
|
|
158
|
+
.values.map(value => ({ [value.name]: value.value }));
|
|
159
|
+
const args = Object.assign({
|
|
160
|
+
session: this.currentRequest.session,
|
|
161
|
+
results: [functionNode.content.result_mapping.map(r => r.result)],
|
|
162
|
+
}, ...nameValues);
|
|
163
|
+
const functionResult = yield this.functions[functionNode.content.subtype](args);
|
|
164
|
+
// TODO define result_mapping per locale??
|
|
165
|
+
const result = functionNode.content.result_mapping.find(r => r.result === functionResult);
|
|
166
|
+
return result.target.id;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.default = BotonicPluginFlowBuilder;
|
|
171
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAMA,kDAAyB;AAEzB,wDAAwD;AAExD,kDAAkD;AAClD,gDAAgD;AAChD,2CAA+C;AAC/C,qDASyB;AAQzB,MAAqB,wBAAwB;IAM3C,YAAqB,OAAwC;QAAxC,YAAO,GAAP,OAAO,CAAiC;QAC3D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE,CAAA;QAClD,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,EAAE,CAAA;QACrD,IAAI,CAAC,SAAS,mCAAQ,6BAAiB,GAAK,eAAe,CAAE,CAAA;IAC/D,CAAC;IAEK,eAAe;;YACnB,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAC9C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAA;YAChC,YAAY;YACZ,OAAO,OAAO,CAAC,OAAO,CAAC,IAAyB,CAAC,CAAA;QACnD,CAAC;KAAA;IAEK,GAAG,CAAC,OAAyB;;YACjC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAA;QAC/B,CAAC;KAAA;IAEK,IAAI,CAAC,QAA2B;8DAAkB,CAAC;KAAA;IAEnD,UAAU,CAAC,EAAU;;YACzB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAA;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;YAC/D,IAAI,CAAC,OAAO;gBAAE,MAAM,KAAK,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAA;YAC5D,OAAO,OAAO,CAAA;QAChB,CAAC;KAAA;IAEK,iBAAiB;;YACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAA;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAC7B,CAAC,CAAkB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAC5B,CAAA;YAClB,IAAI,CAAC,OAAO;gBAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAA;YACnD,OAAO,OAAO,CAAA;QAChB,CAAC;KAAA;IAED,cAAc,CACZ,cAA+B,EAC/B,MAAc;QAEd,QAAQ,cAAc,CAAC,IAAI,EAAE;YAC3B,KAAK,mCAAkB,CAAC,IAAI;gBAC1B,OAAO,eAAQ,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;YACxD,KAAK,mCAAkB,CAAC,KAAK;gBAC3B,OAAO,iBAAS,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;YACzD,KAAK,mCAAkB,CAAC,QAAQ;gBAC9B,OAAO,uBAAY,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;YAC5D;gBACE,OAAO,SAAS,CAAA;SACnB;IACH,CAAC;IAEK,WAAW,CACf,EAAU,EACV,MAAc,EACd,YAA4B;;YAE5B,MAAM,QAAQ,GAAG,YAAY,IAAI,EAAE,CAAA;YACnC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;YAChD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;YACjE,IAAI,cAAc,CAAC,IAAI,KAAK,mCAAkB,CAAC,QAAQ,EAAE;gBACvD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CACtC,cAAgC,EAChC,MAAM,CACP,CAAA;gBACD,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;aACpD;iBAAM;gBACL,IAAI,OAAO;oBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACnC,yCAAyC;gBACzC,IAAI,cAAc,CAAC,SAAS;oBAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;aACzE;YACD,mBAAmB;YACnB,4EAA4E;YAC5E,OAAO,QAAQ,CAAA;QACjB,CAAC;KAAA;IAEK,iBAAiB,CACrB,KAAY,EACZ,MAAc;;;YAEd,IAAI;gBACF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAA;gBAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAC/B,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,mCAAkB,CAAC,MAAM,CAC7B,CAAA;gBACnB,IAAI,KAAK,CAAC,MAAM,EAAE;oBAChB,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;oBAC3C,YAAY;oBACZ,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAC3C,CAAA;oBACD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;wBAC7B,OAAO,MAAA,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,0CAAE,EAAE,CAAA;qBACpC;iBACF;aACF;YAAC,OAAO,KAAK,EAAE;gBACd,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAA;aACzD;YAED,OAAO,SAAS,CAAA;;KACjB;IAED,SAAS,CAAC,IAAkB,EAAE,MAAc,EAAE,MAAc;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CACtC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CACtD,CAAA;QACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;IACxB,CAAC;IAEK,mBAAmB,CACvB,KAAY,EACZ,MAAc;;;YAEd,IAAI;gBACF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAA;gBAC5B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CACpC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,mCAAkB,CAAC,OAAO,CAC7B,CAAA;gBACpB,MAAM,mBAAmB,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;gBACrD,YAAY;gBACZ,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAC7C,CAAA;gBACD,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE;oBAClC,OAAO,MAAA,mBAAmB,CAAC,CAAC,CAAC,CAAC,MAAM,0CAAE,EAAE,CAAA;iBACzC;aACF;YAAC,OAAO,KAAK,EAAE;gBACd,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAA;aACzD;YAED,OAAO,SAAS,CAAA;;KACjB;IAED,aAAa,CAAC,IAAmB,EAAE,KAAa,EAAE,MAAc;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CACtE,CAAA;QACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAA;IACxB,CAAC;IAED,mBAAmB,CAAC,KAAa,EAAE,QAAkB;QACnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACxC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC/B,OAAO,IAAI,CAAA;aACZ;SACF;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAEK,YAAY,CAChB,YAA4B,EAC5B,MAAc;;YAEd,kDAAkD;YAClD,gCAAgC;YAChC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS;iBAC9C,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC;iBAClC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACvD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CACxB;gBACE,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO;gBACpC,OAAO,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;aAClE,EACD,GAAG,UAAU,CACd,CAAA;YACD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CACvE,IAAI,CACL,CAAA;YACD,0CAA0C;YAC1C,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,CACrD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,cAAc,CACjC,CAAA;YACD,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,CAAA;QACzB,CAAC;KAAA;CACF;AAnLD,2CAmLC"}
|
package/lib/utils.d.ts
ADDED
package/lib/utils.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getImageByLocale = void 0;
|
|
4
|
+
function getImageByLocale(locale, image) {
|
|
5
|
+
var _a;
|
|
6
|
+
const result = image.find(t => t.locale == locale);
|
|
7
|
+
return (_a = result === null || result === void 0 ? void 0 : result.file) !== null && _a !== void 0 ? _a : '';
|
|
8
|
+
}
|
|
9
|
+
exports.getImageByLocale = getImageByLocale;
|
|
10
|
+
//# sourceMappingURL=utils.js.map
|
package/lib/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAEA,SAAgB,gBAAgB,CAAC,MAAc,EAAE,KAA0B;;IACzE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,CAAA;IAClD,OAAO,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,mCAAI,EAAE,CAAA;AAC3B,CAAC;AAHD,4CAGC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@botonic/plugin-flow-builder",
|
|
3
|
+
"version": "0.21.0-alpha.0",
|
|
4
|
+
"main": "lib/index.js",
|
|
5
|
+
"description": "Use Flow Builder to show your contents",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "rm -rf lib && ../../node_modules/.bin/tsc",
|
|
8
|
+
"build:watch": "../../node_modules/.bin/tsc --watch",
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
|
+
"cloc": "../../scripts/qa/cloc-package.sh .",
|
|
11
|
+
"prepare": "node ../../preinstall.js",
|
|
12
|
+
"prepublishOnly": "rm -rf lib && npm run build",
|
|
13
|
+
"lint": "npm run lint_core -- --fix",
|
|
14
|
+
"lint_ci": "npm run lint_core -- -c ../.eslintrc_slow.js",
|
|
15
|
+
"lint_core": "../../node_modules/.bin/eslint_d --cache --quiet 'src/**/*.ts*'"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/hubtype/botonic.git"
|
|
20
|
+
},
|
|
21
|
+
"author": "",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/hubtype/botonic/issues"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"lib/**",
|
|
27
|
+
"src/**",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^18.13.0",
|
|
32
|
+
"@types/react": "^18.0.28",
|
|
33
|
+
"typescript": "^4.9.5"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"bot-framework",
|
|
37
|
+
"chatbot",
|
|
38
|
+
"flow-builder",
|
|
39
|
+
"conversational-app",
|
|
40
|
+
"conversational-ui",
|
|
41
|
+
"javascript"
|
|
42
|
+
],
|
|
43
|
+
"eslintConfig": {
|
|
44
|
+
"extends": "../.eslintrc.js",
|
|
45
|
+
"root": true
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@babel/runtime": "^7.20.13",
|
|
49
|
+
"@botonic/core": "^0.21.0",
|
|
50
|
+
"@botonic/react": "^0.21.0",
|
|
51
|
+
"axios": "^1.3.3"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/src/action.tsx
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ActionRequest, RequestContext, Text } from '@botonic/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { FlowContent } from './content-fields/content-base'
|
|
5
|
+
import { doHandoff } from './handoff'
|
|
6
|
+
import { HtHandoffNode } from './hubtype-models'
|
|
7
|
+
|
|
8
|
+
// TODO: remove this from here and use the new "start" attribute in the flow
|
|
9
|
+
export const START = '08c7df06-0c7c-4f06-b8c1-4157582efeb2'
|
|
10
|
+
|
|
11
|
+
type FlowBuilderActionProps = {
|
|
12
|
+
content?: FlowContent[]
|
|
13
|
+
handoffMsg?: HtHandoffNode
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default class FlowBuilderAction extends React.Component<FlowBuilderActionProps> {
|
|
17
|
+
static contextType = RequestContext
|
|
18
|
+
|
|
19
|
+
static async botonicInit(request: ActionRequest): Promise<any> {
|
|
20
|
+
const flowBuilderPlugin = request.plugins.hubtypeFlowBuilder as any
|
|
21
|
+
|
|
22
|
+
let payload = request.input.payload ? request.input.payload : START
|
|
23
|
+
if (!request.input.payload) {
|
|
24
|
+
const intentPayload = await flowBuilderPlugin.getPayloadByInput(
|
|
25
|
+
request.input,
|
|
26
|
+
'es-ES'
|
|
27
|
+
)
|
|
28
|
+
if (intentPayload) {
|
|
29
|
+
payload = intentPayload
|
|
30
|
+
}
|
|
31
|
+
const keywordPayload = await flowBuilderPlugin.getPayloadByKeyword(
|
|
32
|
+
request.input,
|
|
33
|
+
'es-ES'
|
|
34
|
+
)
|
|
35
|
+
if (keywordPayload) {
|
|
36
|
+
payload = keywordPayload
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// We use only Spanish because they are the backend examples
|
|
40
|
+
const content = await flowBuilderPlugin.getContents(payload, 'es-ES')
|
|
41
|
+
|
|
42
|
+
if (content.length == 0) {
|
|
43
|
+
const handoffMsg = await doHandoff(request)
|
|
44
|
+
return { handoffMsg }
|
|
45
|
+
}
|
|
46
|
+
return { content }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
render() {
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
const { content: contents, handoffMsg } = this.props
|
|
52
|
+
if (handoffMsg) {
|
|
53
|
+
// @ts-ignore
|
|
54
|
+
return <Text>{handoffMsg}</Text>
|
|
55
|
+
} else {
|
|
56
|
+
return contents!.map((content, index) => {
|
|
57
|
+
console.log({ content, index })
|
|
58
|
+
return content.toBotonic(index)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Button, Reply } from '@botonic/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { ButtonStyle, HtButton } from '../hubtype-models'
|
|
5
|
+
import { ContentFieldsBase } from './content-base'
|
|
6
|
+
|
|
7
|
+
export class FlowButton extends ContentFieldsBase {
|
|
8
|
+
public text = ''
|
|
9
|
+
public url?: string
|
|
10
|
+
public payload?: string
|
|
11
|
+
|
|
12
|
+
static fromHubtypeCMS(component: HtButton, locale: string): FlowButton {
|
|
13
|
+
const newButton = new FlowButton(component.id)
|
|
14
|
+
newButton.text = FlowButton.getTextByLocale(locale, component.text)
|
|
15
|
+
newButton.payload = component.target?.id
|
|
16
|
+
return newButton
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
renderButton(index: number, buttonStyle: ButtonStyle) {
|
|
20
|
+
if (buttonStyle == ButtonStyle.QUICK_REPLY) {
|
|
21
|
+
return (
|
|
22
|
+
<Reply payload={this.payload} key={index}>
|
|
23
|
+
{this.text}
|
|
24
|
+
</Reply>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
return (
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
<Button payload={this.payload} key={index}>
|
|
30
|
+
{this.text}
|
|
31
|
+
</Button>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Button, Carousel, Element, Pic, Subtitle, Title } from '@botonic/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { HtCarouselNode } from '../hubtype-models'
|
|
5
|
+
import { ContentFieldsBase } from './content-base'
|
|
6
|
+
import { FlowElement } from './element'
|
|
7
|
+
|
|
8
|
+
export class FlowCarousel extends ContentFieldsBase {
|
|
9
|
+
public code = ''
|
|
10
|
+
public elements: FlowElement[] = []
|
|
11
|
+
|
|
12
|
+
static fromHubtypeCMS(
|
|
13
|
+
component: HtCarouselNode,
|
|
14
|
+
locale: string
|
|
15
|
+
): FlowCarousel {
|
|
16
|
+
const newCarousel = new FlowCarousel(component.id)
|
|
17
|
+
newCarousel.code = component.code
|
|
18
|
+
newCarousel.elements = component.content.elements.map(ele =>
|
|
19
|
+
FlowElement.fromHubtypeCMS(ele, locale)
|
|
20
|
+
)
|
|
21
|
+
return newCarousel
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
toBotonic(index: number) {
|
|
25
|
+
return (
|
|
26
|
+
<Carousel key={index}>
|
|
27
|
+
{this.elements.map((e, eIndex) => {
|
|
28
|
+
console.log('TO BOTONIC BOTONIC PACKAGES', { e })
|
|
29
|
+
return (
|
|
30
|
+
<Element key={eIndex}>
|
|
31
|
+
<Pic src={e.image} />
|
|
32
|
+
<Title style=''>{e.title}</Title>
|
|
33
|
+
<Subtitle style=''>{e.subtitle}</Subtitle>
|
|
34
|
+
{/* @ts-ignore */}
|
|
35
|
+
<Button payload={e.buttons?.payload}>{e.buttons?.text}</Button>,
|
|
36
|
+
</Element>
|
|
37
|
+
)
|
|
38
|
+
})}
|
|
39
|
+
</Carousel>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { HtTextLocale } from '../hubtype-models'
|
|
2
|
+
import { FlowCarousel } from './carousel'
|
|
3
|
+
import { FlowImage } from './image'
|
|
4
|
+
import { FlowText } from './text'
|
|
5
|
+
|
|
6
|
+
export abstract class ContentFieldsBase {
|
|
7
|
+
constructor(private readonly id: string) {}
|
|
8
|
+
|
|
9
|
+
static getTextByLocale(locale: string, text: HtTextLocale[]) {
|
|
10
|
+
const result = text.find(t => t.locale == locale)
|
|
11
|
+
return result?.message ?? ''
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type FlowContent = FlowText | FlowImage | FlowCarousel
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { HtElement } from '../hubtype-models'
|
|
2
|
+
import { getImageByLocale } from '../utils'
|
|
3
|
+
import { FlowButton } from './button'
|
|
4
|
+
import { ContentFieldsBase } from './content-base'
|
|
5
|
+
|
|
6
|
+
export class FlowElement extends ContentFieldsBase {
|
|
7
|
+
public title = ''
|
|
8
|
+
public subtitle = ''
|
|
9
|
+
public buttons: FlowButton | undefined
|
|
10
|
+
public image = ''
|
|
11
|
+
public hidden = false
|
|
12
|
+
|
|
13
|
+
static fromHubtypeCMS(component: HtElement, locale: string): FlowElement {
|
|
14
|
+
const newElement = new FlowElement(component.id)
|
|
15
|
+
newElement.title = FlowElement.getTextByLocale(locale, component.title)
|
|
16
|
+
newElement.subtitle = FlowElement.getTextByLocale(
|
|
17
|
+
locale,
|
|
18
|
+
component.subtitle
|
|
19
|
+
)
|
|
20
|
+
newElement.image = getImageByLocale(locale, component.image)
|
|
21
|
+
newElement.buttons = FlowButton.fromHubtypeCMS(component.button, locale)
|
|
22
|
+
return newElement
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Image } from '@botonic/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { HtImageNode } from '../hubtype-models'
|
|
5
|
+
import { getImageByLocale } from '../utils'
|
|
6
|
+
import { ContentFieldsBase } from './content-base'
|
|
7
|
+
|
|
8
|
+
export class FlowImage extends ContentFieldsBase {
|
|
9
|
+
public src = ''
|
|
10
|
+
public code = ''
|
|
11
|
+
|
|
12
|
+
static fromHubtypeCMS(component: HtImageNode, locale: string): FlowImage {
|
|
13
|
+
const newImage = new FlowImage(component.id)
|
|
14
|
+
newImage.code = component.code
|
|
15
|
+
newImage.src = getImageByLocale(locale, component.content.image)
|
|
16
|
+
return newImage
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
toBotonic(index: number) {
|
|
20
|
+
return <Image src={this.src} key={index} />
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Text } from '@botonic/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import { ButtonStyle, HtTextNode } from '../hubtype-models'
|
|
5
|
+
import { FlowButton } from './button'
|
|
6
|
+
import { ContentFieldsBase } from './content-base'
|
|
7
|
+
|
|
8
|
+
export class FlowText extends ContentFieldsBase {
|
|
9
|
+
public text = ''
|
|
10
|
+
public code = ''
|
|
11
|
+
public buttons: FlowButton[] = []
|
|
12
|
+
public buttonStyle = ButtonStyle.BUTTON
|
|
13
|
+
|
|
14
|
+
static fromHubtypeCMS(component: HtTextNode, locale: string): FlowText {
|
|
15
|
+
const newText = new FlowText(component.id)
|
|
16
|
+
newText.code = component.code
|
|
17
|
+
newText.buttonStyle = component.content.buttons_style || ButtonStyle.BUTTON
|
|
18
|
+
newText.text = FlowText.getTextByLocale(locale, component.content.text)
|
|
19
|
+
newText.buttons = component.content.buttons.map(button =>
|
|
20
|
+
FlowButton.fromHubtypeCMS(button, locale)
|
|
21
|
+
)
|
|
22
|
+
return newText
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
toBotonic(index: number) {
|
|
26
|
+
return (
|
|
27
|
+
<Text key={index}>
|
|
28
|
+
{this.text}
|
|
29
|
+
{this.buttons.map((button, index) =>
|
|
30
|
+
button.renderButton(index, this.buttonStyle)
|
|
31
|
+
)}
|
|
32
|
+
</Text>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
|
|
3
|
+
export async function conditionalQueueStatus({ queueId }): Promise<string> {
|
|
4
|
+
const response = await axios.get(
|
|
5
|
+
`https://api.hubtype.com/v1/queues/${queueId}/availability/`
|
|
6
|
+
)
|
|
7
|
+
const isAvailable = response.data.available
|
|
8
|
+
return isAvailable ? 'open' : 'closed'
|
|
9
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { conditionalProvider } from './conditional-provider'
|
|
2
|
+
import { conditionalQueueStatus } from './conditional-queue-status'
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_FUNCTIONS = {
|
|
5
|
+
'conditional-queue-status': conditionalQueueStatus,
|
|
6
|
+
'conditional-provider': conditionalProvider,
|
|
7
|
+
}
|
package/src/handoff.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getOpenQueues, HandOffBuilder } from '@botonic/core'
|
|
2
|
+
import { ActionRequest } from '@botonic/react'
|
|
3
|
+
|
|
4
|
+
// TODO: Remove all "getOpenQueues" logic and open/closed messages.
|
|
5
|
+
// This function should just do a basic handoff
|
|
6
|
+
// TODO: add missing options: withNote, withAgent
|
|
7
|
+
|
|
8
|
+
export async function doHandoff(request: ActionRequest) {
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
const flowBuilderPlugin = request.plugins.hubtypeFlowBuilder as any
|
|
11
|
+
const handoffContent = await flowBuilderPlugin.getHandoffContent()
|
|
12
|
+
console.log(handoffContent)
|
|
13
|
+
// @ts-ignore
|
|
14
|
+
let openQueues = await getOpenQueues(request.session)
|
|
15
|
+
const queueName = 'Test'
|
|
16
|
+
if (openQueues.queues.indexOf(queueName) !== -1) {
|
|
17
|
+
// @ts-ignore
|
|
18
|
+
const handOffBuilder = new HandOffBuilder(request.session)
|
|
19
|
+
handOffBuilder.withQueue('Test')
|
|
20
|
+
handOffBuilder.withOnFinishPayload(handoffContent.target?.id!)
|
|
21
|
+
await handOffBuilder.handOff()
|
|
22
|
+
|
|
23
|
+
return handoffContent.content.message[0].message
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return handoffContent.content.failMessage[0].message
|
|
27
|
+
}
|