@botonic/plugin-flow-builder 0.42.4 → 0.43.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.
Files changed (85) hide show
  1. package/lib/cjs/action/payload.js +22 -2
  2. package/lib/cjs/action/payload.js.map +1 -1
  3. package/lib/cjs/api.d.ts +2 -0
  4. package/lib/cjs/api.js +11 -1
  5. package/lib/cjs/api.js.map +1 -1
  6. package/lib/cjs/constants.d.ts +2 -1
  7. package/lib/cjs/constants.js +3 -2
  8. package/lib/cjs/constants.js.map +1 -1
  9. package/lib/cjs/content-fields/content-fields-base.d.ts +2 -0
  10. package/lib/cjs/content-fields/content-fields-base.js +21 -0
  11. package/lib/cjs/content-fields/content-fields-base.js.map +1 -1
  12. package/lib/cjs/content-fields/flow-button.js +6 -2
  13. package/lib/cjs/content-fields/flow-button.js.map +1 -1
  14. package/lib/cjs/content-fields/flow-text.d.ts +0 -2
  15. package/lib/cjs/content-fields/flow-text.js +1 -21
  16. package/lib/cjs/content-fields/flow-text.js.map +1 -1
  17. package/lib/cjs/content-fields/flow-whatsapp-template.d.ts +28 -0
  18. package/lib/cjs/content-fields/flow-whatsapp-template.js +169 -0
  19. package/lib/cjs/content-fields/flow-whatsapp-template.js.map +1 -0
  20. package/lib/cjs/content-fields/hubtype-fields/common.d.ts +6 -0
  21. package/lib/cjs/content-fields/hubtype-fields/index.d.ts +1 -0
  22. package/lib/cjs/content-fields/hubtype-fields/index.js +1 -0
  23. package/lib/cjs/content-fields/hubtype-fields/index.js.map +1 -1
  24. package/lib/cjs/content-fields/hubtype-fields/node-types.d.ts +1 -0
  25. package/lib/cjs/content-fields/hubtype-fields/node-types.js +1 -0
  26. package/lib/cjs/content-fields/hubtype-fields/node-types.js.map +1 -1
  27. package/lib/cjs/content-fields/hubtype-fields/nodes.d.ts +2 -1
  28. package/lib/cjs/content-fields/hubtype-fields/whatsapp-template.d.ts +66 -0
  29. package/lib/cjs/content-fields/hubtype-fields/whatsapp-template.js +3 -0
  30. package/lib/cjs/content-fields/hubtype-fields/whatsapp-template.js.map +1 -0
  31. package/lib/cjs/content-fields/index.d.ts +3 -2
  32. package/lib/cjs/content-fields/index.js +3 -1
  33. package/lib/cjs/content-fields/index.js.map +1 -1
  34. package/lib/cjs/flow-factory.js +2 -0
  35. package/lib/cjs/flow-factory.js.map +1 -1
  36. package/lib/esm/action/payload.js +23 -3
  37. package/lib/esm/action/payload.js.map +1 -1
  38. package/lib/esm/api.d.ts +2 -0
  39. package/lib/esm/api.js +11 -1
  40. package/lib/esm/api.js.map +1 -1
  41. package/lib/esm/constants.d.ts +2 -1
  42. package/lib/esm/constants.js +2 -1
  43. package/lib/esm/constants.js.map +1 -1
  44. package/lib/esm/content-fields/content-fields-base.d.ts +2 -0
  45. package/lib/esm/content-fields/content-fields-base.js +21 -0
  46. package/lib/esm/content-fields/content-fields-base.js.map +1 -1
  47. package/lib/esm/content-fields/flow-button.js +6 -2
  48. package/lib/esm/content-fields/flow-button.js.map +1 -1
  49. package/lib/esm/content-fields/flow-text.d.ts +0 -2
  50. package/lib/esm/content-fields/flow-text.js +2 -22
  51. package/lib/esm/content-fields/flow-text.js.map +1 -1
  52. package/lib/esm/content-fields/flow-whatsapp-template.d.ts +28 -0
  53. package/lib/esm/content-fields/flow-whatsapp-template.js +165 -0
  54. package/lib/esm/content-fields/flow-whatsapp-template.js.map +1 -0
  55. package/lib/esm/content-fields/hubtype-fields/common.d.ts +6 -0
  56. package/lib/esm/content-fields/hubtype-fields/index.d.ts +1 -0
  57. package/lib/esm/content-fields/hubtype-fields/index.js +1 -0
  58. package/lib/esm/content-fields/hubtype-fields/index.js.map +1 -1
  59. package/lib/esm/content-fields/hubtype-fields/node-types.d.ts +1 -0
  60. package/lib/esm/content-fields/hubtype-fields/node-types.js +1 -0
  61. package/lib/esm/content-fields/hubtype-fields/node-types.js.map +1 -1
  62. package/lib/esm/content-fields/hubtype-fields/nodes.d.ts +2 -1
  63. package/lib/esm/content-fields/hubtype-fields/whatsapp-template.d.ts +66 -0
  64. package/lib/esm/content-fields/hubtype-fields/whatsapp-template.js +2 -0
  65. package/lib/esm/content-fields/hubtype-fields/whatsapp-template.js.map +1 -0
  66. package/lib/esm/content-fields/index.d.ts +3 -2
  67. package/lib/esm/content-fields/index.js +2 -1
  68. package/lib/esm/content-fields/index.js.map +1 -1
  69. package/lib/esm/flow-factory.js +3 -1
  70. package/lib/esm/flow-factory.js.map +1 -1
  71. package/package.json +3 -3
  72. package/src/action/payload.ts +32 -1
  73. package/src/api.ts +14 -1
  74. package/src/constants.ts +2 -1
  75. package/src/content-fields/content-fields-base.ts +31 -0
  76. package/src/content-fields/flow-button.tsx +5 -2
  77. package/src/content-fields/flow-text.tsx +2 -28
  78. package/src/content-fields/flow-whatsapp-template.tsx +281 -0
  79. package/src/content-fields/hubtype-fields/common.ts +7 -0
  80. package/src/content-fields/hubtype-fields/index.ts +1 -0
  81. package/src/content-fields/hubtype-fields/node-types.ts +1 -0
  82. package/src/content-fields/hubtype-fields/nodes.ts +2 -0
  83. package/src/content-fields/hubtype-fields/whatsapp-template.ts +84 -0
  84. package/src/content-fields/index.ts +3 -0
  85. package/src/flow-factory.ts +4 -0
