@botonic/plugin-flow-builder 0.22.0-beta.3 → 0.22.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.
Files changed (268) hide show
  1. package/lib/cjs/action.d.ts +16 -2
  2. package/lib/cjs/action.js +21 -19
  3. package/lib/cjs/action.js.map +1 -1
  4. package/lib/cjs/api.d.ts +19 -0
  5. package/lib/cjs/api.js +108 -0
  6. package/lib/cjs/api.js.map +1 -0
  7. package/lib/cjs/content-fields/content-fields-base.d.ts +4 -4
  8. package/lib/cjs/content-fields/content-fields-base.js.map +1 -1
  9. package/lib/cjs/content-fields/flow-button.d.ts +6 -3
  10. package/lib/cjs/content-fields/flow-button.js +28 -21
  11. package/lib/cjs/content-fields/flow-button.js.map +1 -1
  12. package/lib/cjs/content-fields/flow-carousel.d.ts +3 -2
  13. package/lib/cjs/content-fields/flow-carousel.js +3 -10
  14. package/lib/cjs/content-fields/flow-carousel.js.map +1 -1
  15. package/lib/cjs/content-fields/flow-element.d.ts +6 -3
  16. package/lib/cjs/content-fields/flow-element.js +16 -5
  17. package/lib/cjs/content-fields/flow-element.js.map +1 -1
  18. package/lib/cjs/content-fields/flow-image.d.ts +2 -2
  19. package/lib/cjs/content-fields/flow-image.js.map +1 -1
  20. package/lib/cjs/content-fields/flow-text.d.ts +4 -3
  21. package/lib/cjs/content-fields/flow-text.js +9 -9
  22. package/lib/cjs/content-fields/flow-text.js.map +1 -1
  23. package/lib/cjs/content-fields/flow-video.d.ts +2 -2
  24. package/lib/cjs/content-fields/flow-video.js +0 -1
  25. package/lib/cjs/content-fields/flow-video.js.map +1 -1
  26. package/lib/cjs/content-fields/hubtype-fields/button.d.ts +9 -0
  27. package/lib/cjs/content-fields/hubtype-fields/button.js +3 -0
  28. package/lib/cjs/content-fields/hubtype-fields/button.js.map +1 -0
  29. package/lib/cjs/content-fields/hubtype-fields/carousel.d.ts +16 -0
  30. package/lib/cjs/content-fields/hubtype-fields/carousel.js +3 -0
  31. package/lib/cjs/content-fields/hubtype-fields/carousel.js.map +1 -0
  32. package/lib/cjs/content-fields/hubtype-fields/common.d.ts +55 -0
  33. package/lib/cjs/content-fields/hubtype-fields/common.js +3 -0
  34. package/lib/cjs/content-fields/hubtype-fields/common.js.map +1 -0
  35. package/lib/cjs/content-fields/hubtype-fields/fallback.d.ts +9 -0
  36. package/lib/cjs/content-fields/hubtype-fields/fallback.js +3 -0
  37. package/lib/cjs/content-fields/hubtype-fields/fallback.js.map +1 -0
  38. package/lib/cjs/content-fields/hubtype-fields/function.d.ts +28 -0
  39. package/lib/cjs/content-fields/hubtype-fields/function.js +10 -0
  40. package/lib/cjs/content-fields/hubtype-fields/function.js.map +1 -0
  41. package/lib/cjs/content-fields/hubtype-fields/handoff.d.ts +10 -0
  42. package/lib/cjs/content-fields/hubtype-fields/handoff.js +3 -0
  43. package/lib/cjs/content-fields/hubtype-fields/handoff.js.map +1 -0
  44. package/lib/cjs/content-fields/hubtype-fields/image.d.ts +8 -0
  45. package/lib/cjs/content-fields/{types.js → hubtype-fields/image.js} +1 -1
  46. package/lib/cjs/content-fields/hubtype-fields/image.js.map +1 -0
  47. package/lib/cjs/content-fields/hubtype-fields/index.d.ts +17 -0
  48. package/lib/cjs/content-fields/hubtype-fields/index.js +21 -0
  49. package/lib/cjs/content-fields/hubtype-fields/index.js.map +1 -0
  50. package/lib/cjs/content-fields/hubtype-fields/intent.d.ts +10 -0
  51. package/lib/cjs/content-fields/hubtype-fields/intent.js +3 -0
  52. package/lib/cjs/content-fields/hubtype-fields/intent.js.map +1 -0
  53. package/lib/cjs/content-fields/hubtype-fields/keyword.d.ts +9 -0
  54. package/lib/cjs/content-fields/hubtype-fields/keyword.js +3 -0
  55. package/lib/cjs/content-fields/hubtype-fields/keyword.js.map +1 -0
  56. package/lib/cjs/content-fields/hubtype-fields/node-types.d.ts +23 -0
  57. package/lib/cjs/content-fields/hubtype-fields/node-types.js +31 -0
  58. package/lib/cjs/content-fields/hubtype-fields/node-types.js.map +1 -0
  59. package/lib/cjs/content-fields/hubtype-fields/nodes.d.ts +16 -0
  60. package/lib/cjs/content-fields/hubtype-fields/nodes.js +3 -0
  61. package/lib/cjs/content-fields/hubtype-fields/nodes.js.map +1 -0
  62. package/lib/cjs/content-fields/hubtype-fields/payload.d.ts +8 -0
  63. package/lib/cjs/content-fields/hubtype-fields/payload.js +3 -0
  64. package/lib/cjs/content-fields/hubtype-fields/payload.js.map +1 -0
  65. package/lib/cjs/content-fields/hubtype-fields/start.d.ts +7 -0
  66. package/lib/cjs/content-fields/hubtype-fields/start.js +3 -0
  67. package/lib/cjs/content-fields/hubtype-fields/start.js.map +1 -0
  68. package/lib/cjs/content-fields/hubtype-fields/text.d.ts +11 -0
  69. package/lib/cjs/content-fields/hubtype-fields/text.js +3 -0
  70. package/lib/cjs/content-fields/hubtype-fields/text.js.map +1 -0
  71. package/lib/cjs/content-fields/hubtype-fields/url.d.ts +8 -0
  72. package/lib/cjs/content-fields/hubtype-fields/url.js +3 -0
  73. package/lib/cjs/content-fields/hubtype-fields/url.js.map +1 -0
  74. package/lib/cjs/content-fields/hubtype-fields/video.d.ts +8 -0
  75. package/lib/cjs/content-fields/hubtype-fields/video.js +3 -0
  76. package/lib/cjs/content-fields/hubtype-fields/video.js.map +1 -0
  77. package/lib/cjs/content-fields/hubtype-fields/whatsapp-button-list.d.ts +21 -0
  78. package/lib/cjs/content-fields/hubtype-fields/whatsapp-button-list.js +3 -0
  79. package/lib/cjs/content-fields/hubtype-fields/whatsapp-button-list.js.map +1 -0
  80. package/lib/cjs/content-fields/index.d.ts +7 -5
  81. package/lib/cjs/content-fields/index.js +11 -9
  82. package/lib/cjs/content-fields/index.js.map +1 -1
  83. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.d.ts +10 -0
  84. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.js +32 -0
  85. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.js.map +1 -0
  86. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.d.ts +10 -0
  87. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js +29 -0
  88. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js.map +1 -0
  89. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list.d.ts +12 -0
  90. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js +33 -0
  91. package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js.map +1 -0
  92. package/lib/cjs/functions/conditional-provider.d.ts +2 -2
  93. package/lib/cjs/functions/conditional-provider.js +2 -2
  94. package/lib/cjs/functions/conditional-provider.js.map +1 -1
  95. package/lib/cjs/functions/conditional-queue-status.d.ts +7 -2
  96. package/lib/cjs/functions/conditional-queue-status.js +11 -1
  97. package/lib/cjs/functions/conditional-queue-status.js.map +1 -1
  98. package/lib/cjs/handoff.d.ts +2 -2
  99. package/lib/cjs/handoff.js +17 -9
  100. package/lib/cjs/handoff.js.map +1 -1
  101. package/lib/cjs/helpers.d.ts +2 -1
  102. package/lib/cjs/helpers.js +5 -13
  103. package/lib/cjs/helpers.js.map +1 -1
  104. package/lib/cjs/index.d.ts +10 -21
  105. package/lib/cjs/index.js +36 -151
  106. package/lib/cjs/index.js.map +1 -1
  107. package/lib/cjs/types.d.ts +8 -2
  108. package/lib/cjs/types.js.map +1 -1
  109. package/lib/esm/action.d.ts +16 -2
  110. package/lib/esm/action.js +21 -19
  111. package/lib/esm/action.js.map +1 -1
  112. package/lib/esm/api.d.ts +19 -0
  113. package/lib/esm/api.js +103 -0
  114. package/lib/esm/api.js.map +1 -0
  115. package/lib/esm/content-fields/content-fields-base.d.ts +4 -4
  116. package/lib/esm/content-fields/content-fields-base.js.map +1 -1
  117. package/lib/esm/content-fields/flow-button.d.ts +6 -3
  118. package/lib/esm/content-fields/flow-button.js +28 -21
  119. package/lib/esm/content-fields/flow-button.js.map +1 -1
  120. package/lib/esm/content-fields/flow-carousel.d.ts +3 -2
  121. package/lib/esm/content-fields/flow-carousel.js +4 -11
  122. package/lib/esm/content-fields/flow-carousel.js.map +1 -1
  123. package/lib/esm/content-fields/flow-element.d.ts +6 -3
  124. package/lib/esm/content-fields/flow-element.js +15 -5
  125. package/lib/esm/content-fields/flow-element.js.map +1 -1
  126. package/lib/esm/content-fields/flow-image.d.ts +2 -2
  127. package/lib/esm/content-fields/flow-image.js.map +1 -1
  128. package/lib/esm/content-fields/flow-text.d.ts +4 -3
  129. package/lib/esm/content-fields/flow-text.js +9 -9
  130. package/lib/esm/content-fields/flow-text.js.map +1 -1
  131. package/lib/esm/content-fields/flow-video.d.ts +2 -2
  132. package/lib/esm/content-fields/flow-video.js +0 -1
  133. package/lib/esm/content-fields/flow-video.js.map +1 -1
  134. package/lib/esm/content-fields/hubtype-fields/button.d.ts +9 -0
  135. package/lib/esm/content-fields/hubtype-fields/button.js +2 -0
  136. package/lib/esm/content-fields/hubtype-fields/button.js.map +1 -0
  137. package/lib/esm/content-fields/hubtype-fields/carousel.d.ts +16 -0
  138. package/lib/esm/content-fields/hubtype-fields/carousel.js +2 -0
  139. package/lib/esm/content-fields/hubtype-fields/carousel.js.map +1 -0
  140. package/lib/esm/content-fields/hubtype-fields/common.d.ts +55 -0
  141. package/lib/esm/content-fields/hubtype-fields/common.js +2 -0
  142. package/lib/esm/content-fields/hubtype-fields/common.js.map +1 -0
  143. package/lib/esm/content-fields/hubtype-fields/fallback.d.ts +9 -0
  144. package/lib/esm/content-fields/hubtype-fields/fallback.js +2 -0
  145. package/lib/esm/content-fields/hubtype-fields/fallback.js.map +1 -0
  146. package/lib/esm/content-fields/hubtype-fields/function.d.ts +28 -0
  147. package/lib/esm/content-fields/hubtype-fields/function.js +7 -0
  148. package/lib/esm/content-fields/hubtype-fields/function.js.map +1 -0
  149. package/lib/esm/content-fields/hubtype-fields/handoff.d.ts +10 -0
  150. package/lib/esm/content-fields/hubtype-fields/handoff.js +2 -0
  151. package/lib/esm/content-fields/hubtype-fields/handoff.js.map +1 -0
  152. package/lib/esm/content-fields/hubtype-fields/image.d.ts +8 -0
  153. package/lib/esm/content-fields/hubtype-fields/image.js +2 -0
  154. package/lib/esm/content-fields/hubtype-fields/image.js.map +1 -0
  155. package/lib/esm/content-fields/hubtype-fields/index.d.ts +17 -0
  156. package/lib/esm/content-fields/hubtype-fields/index.js +18 -0
  157. package/lib/esm/content-fields/hubtype-fields/index.js.map +1 -0
  158. package/lib/esm/content-fields/hubtype-fields/intent.d.ts +10 -0
  159. package/lib/esm/content-fields/hubtype-fields/intent.js +2 -0
  160. package/lib/esm/content-fields/hubtype-fields/intent.js.map +1 -0
  161. package/lib/esm/content-fields/hubtype-fields/keyword.d.ts +9 -0
  162. package/lib/esm/content-fields/hubtype-fields/keyword.js +2 -0
  163. package/lib/esm/content-fields/hubtype-fields/keyword.js.map +1 -0
  164. package/lib/esm/content-fields/hubtype-fields/node-types.d.ts +23 -0
  165. package/lib/esm/content-fields/hubtype-fields/node-types.js +28 -0
  166. package/lib/esm/content-fields/hubtype-fields/node-types.js.map +1 -0
  167. package/lib/esm/content-fields/hubtype-fields/nodes.d.ts +16 -0
  168. package/lib/esm/content-fields/hubtype-fields/nodes.js +2 -0
  169. package/lib/esm/content-fields/hubtype-fields/nodes.js.map +1 -0
  170. package/lib/esm/content-fields/hubtype-fields/payload.d.ts +8 -0
  171. package/lib/esm/content-fields/hubtype-fields/payload.js +2 -0
  172. package/lib/esm/content-fields/hubtype-fields/payload.js.map +1 -0
  173. package/lib/esm/content-fields/hubtype-fields/start.d.ts +7 -0
  174. package/lib/esm/content-fields/hubtype-fields/start.js +2 -0
  175. package/lib/esm/content-fields/hubtype-fields/start.js.map +1 -0
  176. package/lib/esm/content-fields/hubtype-fields/text.d.ts +11 -0
  177. package/lib/esm/content-fields/hubtype-fields/text.js +2 -0
  178. package/lib/esm/content-fields/hubtype-fields/text.js.map +1 -0
  179. package/lib/esm/content-fields/hubtype-fields/url.d.ts +8 -0
  180. package/lib/esm/content-fields/hubtype-fields/url.js +2 -0
  181. package/lib/esm/content-fields/hubtype-fields/url.js.map +1 -0
  182. package/lib/esm/content-fields/hubtype-fields/video.d.ts +8 -0
  183. package/lib/esm/content-fields/hubtype-fields/video.js +2 -0
  184. package/lib/esm/content-fields/hubtype-fields/video.js.map +1 -0
  185. package/lib/esm/content-fields/hubtype-fields/whatsapp-button-list.d.ts +21 -0
  186. package/lib/esm/content-fields/hubtype-fields/whatsapp-button-list.js +2 -0
  187. package/lib/esm/content-fields/hubtype-fields/whatsapp-button-list.js.map +1 -0
  188. package/lib/esm/content-fields/index.d.ts +7 -5
  189. package/lib/esm/content-fields/index.js +6 -4
  190. package/lib/esm/content-fields/index.js.map +1 -1
  191. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.d.ts +10 -0
  192. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.js +28 -0
  193. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.js.map +1 -0
  194. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.d.ts +10 -0
  195. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js +25 -0
  196. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js.map +1 -0
  197. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list.d.ts +12 -0
  198. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js +28 -0
  199. package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js.map +1 -0
  200. package/lib/esm/functions/conditional-provider.d.ts +2 -2
  201. package/lib/esm/functions/conditional-provider.js +2 -2
  202. package/lib/esm/functions/conditional-provider.js.map +1 -1
  203. package/lib/esm/functions/conditional-queue-status.d.ts +7 -2
  204. package/lib/esm/functions/conditional-queue-status.js +11 -1
  205. package/lib/esm/functions/conditional-queue-status.js.map +1 -1
  206. package/lib/esm/handoff.d.ts +2 -2
  207. package/lib/esm/handoff.js +17 -9
  208. package/lib/esm/handoff.js.map +1 -1
  209. package/lib/esm/helpers.d.ts +2 -1
  210. package/lib/esm/helpers.js +3 -11
  211. package/lib/esm/helpers.js.map +1 -1
  212. package/lib/esm/index.d.ts +10 -21
  213. package/lib/esm/index.js +38 -153
  214. package/lib/esm/index.js.map +1 -1
  215. package/lib/esm/types.d.ts +8 -2
  216. package/lib/esm/types.js.map +1 -1
  217. package/package.json +4 -5
  218. package/src/action.tsx +31 -22
  219. package/src/api.ts +162 -0
  220. package/src/content-fields/content-fields-base.ts +7 -7
  221. package/src/content-fields/flow-button.tsx +40 -19
  222. package/src/content-fields/flow-carousel.tsx +10 -18
  223. package/src/content-fields/flow-element.tsx +26 -9
  224. package/src/content-fields/flow-image.tsx +2 -2
  225. package/src/content-fields/flow-text.tsx +15 -12
  226. package/src/content-fields/flow-video.tsx +2 -3
  227. package/src/content-fields/hubtype-fields/button.ts +15 -0
  228. package/src/content-fields/hubtype-fields/carousel.ts +18 -0
  229. package/src/content-fields/hubtype-fields/common.ts +65 -0
  230. package/src/content-fields/hubtype-fields/fallback.ts +10 -0
  231. package/src/content-fields/hubtype-fields/function.ts +33 -0
  232. package/src/content-fields/hubtype-fields/handoff.ts +11 -0
  233. package/src/content-fields/hubtype-fields/image.ts +9 -0
  234. package/src/content-fields/hubtype-fields/index.ts +17 -0
  235. package/src/content-fields/hubtype-fields/intent.ts +11 -0
  236. package/src/content-fields/hubtype-fields/keyword.ts +10 -0
  237. package/src/content-fields/hubtype-fields/node-types.ts +26 -0
  238. package/src/content-fields/hubtype-fields/nodes.ts +32 -0
  239. package/src/content-fields/hubtype-fields/payload.ts +9 -0
  240. package/src/content-fields/hubtype-fields/start.ts +8 -0
  241. package/src/content-fields/hubtype-fields/text.ts +12 -0
  242. package/src/content-fields/hubtype-fields/url.ts +9 -0
  243. package/src/content-fields/hubtype-fields/video.ts +9 -0
  244. package/src/content-fields/hubtype-fields/whatsapp-button-list.ts +25 -0
  245. package/src/content-fields/index.ts +14 -5
  246. package/src/content-fields/whatsapp-button-list/flow-whatsapp-button-list-row.tsx +33 -0
  247. package/src/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.tsx +35 -0
  248. package/src/content-fields/whatsapp-button-list/flow-whatsapp-button-list.tsx +46 -0
  249. package/src/functions/conditional-provider.ts +2 -2
  250. package/src/functions/conditional-queue-status.ts +22 -3
  251. package/src/handoff.ts +27 -14
  252. package/src/helpers.ts +8 -19
  253. package/src/index.ts +55 -197
  254. package/src/types.ts +14 -2
  255. package/lib/cjs/content-fields/types.d.ts +0 -5
  256. package/lib/cjs/content-fields/types.js.map +0 -1
  257. package/lib/cjs/flow-builder-models.d.ts +0 -196
  258. package/lib/cjs/flow-builder-models.js +0 -24
  259. package/lib/cjs/flow-builder-models.js.map +0 -1
  260. package/lib/esm/content-fields/types.d.ts +0 -5
  261. package/lib/esm/content-fields/types.js +0 -2
  262. package/lib/esm/content-fields/types.js.map +0 -1
  263. package/lib/esm/flow-builder-models.d.ts +0 -196
  264. package/lib/esm/flow-builder-models.js +0 -21
  265. package/lib/esm/flow-builder-models.js.map +0 -1
  266. package/src/.DS_Store +0 -0
  267. package/src/content-fields/types.ts +0 -6
  268. package/src/flow-builder-models.ts +0 -249