@@ -0,0 +1,281 @@
1
+ import { isWhatsapp } from '@botonic/core'
2
+ import {
3
+ ActionRequest,
4
+ Text,
5
+ WhatsappTemplate,
6
+ WhatsappTemplateButton,
7
+ WhatsAppTemplateButtonSubType,
8
+ WhatsappTemplateComponentBody,
9
+ WhatsappTemplateComponentButtons,
10
+ WhatsappTemplateComponentHeader,
11
+ WhatsAppTemplateComponentType,
12
+ WhatsAppTemplateParameterType,
13
+ WhatsappTemplateQuickReplyButton,
14
+ WhatsappTemplateUrlButton,
15
+ WhatsappTemplateVoiceCallButton,
16
+ } from '@botonic/react'
17
+ import React from 'react'
18
+
19
+ import { getFlowBuilderPlugin } from '../helpers'
20
+ import { trackOneContent } from '../tracking'
21
+ import { ContentFieldsBase } from './content-fields-base'
22
+ import {
23
+ HtButton,
24
+ HtMediaFileLocale,
25
+ HtWhatsAppTemplate,
26
+ HtWhatsAppTemplateButtonsComponent,
27
+ HtWhatsAppTemplateHeaderComponent,
28
+ HtWhatsappTemplateNode,
29
+ } from './hubtype-fields'
30
+
31
+ interface HeaderVariables {
32
+ type: WhatsAppTemplateParameterType
33
+ text?: Record<string, string>
34
+ media?: HtMediaFileLocale[]
35
+ }
36
+
37
+ export class FlowWhatsappTemplate extends ContentFieldsBase {
38
+ public htWhatsappTemplate: HtWhatsAppTemplate
39
+ public variableValues: Record<string, string> = {}
40
+ public headerVariables?: HeaderVariables
41
+ public buttons?: HtButton[]
42
+ public urlVariableValues?: Record<string, string>
43
+
44
+ static fromHubtypeCMS(
45
+ component: HtWhatsappTemplateNode
46
+ ): FlowWhatsappTemplate {
47
+ const whatsappTemplate = new FlowWhatsappTemplate(component.id)
48
+ whatsappTemplate.code = component.code
49
+ whatsappTemplate.htWhatsappTemplate = component.content.template
50
+ whatsappTemplate.headerVariables = component.content.header_variables
51
+ whatsappTemplate.variableValues = component.content.variable_values
52
+ whatsappTemplate.buttons = component.content.buttons
53
+ whatsappTemplate.urlVariableValues = component.content.url_variable_values
54
+
55
+ whatsappTemplate.followUp = component.follow_up
56
+
57
+ return whatsappTemplate
58
+ }
59
+
60
+ private getHeaderComponent(
61
+ whatsappTemplate: HtWhatsAppTemplate,
62
+ headerVariables: HeaderVariables,
63
+ locale: string,
64
+ request: ActionRequest
65
+ ): WhatsappTemplateComponentHeader | undefined {
66
+ const headerComponent = whatsappTemplate.components.find(
67
+ component => component.type === WhatsAppTemplateComponentType.HEADER
68
+ ) as HtWhatsAppTemplateHeaderComponent | undefined
69
+
70
+ if (
71
+ headerComponent &&
72
+ headerComponent.format === WhatsAppTemplateParameterType.TEXT
73
+ ) {
74
+ return this.createHeaderTextComponent(headerVariables, request)
75
+ }
76
+
77
+ if (
78
+ headerComponent &&
79
+ headerComponent.format === WhatsAppTemplateParameterType.IMAGE
80
+ ) {
81
+ return this.createHeaderImageComponent(headerVariables, locale)
82
+ }
83
+
84
+ return undefined
85
+ }
86
+
87
+ private createHeaderTextComponent(
88
+ headerVariables: HeaderVariables,
89
+ request: ActionRequest
90
+ ): WhatsappTemplateComponentHeader {
91
+ return {
92
+ type: WhatsAppTemplateComponentType.HEADER,
93
+ parameters: Object.values(headerVariables.text || {}).map(value => {
94
+ const valueVariable = this.replaceVariables(value, request)
95
+ return {
96
+ type: WhatsAppTemplateParameterType.TEXT,
97
+ text: valueVariable,
98
+ }
99
+ }),
100
+ }
101
+ }
102
+
103
+ private createHeaderImageComponent(
104
+ headerVariables: HeaderVariables,
105
+ locale: string
106
+ ): WhatsappTemplateComponentHeader {
107
+ return {
108
+ type: WhatsAppTemplateComponentType.HEADER,
109
+ parameters: [
110
+ {
111
+ type: WhatsAppTemplateParameterType.IMAGE,
112
+ image: {
113
+ link:
114
+ headerVariables.media?.find(m => m.locale === locale)?.file || '',
115
+ },
116
+ },
117
+ ],
118
+ }
119
+ }
120
+
121
+ // TODO: To use named variables (contact_info_fields) we need to take it from request.session.user.contact_info, this only be able in toBotonic method
122
+ private getBodyComponent(
123
+ variableValues: Record<string, string>,
124
+ request: ActionRequest
125
+ ): WhatsappTemplateComponentBody {
126
+ return {
127
+ type: WhatsAppTemplateComponentType.BODY,
128
+ parameters: Object.entries(variableValues).map(([key, value]) => {
129
+ const valueVariable = this.replaceVariables(value, request)
130
+ return {
131
+ type: WhatsAppTemplateParameterType.TEXT,
132
+ parameter_name: key,
133
+ text: valueVariable,
134
+ }
135
+ }),
136
+ }
137
+ }
138
+
139
+ private getButtons(
140
+ whatsappTemplate: HtWhatsAppTemplate,
141
+ buttonNodes: HtButton[],
142
+ urlVariableValues: Record<string, string>,
143
+ request: ActionRequest
144
+ ): WhatsappTemplateComponentButtons | undefined {
145
+ const htWhatsappTemplateButtons = whatsappTemplate.components.find(
146
+ component => component.type === WhatsAppTemplateComponentType.BUTTONS
147
+ ) as HtWhatsAppTemplateButtonsComponent | undefined
148
+
149
+ if (htWhatsappTemplateButtons) {
150
+ const buttons = htWhatsappTemplateButtons.buttons
151
+ .map((button, index) => {
152
+ if (button.type === WhatsAppTemplateButtonSubType.URL) {
153
+ const urlParam: string | undefined =
154
+ urlVariableValues?.[String(index)]
155
+ if (!urlParam) {
156
+ return null
157
+ }
158
+ return this.createUrlButtonComponent(index, urlParam, request)
159
+ }
160
+
161
+ if (button.type === WhatsAppTemplateButtonSubType.QUICK_REPLY) {
162
+ const payload = buttonNodes[index].target?.id || ''
163
+ return this.createQuickReplyButtonComponent(index, payload)
164
+ }
165
+
166
+ return this.createVoiceCallButtonComponent(index)
167
+ })
168
+ .filter(button => button !== null)
169
+
170
+ return {
171
+ type: WhatsAppTemplateComponentType.BUTTONS,
172
+ buttons: buttons as WhatsappTemplateButton[],
173
+ }
174
+ }
175
+
176
+ return undefined
177
+ }
178
+
179
+ private createUrlButtonComponent(
180
+ index: number,
181
+ urlParam: string,
182
+ request: ActionRequest
183
+ ): WhatsappTemplateUrlButton {
184
+ const variableUrlParam = this.replaceVariables(urlParam, request)
185
+ return {
186
+ type: WhatsAppTemplateComponentType.BUTTON,
187
+ sub_type: WhatsAppTemplateButtonSubType.URL,
188
+ index: index,
189
+ parameters: urlParam
190
+ ? [
191
+ {
192
+ type: WhatsAppTemplateParameterType.TEXT,
193
+ text: variableUrlParam,
194
+ },
195
+ ]
196
+ : [],
197
+ }
198
+ }
199
+
200
+ private createQuickReplyButtonComponent(
201
+ index: number,
202
+ payload: string
203
+ ): WhatsappTemplateQuickReplyButton {
204
+ return {
205
+ type: WhatsAppTemplateComponentType.BUTTON,
206
+ sub_type: WhatsAppTemplateButtonSubType.QUICK_REPLY,
207
+ index: index,
208
+ parameters: [
209
+ {
210
+ type: WhatsAppTemplateParameterType.PAYLOAD,
211
+ payload: payload,
212
+ },
213
+ ],
214
+ }
215
+ }
216
+
217
+ private createVoiceCallButtonComponent(
218
+ index: number
219
+ ): WhatsappTemplateVoiceCallButton {
220
+ return {
221
+ type: WhatsAppTemplateComponentType.BUTTON,
222
+ sub_type: WhatsAppTemplateButtonSubType.VOICE_CALL,
223
+ index: index,
224
+ parameters: [],
225
+ }
226
+ }
227
+
228
+ async trackFlow(request: ActionRequest): Promise<void> {
229
+ await trackOneContent(request, this)
230
+ }
231
+
232
+ toBotonic(id: string, request: ActionRequest): JSX.Element {
233
+ const templateName = this.htWhatsappTemplate.name
234
+ const templateLanguage = this.htWhatsappTemplate.language
235
+ const body = this.getBodyComponent(this.variableValues, request)
236
+ const pluginFlowBuilder = getFlowBuilderPlugin(request.plugins)
237
+ const resolvedLocale = pluginFlowBuilder.cmsApi.getResolvedLocale()
238
+
239
+ const header = this.getHeaderComponent(
240
+ this.htWhatsappTemplate,
241
+ this.headerVariables || ({} as HeaderVariables),
242
+ resolvedLocale,
243
+ request
244
+ )
245
+ const buttons = this.getButtons(
246
+ this.htWhatsappTemplate,
247
+ this.buttons || [],
248
+ this.urlVariableValues || {},
249
+ request
250
+ )
251
+
252
+ console.log('toBotonic templateName', templateName)
253
+ console.log('toBotonic templateLanguage', templateLanguage)
254
+ console.log('toBotonic resolvedLocale', resolvedLocale)
255
+ console.log('toBotonic header', JSON.stringify(header, null, 2))
256
+ console.log('toBotonic body', JSON.stringify(body, null, 2))
257
+ console.log('toBotonic buttons', JSON.stringify(buttons, null, 2))
258
+
259
+ if (isWhatsapp(request.session)) {
260
+ return (
261
+ <WhatsappTemplate
262
+ key={id}
263
+ name={templateName}
264
+ language={templateLanguage}
265
+ header={header}
266
+ body={body}
267
+ buttons={buttons}
268
+ />
269
+ )
270
+ }
271
+
272
+ return (
273
+ <Text key={id}>
274
+ {`WhatsApp Template: ${templateName} (${templateLanguage})`}
275
+ {header && `${JSON.stringify(header, null, 2)}`}
276
+ {body && `${JSON.stringify(body, null, 2)}`}
277
+ {buttons && `${JSON.stringify(buttons, null, 2)}`}
278
+ </Text>
279
+ )
280
+ }
281
+ }
@@ -13,6 +13,7 @@ export interface HtFlowBuilderData {
13
13
  nodes: HtNodeComponent[]
14
14
  flows: HtFlows[]
15
15
  webviews: HtFlowWebview[]
16
+ campaigns: HtCampaign[]
16
17
  }