package/src/action.tsx CHANGED
@@ -2,70 +2,79 @@ import { ActionRequest, Multichannel, RequestContext } from '@botonic/react'
2
2
  import React from 'react'
3
3
 
4
4
  import { FlowContent } from './content-fields'
5
+ import { HtNodeWithContent } from './content-fields/hubtype-fields'
5
6
  import { doHandoff } from './handoff'
6
7
  import { getFlowBuilderPlugin } from './helpers'
7
8
 
8
9
  type FlowBuilderActionProps = {
9
- content?: FlowContent[]
10
+ contents: FlowContent[]
10
11
  isHandoff?: boolean
11
12
  }
12
13
 
13
14
  let alternateFallbackMessage = false
14
- export class FlowBuilderAction extends React.Component {
15
- static contextType: any = RequestContext
15
+ export class FlowBuilderAction extends React.Component<FlowBuilderActionProps> {
16
+ static contextType = RequestContext
16
17
 
17
18
  static async botonicInit(request: ActionRequest): Promise<any> {
18
19
  const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
19
20
  const locale = flowBuilderPlugin.getLocale(request.session)
20
21
  const payload = request.input.payload
21
- let targetContentId: string | undefined = payload
22
+ let targetNode: HtNodeWithContent | string | undefined = payload
23
+
22
24
  if (!payload && request.session.is_first_interaction) {
23
- targetContentId = await flowBuilderPlugin.getStartId()
25
+ targetNode = flowBuilderPlugin.cmsApi.getStartNode()
24
26
  }
25
- if (!payload) {
26
- const intentPayload = await flowBuilderPlugin.getPayloadByIntent(
27
+
28
+ if (!payload && request.input.data) {
29
+ const intentNode = flowBuilderPlugin.cmsApi.getNodeByIntent(
27
30
  request.input,
28
31
  locale
29
32
  )
30
- if (intentPayload) targetContentId = intentPayload
31
- const keywordPayload = await flowBuilderPlugin.getPayloadByKeyword(
32
- request.input,
33
+ const keywordNode = flowBuilderPlugin.cmsApi.getNodeByKeyword(
34
+ request.input.data,
33
35
  locale
34
36
  )
35
- if (keywordPayload) targetContentId = keywordPayload
37
+ if (intentNode) {
38
+ targetNode = intentNode
39
+ } else if (keywordNode) {
40
+ targetNode = keywordNode
41
+ }
36
42
  }
37
- if (!targetContentId) {
38
- targetContentId = await flowBuilderPlugin.getFallbackId(
43
+
44
+ if (!targetNode) {
45
+ targetNode = flowBuilderPlugin.cmsApi.getFallbackNode(
39
46
  alternateFallbackMessage
40
47
  )
41
48
  alternateFallbackMessage = !alternateFallbackMessage
42
49
  }
43
50
 
44
- const { contents, handoffNode } = await flowBuilderPlugin.getContents(
45
- targetContentId,
51
+ const { contents, handoffNode } = await flowBuilderPlugin.getContent(
52
+ targetNode,
46
53
  locale
47
54
  )
48
55
 
56
+ if (flowBuilderPlugin.trackEvent) {
57
+ // TODO: track all targets nodes?
58
+ await flowBuilderPlugin.trackEvent(request, contents[0].code)
59
+ }
60
+
49
61
  if (handoffNode) await doHandoff(request, locale, handoffNode)
50
62
 
51
63
  return { contents, handoffNode }
52
64
  }
53
65
 
54
66
  render(): JSX.Element | JSX.Element[] {
55
- // @ts-ignore
56
- const { contents, handoffNode } = this.props
57
- return contents!.map(content => content.toBotonic(content.id))
67
+ const { contents } = this.props
68
+ return contents.map(content => content.toBotonic(content.id))
58
69
  }
59
70
  }
60
71
 
61
72
  export class FlowBuilderMultichannelAction extends FlowBuilderAction {
62
73
  render(): JSX.Element | JSX.Element[] {
63
- // @ts-ignore
64
- const { contents, handoffNode } = this.props
74
+ const { contents } = this.props
65
75
  return (
66
- //@ts-ignore
67
76
  <Multichannel text={{ buttonsAsText: false }}>
68
- {contents!.map(content => content.toBotonic(content.id))}
77
+ {contents.map(content => content.toBotonic(content.id))}
69
78
  </Multichannel>
70
79
  )
71
80
  }
package/src/api.ts ADDED
@@ -0,0 +1,162 @@
1
+ import { Input } from '@botonic/core'
2
+ import axios from 'axios/index'
3
+
4
+ import {
5
+ HtFallbackNode,
6
+ HtFlowBuilderData,
7
+ HtIntentNode,
8
+ HtKeywordNode,
9
+ HtNodeComponent,
10
+ HtNodeStartType,
11
+ HtNodeWithContent,
12
+ HtNodeWithContentType,
13
+ HtStartNode,
14
+ } from './content-fields/hubtype-fields'
15
+ import { FlowBuilderApiOptions } from './types'
16
+
17
+ export class FlowBuilderApi {
18
+ private readonly url: string
19
+ public flow: HtFlowBuilderData
20
+
21
+ constructor(options: FlowBuilderApiOptions) {
22
+ this.url = options.url
23
+ if (options.flow) {
24
+ this.flow = options.flow
25
+ }
26
+ }
27
+
28
+ async init(token: string) {
29
+ const { data } = await axios.get(this.url, {
30
+ headers: { Authorization: `Bearer ${token}` },
31
+ })
32
+ this.flow = data
33
+ }
34
+
35
+ getNode<T extends HtNodeComponent>(id: string): T {
36
+ const node = this.flow.nodes.find(node => node.id === id)
37
+ if (!node) throw Error(`Node with id: '${id}' not found`)
38
+ return node as T
39
+ }
40
+
41
+ getNodeByCode(code: string): HtNodeComponent {
42
+ const content = this.flow.nodes.find(node =>
43
+ 'code' in node ? node.code === code : false
44
+ )
45
+ if (!content) throw Error(`Node with code: '${code}' not found`)
46
+ return content
47
+ }
48
+
49
+ getStartNode(): HtNodeWithContent {
50
+ const startUpNode = this.flow.nodes.find(
51
+ node => node.type === HtNodeStartType.STARTUP
52
+ ) as HtStartNode | undefined
53
+ if (!startUpNode) throw new Error('Start-up id must be defined')
54
+ return this.getNode(startUpNode.target.id)
55
+ }
56
+
57
+ getFallbackNode(alternate: boolean): HtNodeWithContent {
58
+ const fallbackNode = this.flow.nodes.find(
59
+ node => node.type === HtNodeWithContentType.FALLBACK
60
+ ) as HtFallbackNode | undefined
61
+ if (!fallbackNode) {
62
+ throw new Error('Fallback node must be defined')
63
+ }
64
+ const fallbackFirstMessage = fallbackNode.content.first_message
65
+ if (!fallbackFirstMessage) {
66
+ throw new Error('Fallback 1st message must be defined')
67
+ }
68
+ const fallbackSecondMessage = fallbackNode.content.second_message
69
+ if (!fallbackSecondMessage) {
70
+ return this.getNode(fallbackFirstMessage.id)
71
+ }
72
+ return alternate
73
+ ? this.getNode(fallbackFirstMessage.id)
74
+ : this.getNode(fallbackSecondMessage.id)
75
+ }
76
+
77
+ getNodeByIntent(input: Input, locale: string): HtNodeWithContent | undefined {
78
+ try {
79
+ const intents = this.flow.nodes.filter(
80
+ node => node.type === HtNodeWithContentType.INTENT
81
+ ) as HtIntentNode[]
82
+ const inputIntent = input.intent
83
+ const inputConfidence = input.confidence
84
+ if (inputIntent) {
85
+ const matchedIntentNode = intents.find(
86
+ node =>
87
+ inputIntent &&
88
+ this.hasIntent(node, inputIntent, locale) &&
89
+ inputConfidence &&
90
+ this.hasMetConfidenceThreshold(node, inputConfidence)
91
+ )
92
+ return (
93
+ matchedIntentNode?.target &&
94
+ this.getNode<HtNodeWithContent>(matchedIntentNode?.target.id)
95
+ )
96
+ }
97
+ } catch (error) {
98
+ console.error(`Error getting node by intent '${input.intent}': `, error)
99
+ }
100
+
101
+ return undefined
102
+ }
103
+
104
+ private hasIntent(
105
+ node: HtIntentNode,
106
+ intent: string,
107
+ locale: string
108
+ ): boolean {
109
+ return node.content.intents.some(
110
+ i => i.locale === locale && i.values.includes(intent)
111
+ )
112
+ }
113
+
114
+ private hasMetConfidenceThreshold(
115
+ node: HtIntentNode,
116
+ predictedConfidence: number
117
+ ): boolean {
118
+ const nodeConfidence = node.content.confidence / 100
119
+ return predictedConfidence >= nodeConfidence
120
+ }
121
+
122
+ getNodeByKeyword(
123
+ userInput: string,
124
+ locale: string
125
+ ): HtNodeWithContent | undefined {
126
+ try {
127
+ const keywordNodes = this.flow.nodes.filter(
128
+ node => node.type == HtNodeWithContentType.KEYWORD
129
+ ) as HtKeywordNode[]
130
+ const matchedKeywordNodes = keywordNodes.filter(node =>
131
+ this.matchKeywords(node, userInput, locale)
132
+ )
133
+ if (matchedKeywordNodes.length > 0 && matchedKeywordNodes[0].target) {
134
+ return this.getNode<HtNodeWithContent>(matchedKeywordNodes[0].target.id)
135
+ }
136
+ } catch (error) {
137
+ console.error(`Error getting node by keyword '${userInput}': `, error)
138
+ }
139
+
140
+ return undefined
141
+ }
142
+
143
+ private matchKeywords(
144
+ node: HtKeywordNode,
145
+ input: string,
146
+ locale: string
147
+ ): boolean {
148
+ const result = node.content.keywords.find(
149
+ i => i.locale === locale && this.containsAnyKeywords(input, i.values)
150
+ )
151
+ return Boolean(result)
152
+ }
153
+
154
+ private containsAnyKeywords(input: string, keywords: string[]): boolean {
155
+ for (let i = 0; i < keywords.length; i++) {
156
+ if (input.includes(keywords[i])) {
157
+ return true
158
+ }
159
+ }
160
+ return false
161
+ }
162
+ }
@@ -1,23 +1,23 @@
1
1
  import {
2
- MediaFileLocale,
3
- TextLocale,
4
- VideoLocale,
5
- } from '../flow-builder-models'
2
+ HtMediaFileLocale,
3
+ HtTextLocale,
4
+ HtVideoLocale,
5
+ } from './hubtype-fields'
6
6
 
7
7
  export abstract class ContentFieldsBase {
8
8
  constructor(public readonly id: string) {}
9
9
 
10
- static getTextByLocale(locale: string, text: TextLocale[]): string {
10
+ static getTextByLocale(locale: string, text: HtTextLocale[]): string {
11
11
  const result = text.find(t => t.locale === locale)
12
12
  return result?.message ?? ''
13
13
  }
14
14
 
15
- static getImageByLocale(locale: string, image: MediaFileLocale[]): string {
15
+ static getImageByLocale(locale: string, image: HtMediaFileLocale[]): string {
16
16
  const result = image.find(i => i.locale === locale)
17
17
  return result?.file ?? ''
18
18
  }
19
19
 
20
- static getVideoByLocale(locale: string, video: VideoLocale[]): string {
20
+ static getVideoByLocale(locale: string, video: HtVideoLocale[]): string {
21
21
  const result = video.find(v => v.locale === locale)
22
22
  return result?.url ?? ''
23
23
  }
@@ -1,42 +1,63 @@
1
1
  import { Button, Reply } from '@botonic/react'
2
2
  import React from 'react'
3
3
 
4
- import { Button as FbButton, ButtonStyle } from '../flow-builder-models'
4
+ import { FlowBuilderApi } from '../api'
5
5
  import { ContentFieldsBase } from './content-fields-base'
6
+ import {
7
+ HtButton,
8
+ HtButtonStyle,
9
+ HtPayloadNode,
10
+ HtUrlNode,
11
+ } from './hubtype-fields'
6
12
 
7
13
  export class FlowButton extends ContentFieldsBase {
8
14
  public text = ''
9
15
  public url?: string
10
16
  public payload?: string
11
17
 
12
- static fromHubtypeCMS(component: FbButton, locale: string): FlowButton {
13
- const newButton = new FlowButton(component.id)
14
- newButton.text = FlowButton.getTextByLocale(locale, component.text)
15
- newButton.payload = component.target
16
- ? component.target.id
17
- : component.payload?.find(payload => payload.locale === locale)?.id
18
- if (component.url) {
19
- const urlButton = (component.url as any).find(
20
- url => url.locale === locale
21
- )
22
- if (urlButton) newButton.url = urlButton.content.url
18
+ static fromHubtypeCMS(
19
+ cmsButton: HtButton,
20
+ locale: string,
21
+ cmsApi: FlowBuilderApi
22
+ ): FlowButton {
23
+ const payloadId = this.getPayloadId(cmsButton, locale)
24
+ const urlId = this.getUrlId(cmsButton, locale)
25
+
26
+ const newButton = new FlowButton(cmsButton.id)
27
+ newButton.text = this.getTextByLocale(locale, cmsButton.text)
28
+ if (cmsButton.target) {
29
+ newButton.payload = cmsButton.target.id
30
+ }
31
+ if (cmsButton.payload && payloadId) {
32
+ const payloadNode = cmsApi.getNode(payloadId) as HtPayloadNode
33
+ newButton.payload = payloadNode.content.payload
23
34
  }
35
+ if (cmsButton.url && urlId) {
36
+ const payloadNode = cmsApi.getNode(urlId) as HtUrlNode
37
+ newButton.url = payloadNode.content.url
38
+ }
39
+
24
40
  return newButton
25
41
  }
26
42
 
27
- renderButton(id: string, buttonStyle: ButtonStyle): JSX.Element {
28
- if (buttonStyle === ButtonStyle.QUICK_REPLY) {
43
+ static getPayloadId(cmsButton, locale): string | undefined {
44
+ return cmsButton.payload.find(payload => payload.locale === locale)?.id
45
+ }
46
+
47
+ static getUrlId(cmsButton, locale): string | undefined {
48
+ return cmsButton.url.find(url => url.locale === locale)?.id
49
+ }
50
+
51
+ renderButton(buttonStyle?: HtButtonStyle): JSX.Element {
52
+ if (buttonStyle === HtButtonStyle.QUICK_REPLY) {
29
53
  return (
30
- <Reply key={id} payload={this.payload}>
54
+ <Reply key={this.id} payload={this.payload}>
31
55
  {this.text}
32
56
  </Reply>
33
57
  )
34
58
  }
35
- let props = {}
36
- if (this.url) props = { url: this.url }
37
59
  return (
38
- // @ts-ignore
39
- <Button key={id} payload={this.payload} {...props}>
60
+ <Button key={this.id} payload={this.payload} url={this.url}>
40
61
  {this.text}
41
62
  </Button>
42
63
  )
@@ -1,19 +1,24 @@
1
- import { Button, Carousel, Element, Pic, Subtitle, Title } from '@botonic/react'
1
+ import { Carousel } from '@botonic/react'
2
2
  import React from 'react'
3
3
 
4
- import { CarouselNode } from '../flow-builder-models'
4
+ import { FlowBuilderApi } from '../api'
5
5
  import { ContentFieldsBase } from './content-fields-base'
6
6
  import { FlowElement } from './flow-element'
7
+ import { HtCarouselNode } from './hubtype-fields'
7
8
 
8
9
  export class FlowCarousel extends ContentFieldsBase {
9
10
  public code = ''
10
11
  public elements: FlowElement[] = []
11
12
 
12
- static fromHubtypeCMS(component: CarouselNode, locale: string): FlowCarousel {
13
+ static fromHubtypeCMS(
14
+ component: HtCarouselNode,
15
+ locale: string,
16
+ cmsApi: FlowBuilderApi
17
+ ): FlowCarousel {
13
18
  const newCarousel = new FlowCarousel(component.id)
14
19
  newCarousel.code = component.code
15
20
  newCarousel.elements = component.content.elements.map(element =>
16
- FlowElement.fromHubtypeCMS(element, locale)
21
+ FlowElement.fromHubtypeCMS(element, locale, cmsApi)
17
22
  )
18
23
  return newCarousel
19
24
  }
@@ -21,20 +26,7 @@ export class FlowCarousel extends ContentFieldsBase {
21
26
  toBotonic(id: string): JSX.Element {
22
27
  return (
23
28
  <Carousel key={id}>
24
- {this.elements.map(element => (
25
- <Element key={`${id}-${element.id}`}>
26
- <Pic src={element.image} />
27
- <Title style=''>{element.title}</Title>
28
- <Subtitle style=''>{element.subtitle}</Subtitle>
29
- {/* @ts-ignore */}
30
- <Button
31
- payload={element.buttons?.payload}
32
- url={element.buttons?.url}
33
- >
34
- {element.buttons?.text}
35
- </Button>
36
- </Element>
37
- ))}
29
+ {this.elements.map(element => element.toBotonic(id))}
38
30
  </Carousel>
39
31
  )
40
32
  }
@@ -1,26 +1,43 @@
1
- import { CarouselElementNode } from '../flow-builder-models'
1
+ import { Element, Pic, Subtitle, Title } from '@botonic/react'
2
+ import React from 'react'
3
+
4
+ import { FlowBuilderApi } from '../api'
2
5
  import { ContentFieldsBase } from './content-fields-base'
3
6
  import { FlowButton } from './flow-button'
7
+ import { HtCarouselElement } from './hubtype-fields'
4
8
 
5
9
  export class FlowElement extends ContentFieldsBase {
6
10
  public title = ''
7
11
  public subtitle = ''
8
- public buttons: FlowButton | undefined
12
+ public button: FlowButton | undefined
9
13
  public image = ''
10
14
  public hidden = false
11
15
 
12
16
  static fromHubtypeCMS(
13
- component: CarouselElementNode,
14
- locale: string
17
+ component: HtCarouselElement,
18
+ locale: string,
19
+ cmsApi: FlowBuilderApi
15
20
  ): FlowElement {
16
21
  const newElement = new FlowElement(component.id)
17
- newElement.title = FlowElement.getTextByLocale(locale, component.title)
18
- newElement.subtitle = FlowElement.getTextByLocale(
22
+ newElement.title = this.getTextByLocale(locale, component.title)
23
+ newElement.subtitle = this.getTextByLocale(locale, component.subtitle)
24
+ newElement.image = this.getImageByLocale(locale, component.image)
25
+ newElement.button = FlowButton.fromHubtypeCMS(
26
+ component.button,
19
27
  locale,
20
- component.subtitle
28
+ cmsApi
21
29
  )
22
- newElement.image = FlowElement.getImageByLocale(locale, component.image)
23
- newElement.buttons = FlowButton.fromHubtypeCMS(component.button, locale)
24
30
  return newElement
25
31
  }
32
+
33
+ toBotonic(parentId: string): JSX.Element {
34
+ return (
35
+ <Element key={`${parentId}-${this.id}`}>
36
+ <Pic src={this.image} />
37
+ <Title>{this.title}</Title>
38
+ <Subtitle>{this.subtitle}</Subtitle>
39
+ {this.button?.renderButton()}
40
+ </Element>
41
+ )
42
+ }
26
43
  }
@@ -1,14 +1,14 @@
1
1
  import { Image } from '@botonic/react'
2
2
  import React from 'react'
3
3
 
4
- import { ImageNode } from '../flow-builder-models'
5
4
  import { ContentFieldsBase } from './content-fields-base'
5
+ import { HtImageNode } from './hubtype-fields'
6
6
 
7
7
  export class FlowImage extends ContentFieldsBase {
8
8
  public src = ''
9
9
  public code = ''
10
10
 
11
- static fromHubtypeCMS(component: ImageNode, locale: string): FlowImage {
11
+ static fromHubtypeCMS(component: HtImageNode, locale: string): FlowImage {
12
12
  const newImage = new FlowImage(component.id)
13
13
  newImage.code = component.code
14
14
  newImage.src = this.getImageByLocale(locale, component.content.image)
@@ -1,23 +1,28 @@
1
1
  import { Text } from '@botonic/react'
2
2
  import React from 'react'
3
3
 
4
- import { ButtonStyle, TextNode } from '../flow-builder-models'
4
+ import { FlowBuilderApi } from '../api'
5
5
  import { ContentFieldsBase } from './content-fields-base'
6
6
  import { FlowButton } from './flow-button'
7
+ import { HtButtonStyle, HtTextNode } from './hubtype-fields'
7
8
 
8
9
  export class FlowText extends ContentFieldsBase {
9
10
  public text = ''
10
11
  public code = ''
11
12
  public buttons: FlowButton[] = []
12
- public buttonStyle = ButtonStyle.BUTTON
13
+ public buttonStyle = HtButtonStyle.BUTTON
13
14
 
14
- static fromHubtypeCMS(component: TextNode, 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)
15
+ static fromHubtypeCMS(
16
+ cmsText: HtTextNode,
17
+ locale: string,
18
+ cmsApi: FlowBuilderApi
19
+ ): FlowText {
20
+ const newText = new FlowText(cmsText.id)
21
+ newText.code = cmsText.code
22
+ newText.buttonStyle = cmsText.content.buttons_style || HtButtonStyle.BUTTON
23
+ newText.text = this.getTextByLocale(locale, cmsText.content.text)
24
+ newText.buttons = cmsText.content.buttons.map(button =>
25
+ FlowButton.fromHubtypeCMS(button, locale, cmsApi)
21
26
  )
22
27
  return newText
23
28
  }
@@ -26,9 +31,7 @@ export class FlowText extends ContentFieldsBase {
26
31
  return (
27
32
  <Text key={id}>
28
33
  {this.text}
29
- {this.buttons.map(button =>
30
- button.renderButton(button.id, this.buttonStyle)
31
- )}
34
+ {this.buttons.map(button => button.renderButton(this.buttonStyle))}
32
35
  </Text>
33
36
  )
34
37
  }
@@ -1,14 +1,14 @@
1
1
  import { Video } from '@botonic/react'
2
2
  import React from 'react'
3
3
 
4
- import { VideoNode } from '../flow-builder-models'
5
4
  import { ContentFieldsBase } from './content-fields-base'
5
+ import { HtVideoNode } from './hubtype-fields'
6
6
 
7
7
  export class FlowVideo extends ContentFieldsBase {
8
8
  public src = ''
9
9
  public code = ''
10
10
 
11
- static fromHubtypeCMS(component: VideoNode, locale: string): FlowVideo {
11
+ static fromHubtypeCMS(component: HtVideoNode, locale: string): FlowVideo {
12
12
  const newVideo = new FlowVideo(component.id)
13
13
  newVideo.code = component.code
14
14
  newVideo.src = this.getVideoByLocale(locale, component.content.video)
@@ -16,7 +16,6 @@ export class FlowVideo extends ContentFieldsBase {
16
16
  }
17
17
 
18
18
  toBotonic(id: string): JSX.Element {
19
- // @ts-ignore
20
19
  return <Video key={id} src={this.src} />
21
20
  }
22
21
  }
@@ -0,0 +1,15 @@
1
+ import {
2
+ HtNodeLink,
3
+ HtPayloadLocale,
4
+ HtTextLocale,
5
+ HtUrlLocale,
6
+ } from './common'
7
+
8
+ export interface HtButton {
9
+ id: string
10
+ text: HtTextLocale[]
11
+ url: HtUrlLocale[]
12
+ payload: HtPayloadLocale[]
13
+ target?: HtNodeLink
14
+ hidden: string[]
15
+ }
@@ -0,0 +1,18 @@
1
+ import { HtButton } from './button'
2
+ import { HtBaseNode, HtMediaFileLocale, HtTextLocale } from './common'
3
+ import { HtNodeWithContentType } from './node-types'
4
+
5
+ export interface HtCarouselElement {
6
+ id: string
7
+ title: HtTextLocale[]
8
+ subtitle: HtTextLocale[]
9
+ image: HtMediaFileLocale[]
10
+ button: HtButton
11
+ }
12
+
13
+ export interface HtCarouselNode extends HtBaseNode {
14
+ type: HtNodeWithContentType.CAROUSEL
15
+ content: {
16
+ elements: HtCarouselElement[]
17
+ }
18
+ }
@@ -0,0 +1,65 @@
1
+ import { HtNodeWithContentType, HtNodeWithoutContentType } from './node-types'
2
+ import { HtNodeComponent } from './nodes'
3
+
4
+ export interface HtFlowBuilderData {
5
+ version: string
6
+ name: string
7
+ locales: string[]
8
+ start_node_id?: string
9
+ ai_model_id?: string
10
+ nodes: HtNodeComponent[]
11
+ }
12
+
13
+ export interface HtNodeLink {
14
+ id: string
15
+ type: HtNodeWithContentType | HtNodeWithoutContentType
16
+ }
17
+
18
+ export interface HtBaseNode {
19
+ id: string
20
+ code: string
21
+ meta: {
22
+ x: number
23
+ y: number
24
+ }
25
+ follow_up?: HtNodeLink
26
+ target?: HtNodeLink
27
+ }
28
+
29
+ export interface HtTextLocale {
30
+ message: string
31
+ locale: string
32
+ }
33
+
34
+ export interface HtMediaFileLocale {
35
+ id: string
36
+ file: string
37
+ locale: string
38
+ }
39
+
40
+ export interface HtVideoLocale {
41
+ url: string
42
+ is_embedded: boolean
43
+ locale: string
44
+ }
45
+
46
+ export interface HtQueueLocale {
47
+ id: string
48
+ name: string
49
+ locale: string
50
+ }
51
+
52
+ export interface HtInputLocale {
53
+ values: string[]
54
+ locale: string
55
+ }
56
+
57
+ export interface HtUrlLocale {
58
+ id: string
59
+ locale: string
60
+ }
61
+
62
+ export interface HtPayloadLocale {
63
+ id: string
64
+ locale: string
65
+ }