17
18
 
18
19
  export interface HtFlows {
@@ -27,6 +28,12 @@ export interface HtFlowWebview {
27
28
  component_name: string
28
29
  }
29
30
 
31
+ export interface HtCampaign {
32
+ id: string
33
+ name: string
34
+ start_node_id: string
35
+ }
36
+
30
37
  export interface HtNodeLink {
31
38
  id: string
32
39
  type: HtNodeWithContentType | HtNodeWithoutContentType
@@ -20,3 +20,4 @@ export * from './video'
20
20
  export * from './webview'
21
21
  export * from './whatsapp-button-list'
22
22
  export * from './whatsapp-cta-url-button'
23
+ export * from './whatsapp-template'
@@ -10,6 +10,7 @@ export enum HtNodeWithContentType {
10
10
  VIDEO = 'video',
11
11
  WHATSAPP_BUTTON_LIST = 'whatsapp-button-list',
12
12
  WHATSAPP_CTA_URL_BUTTON = 'whatsapp-cta-url-button',
13
+ WHATSAPP_TEMPLATE = 'whatsapp-template',
13
14
  KNOWLEDGE_BASE = 'knowledge-base',
14
15
  BOT_ACTION = 'bot-action',
15
16
  AI_AGENT = 'ai-agent',
@@ -21,6 +21,7 @@ import { HtVideoNode } from './video'
21
21
  import { HtWebviewNode } from './webview'
22
22
  import { HtWhatsappButtonListNode } from './whatsapp-button-list'
23
23
  import { HtWhatsappCTAUrlButtonNode } from './whatsapp-cta-url-button'
24
+ import { HtWhatsappTemplateNode } from './whatsapp-template'
24
25
 
25
26
  export type HtNodeWithContent =
26
27
  | HtTextNode
@@ -40,6 +41,7 @@ export type HtNodeWithContent =
40
41
  | HtRatingNode
41
42
  | HtWebviewNode
42
43
  | HtGoToFlow
44
+ | HtWhatsappTemplateNode
43
45
  // | HtChannelConditionalNode
44
46
  // | HtCountryConditionalNode
45
47
  // | HtCustomConditionalNode
@@ -0,0 +1,84 @@
1
+ import {
2
+ WhatsAppTemplateButtonSubType,
3
+ WhatsAppTemplateComponentType,
4
+ WhatsAppTemplateParameterType,
5
+ } from '@botonic/react'
6
+
7
+ import { HtButton } from './button'
8
+ import { HtBaseNode, HtMediaFileLocale } from './common'
9
+ import { HtNodeWithContentType } from './node-types'
10
+
11
+ type HtWhatsAppTemplateButton =
12
+ | {
13
+ type: WhatsAppTemplateButtonSubType.URL
14
+ text: string
15
+ url?: string
16
+ index: number
17
+ }
18
+ | {
19
+ type: WhatsAppTemplateButtonSubType.QUICK_REPLY
20
+ text: string
21
+ id: string
22
+ index: number
23
+ }
24
+ | {
25
+ type: WhatsAppTemplateButtonSubType.PHONE_NUMBER
26
+ text: string
27
+ phone_number: string
28
+ index: number
29
+ }
30
+
31
+ export interface HtWhatsAppTemplateHeaderComponent {
32
+ type: WhatsAppTemplateComponentType.HEADER
33
+ format:
34
+ | WhatsAppTemplateParameterType.TEXT
35
+ | WhatsAppTemplateParameterType.IMAGE
36
+ text?: string
37
+ image?: { link: string }
38
+ }
39
+
40
+ export interface HtWhatsAppTemplateBodyComponent {
41
+ type: WhatsAppTemplateComponentType.BODY
42
+ text: string
43
+ }
44
+
45
+ export interface HtWhatsAppTemplateFooterComponent {
46
+ type: WhatsAppTemplateComponentType.FOOTER
47
+ text: string
48
+ }
49
+
50
+ export interface HtWhatsAppTemplateButtonsComponent {
51
+ type: WhatsAppTemplateComponentType.BUTTONS
52
+ buttons: HtWhatsAppTemplateButton[]
53
+ }
54
+ export type HtWhatsAppTemplateComponent =
55
+ | HtWhatsAppTemplateHeaderComponent
56
+ | HtWhatsAppTemplateBodyComponent
57
+ | HtWhatsAppTemplateFooterComponent
58
+ | HtWhatsAppTemplateButtonsComponent
59
+
60
+ export interface HtWhatsAppTemplate {
61
+ id: string
62
+ name: string
63
+ language: string
64
+ status: string
65
+ category: string
66
+ components: HtWhatsAppTemplateComponent[]
67
+ namespace: string
68
+ parameter_format: string
69
+ }
70
+ export interface HtWhatsappTemplateNode extends HtBaseNode {
71
+ type: HtNodeWithContentType.WHATSAPP_TEMPLATE
72
+ content: {
73
+ template: HtWhatsAppTemplate
74
+ header_variables?: {
75
+ type: WhatsAppTemplateParameterType
76
+ text?: Record<string, string>
77
+ media?: HtMediaFileLocale[]
78
+ }
79
+ variable_values: Record<string, string>
80
+
81
+ buttons: HtButton[]
82
+ url_variable_values?: Record<string, string>
83
+ }
84
+ }
@@ -16,6 +16,7 @@ import { FlowRating } from './flow-rating'
16
16
  import { FlowText } from './flow-text'
17
17
  import { FlowVideo } from './flow-video'
18
18
  import { FlowWhatsappCtaUrlButtonNode } from './flow-whatsapp-cta-url-button'
19
+ import { FlowWhatsappTemplate } from './flow-whatsapp-template'
19
20
  import { FlowWhatsappButtonList } from './whatsapp-button-list/flow-whatsapp-button-list'
20
21
 
21
22
  export { ContentFieldsBase } from './content-fields-base'
@@ -38,6 +39,7 @@ export {
38
39
  FlowVideo,
39
40
  FlowWhatsappButtonList,
40
41
  FlowWhatsappCtaUrlButtonNode,
42
+ FlowWhatsappTemplate,
41
43
  }
42
44
 
43
45
  export type FlowContent =
@@ -47,6 +49,7 @@ export type FlowContent =
47
49
  | FlowVideo
48
50
  | FlowWhatsappButtonList
49
51
  | FlowWhatsappCtaUrlButtonNode
52
+ | FlowWhatsappTemplate
50
53
  | FlowHandoff
51
54
  | FlowKnowledgeBase
52
55
  | FlowBotAction
@@ -19,6 +19,7 @@ import {
19
19
  FlowVideo,
20
20
  FlowWhatsappButtonList,
21
21
  FlowWhatsappCtaUrlButtonNode,
22
+ FlowWhatsappTemplate,
22
23
  } from './content-fields'
23
24
  import {
24
25
  HtFunctionNode,
@@ -90,6 +91,9 @@ export class FlowFactory {
90
91
  case HtNodeWithContentType.GO_TO_FLOW:
91
92
  return FlowGoToFlow.fromHubtypeCMS(hubtypeContent, this.cmsApi)
92
93
 
94
+ case HtNodeWithContentType.WHATSAPP_TEMPLATE:
95
+ return FlowWhatsappTemplate.fromHubtypeCMS(hubtypeContent)
96
+
93
97
  default:
94
98
  return undefined
95
99
  }