@seamly/web-ui 20.3.1 → 20.6.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/CHANGELOG.md +769 -0
- package/build/dist/lib/index.debug.js +66 -99
- package/build/dist/lib/index.debug.min.js +1 -1
- package/build/dist/lib/index.debug.min.js.LICENSE.txt +8 -20
- package/build/dist/lib/index.js +748 -4372
- package/build/dist/lib/index.min.js +1 -1
- package/build/dist/lib/index.min.js.LICENSE.txt +0 -5
- package/build/dist/lib/standalone.js +606 -4449
- package/build/dist/lib/standalone.min.js +1 -1
- package/build/dist/lib/style-guide.js +373 -178
- package/build/dist/lib/style-guide.min.js +1 -1
- package/build/dist/lib/styles.css +1 -1
- package/package.json +2 -4
- package/src/javascripts/api/index.js +17 -1
- package/src/javascripts/domains/config/reducer.js +2 -0
- package/src/javascripts/domains/forms/provider.js +14 -6
- package/src/javascripts/domains/store/index.js +11 -11
- package/src/javascripts/domains/store/state-reducer.js +1 -0
- package/src/javascripts/domains/translations/middleware.js +6 -5
- package/src/javascripts/domains/visibility/actions.js +2 -0
- package/src/javascripts/domains/visibility/hooks.js +60 -1
- package/src/javascripts/domains/visibility/reducer.js +5 -0
- package/src/javascripts/domains/visibility/selectors.js +5 -0
- package/src/javascripts/domains/visibility/utils.js +5 -1
- package/src/javascripts/style-guide/components/app.js +2 -0
- package/src/javascripts/style-guide/states.js +86 -51
- package/src/javascripts/ui/components/conversation/conversation.js +40 -36
- package/src/javascripts/ui/components/conversation/event/card-component.js +1 -2
- package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +19 -9
- package/src/javascripts/ui/components/conversation/event/cta.js +1 -2
- package/src/javascripts/ui/components/conversation/event/image.js +11 -3
- package/src/javascripts/ui/components/conversation/event/participant.js +2 -11
- package/src/javascripts/ui/components/conversation/event/splash.js +1 -3
- package/src/javascripts/ui/components/conversation/event/text.js +9 -9
- package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +6 -0
- package/src/javascripts/ui/components/layout/chat.js +52 -48
- package/src/javascripts/ui/components/suggestions/suggestions-list.js +12 -14
- package/src/javascripts/ui/components/view/deprecated-view.js +16 -11
- package/src/javascripts/ui/components/view/inline-view.js +13 -8
- package/src/javascripts/ui/hooks/seamly-entry-hooks.js +3 -2
- package/src/javascripts/ui/hooks/seamly-state-hooks.js +7 -3
- package/src/javascripts/ui/hooks/use-seamly-chat.js +41 -29
- package/src/javascripts/ui/hooks/use-seamly-commands.js +16 -4
- package/src/javascripts/ui/utils/seamly-utils.js +27 -7
- package/src/stylesheets/5-components/_message-count.scss +5 -2
- package/webpack/parts/dev-server.js +10 -1
- package/src/.DS_Store +0 -0
- package/src/javascripts/lib/parse-body.js +0 -10
- package/src/javascripts/ui/components/conversation/event/hooks/use-text-rendering.js +0 -35
|
@@ -17,6 +17,7 @@ const baseState = {
|
|
|
17
17
|
},
|
|
18
18
|
initialState: {},
|
|
19
19
|
unreadEvents: 0,
|
|
20
|
+
loadedImageEventIds: [],
|
|
20
21
|
isLoading: false,
|
|
21
22
|
idleDetachCountdown: { hasCountdown: false, isActive: false },
|
|
22
23
|
resumeConversationPrompt: false,
|
|
@@ -58,7 +59,9 @@ const baseState = {
|
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
const avatar =
|
|
61
|
-
'data:image/svg+xml;base64,
|
|
62
|
+
'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMiAzMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzIgMzIiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8cGF0aCBmaWxsPSIjNEE0OEMxIiBkPSJNMTAsMTQuOGMtMS4xLDAtMi0wLjktMi0yczAuOS0yLDItMnMyLDAuOSwyLDJTMTEuMSwxNC44LDEwLDE0Ljh6IE0xNS45LDE0LjhjMS4xLDAsMi0wLjksMi0ycy0wLjktMi0yLTIKCXMtMiwwLjktMiwyUzE0LjgsMTQuOCwxNS45LDE0Ljh6IE0yMS44LDEwLjhjLTEuMSwwLTIsMC45LTIsMnMwLjksMiwyLDJzMi0wLjksMi0yUzIyLjksMTAuOCwyMS44LDEwLjh6IE0yMS4zLDE4LjFIMTAuNwoJQzExLjcsMjMuOSwyMC4yLDIzLjksMjEuMywxOC4xeiIvPgo8L3N2Zz4K'
|
|
63
|
+
const transferAvatar =
|
|
64
|
+
'data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAzMiAzMiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMzIgMzIiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8cGF0aCBmaWxsPSIjNEE0OEMxIiBkPSJNMTAuMSwxNC45Yy0xLjEsMC0yLTAuOS0yLTJzMC45LTIsMi0yczIsMC45LDIsMlMxMS4yLDE0LjksMTAuMSwxNC45eiBNMjEuOSwxMC45Yy0xLjEsMC0yLDAuOS0yLDIKCXMwLjksMiwyLDJzMi0wLjksMi0yUzIzLDEwLjksMjEuOSwxMC45eiBNMjEuNCwxOC4ySDEwLjhDMTEuOCwyNCwyMC4zLDI0LDIxLjQsMTguMnogTTE3LjIsMjUuM2gtMi40Yy0wLjYsMC0xLjIsMC40LTEuNCwxCgljLTUuMS0wLjItOS4yLTQuNC05LjQtOS42YzAuMSwwLDAuMiwwLjEsMC40LDAuMWgwLjFjMC44LDAsMS40LTAuNiwxLjQtMS40di00LjdjMC0wLjgtMC42LTEuNC0xLjQtMS40aDBjLTAuOCwwLTEuNCwwLjYtMS40LDEuNAoJdjIuN3YydjEuMWMwLDUuOSw0LjcsMTAuNiwxMC41LDEwLjhjMC4yLDAuNSwwLjcsMC44LDEuMiwwLjhoMi40YzAuOCwwLDEuNC0wLjYsMS40LTEuNFMxOCwyNS4zLDE3LjIsMjUuM3oiLz4KPC9zdmc+Cg=='
|
|
62
65
|
|
|
63
66
|
const participantInfo = {
|
|
64
67
|
participants: {
|
|
@@ -155,7 +158,6 @@ const infoMessage = {
|
|
|
155
158
|
body: {
|
|
156
159
|
text: 'This is a system generated info message',
|
|
157
160
|
type: 'text',
|
|
158
|
-
variables: {},
|
|
159
161
|
},
|
|
160
162
|
fromClient: false,
|
|
161
163
|
id: randomId(),
|
|
@@ -198,7 +200,7 @@ const participantMessage = {
|
|
|
198
200
|
participant: {
|
|
199
201
|
avatar,
|
|
200
202
|
id: 'agent',
|
|
201
|
-
introduction: "You're now talking to
|
|
203
|
+
introduction: "You're now talking to Mrs. Bot gimme a minit",
|
|
202
204
|
name: 'Mrs. Bot',
|
|
203
205
|
service: {
|
|
204
206
|
expose: { map: {}, version: 2 },
|
|
@@ -213,6 +215,32 @@ const participantMessage = {
|
|
|
213
215
|
},
|
|
214
216
|
}
|
|
215
217
|
|
|
218
|
+
const participantTransferMessage = {
|
|
219
|
+
type: 'participant',
|
|
220
|
+
payload: {
|
|
221
|
+
fromClient: false,
|
|
222
|
+
fromHistory: true,
|
|
223
|
+
id: randomId(),
|
|
224
|
+
messageStatus: 'received',
|
|
225
|
+
participant: {
|
|
226
|
+
introduction:
|
|
227
|
+
'Welcome, you are now chatting with Mrs. Bot 2, give me a minit to read back the chat history.',
|
|
228
|
+
id: 'agent',
|
|
229
|
+
avatar: transferAvatar,
|
|
230
|
+
name: 'Two',
|
|
231
|
+
service: {
|
|
232
|
+
expose: { map: {}, version: 3 },
|
|
233
|
+
meta: {},
|
|
234
|
+
name: 'new service',
|
|
235
|
+
serviceSessionId: randomId(),
|
|
236
|
+
settings: {},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
transactionId: randomId(),
|
|
240
|
+
type: 'participant',
|
|
241
|
+
},
|
|
242
|
+
}
|
|
243
|
+
|
|
216
244
|
const participantMessageDefaultIcon = {
|
|
217
245
|
type: 'participant',
|
|
218
246
|
payload: {
|
|
@@ -222,7 +250,7 @@ const participantMessageDefaultIcon = {
|
|
|
222
250
|
messageStatus: 'received',
|
|
223
251
|
participant: {
|
|
224
252
|
id: 'user',
|
|
225
|
-
introduction: "You're now talking to
|
|
253
|
+
introduction: "You're now talking to Mrs. Bot gimme a minit",
|
|
226
254
|
name: 'Mrs. Bot',
|
|
227
255
|
service: {
|
|
228
256
|
expose: { map: {}, version: 2 },
|
|
@@ -244,7 +272,6 @@ const getCustomMessage = ({ type, data, text }) => ({
|
|
|
244
272
|
type,
|
|
245
273
|
text,
|
|
246
274
|
data,
|
|
247
|
-
variables: {},
|
|
248
275
|
},
|
|
249
276
|
participant: 'agent',
|
|
250
277
|
service: {
|
|
@@ -268,7 +295,6 @@ const shortTextMessage = {
|
|
|
268
295
|
body: {
|
|
269
296
|
text: 'What do you want to do?',
|
|
270
297
|
type: 'text',
|
|
271
|
-
variables: {},
|
|
272
298
|
},
|
|
273
299
|
fromClient: false,
|
|
274
300
|
fromHistory: true,
|
|
@@ -303,7 +329,8 @@ const ctaMessage = {
|
|
|
303
329
|
type: 'message',
|
|
304
330
|
payload: {
|
|
305
331
|
body: {
|
|
306
|
-
description:
|
|
332
|
+
description:
|
|
333
|
+
'Thanks for chatting!\n\nMore info about our <strong>products</strong>?',
|
|
307
334
|
buttonLink: 'https://seamly.ai',
|
|
308
335
|
buttonText: 'View website',
|
|
309
336
|
buttonNewTab: true,
|
|
@@ -330,7 +357,6 @@ const longTextMessage = {
|
|
|
330
357
|
body: {
|
|
331
358
|
text: 'What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am. What do you want to do? This is a really long message from a bot that has a lot to say about a lot of things. Currently I am contemplating my own bot existence and constantly asking myself who I am.',
|
|
332
359
|
type: 'text',
|
|
333
|
-
variables: {},
|
|
334
360
|
},
|
|
335
361
|
fromClient: false,
|
|
336
362
|
fromHistory: true,
|
|
@@ -352,9 +378,8 @@ const textMessageBoldItalicUnderline = {
|
|
|
352
378
|
type: 'message',
|
|
353
379
|
payload: {
|
|
354
380
|
body: {
|
|
355
|
-
text: 'Bubble with
|
|
381
|
+
text: 'Bubble with <strong>bold</strong> <em>italic</em> <u>underline</u>',
|
|
356
382
|
type: 'text',
|
|
357
|
-
variables: {},
|
|
358
383
|
},
|
|
359
384
|
fromClient: false,
|
|
360
385
|
fromHistory: true,
|
|
@@ -376,24 +401,8 @@ const textMessageWithLinks = {
|
|
|
376
401
|
type: 'message',
|
|
377
402
|
payload: {
|
|
378
403
|
body: {
|
|
379
|
-
text: '
|
|
404
|
+
text: '<a href="https://google.com" data-link-id="1">Link in same window</a> and <a href="https://google.com" data-link-id="2" target="_blank">link in new window</a> embedded in text',
|
|
380
405
|
type: 'text',
|
|
381
|
-
variables: {
|
|
382
|
-
link_1: {
|
|
383
|
-
id: '1',
|
|
384
|
-
name: 'Link in same window',
|
|
385
|
-
newTab: false,
|
|
386
|
-
type: 'link',
|
|
387
|
-
url: 'https://google.com',
|
|
388
|
-
},
|
|
389
|
-
link_2: {
|
|
390
|
-
id: '2',
|
|
391
|
-
name: 'link in new window',
|
|
392
|
-
newTab: true,
|
|
393
|
-
type: 'link',
|
|
394
|
-
url: 'https://google.com',
|
|
395
|
-
},
|
|
396
|
-
},
|
|
397
406
|
},
|
|
398
407
|
fromClient: false,
|
|
399
408
|
fromHistory: true,
|
|
@@ -415,17 +424,8 @@ const textMessageWithLongLink = {
|
|
|
415
424
|
type: 'message',
|
|
416
425
|
payload: {
|
|
417
426
|
body: {
|
|
418
|
-
text: 'Here is a long link
|
|
427
|
+
text: 'Here is a long link <a href="https://google.com" data-link-id="1">click me click me please click me yoohoooo please please click me here I am click me now what are you waiting for click me now now now now now click meeeeeeeeeeeeee</a> embedded in text',
|
|
419
428
|
type: 'text',
|
|
420
|
-
variables: {
|
|
421
|
-
link_1: {
|
|
422
|
-
id: '1',
|
|
423
|
-
name: 'click me click me please click me yoohoooo please please click me here I am click me now what are you waiting for click me now now now now now click meeeeeeeeeeeeee',
|
|
424
|
-
newTab: false,
|
|
425
|
-
type: 'link',
|
|
426
|
-
url: 'https://google.com',
|
|
427
|
-
},
|
|
428
|
-
},
|
|
429
429
|
},
|
|
430
430
|
fromClient: false,
|
|
431
431
|
fromHistory: true,
|
|
@@ -449,7 +449,6 @@ const textMesageWithBullets = {
|
|
|
449
449
|
body: {
|
|
450
450
|
text: '<ul>\n<li>Bullets</li>\n<li>bullets</li>\n<li>bullets</li>\n</ul>\n',
|
|
451
451
|
type: 'text',
|
|
452
|
-
variables: {},
|
|
453
452
|
},
|
|
454
453
|
fromClient: false,
|
|
455
454
|
fromHistory: true,
|
|
@@ -604,7 +603,6 @@ const userMessage = {
|
|
|
604
603
|
body: {
|
|
605
604
|
text: 'This is what the user typed',
|
|
606
605
|
type: 'text',
|
|
607
|
-
variables: {},
|
|
608
606
|
},
|
|
609
607
|
fromClient: true,
|
|
610
608
|
fromHistory: true,
|
|
@@ -623,7 +621,23 @@ const userMessageLong = {
|
|
|
623
621
|
body: {
|
|
624
622
|
text: 'This is what the user typed. And sometimes the user has quite a lot to say and then we get longer lines that need to wrap well and not break the styling so here goes with just such a line right here!!',
|
|
625
623
|
type: 'text',
|
|
626
|
-
|
|
624
|
+
},
|
|
625
|
+
fromClient: true,
|
|
626
|
+
fromHistory: true,
|
|
627
|
+
id: randomId(),
|
|
628
|
+
messageStatus: 'read',
|
|
629
|
+
participant: 'user',
|
|
630
|
+
transactionId: '1cdefea9-7437-4672-bcf8-2c75dc99244c',
|
|
631
|
+
transactionLast: null,
|
|
632
|
+
type: 'text',
|
|
633
|
+
},
|
|
634
|
+
}
|
|
635
|
+
const userMessageWithLinks = {
|
|
636
|
+
type: 'message',
|
|
637
|
+
payload: {
|
|
638
|
+
body: {
|
|
639
|
+
text: '<a href="https://google.com" data-link-id="1">Link in same window</a> and <a href="https://google.com" data-link-id="2" target="_blank">link in new window</a> embedded in text',
|
|
640
|
+
type: 'text',
|
|
627
641
|
},
|
|
628
642
|
fromClient: true,
|
|
629
643
|
fromHistory: true,
|
|
@@ -835,7 +849,7 @@ const cardAskText = {
|
|
|
835
849
|
},
|
|
836
850
|
buttonText: 'Ask about pizzas!',
|
|
837
851
|
description:
|
|
838
|
-
'Pizza Margherita is a
|
|
852
|
+
'Pizza Margherita is a <strong>typical Neapolitan pizza</strong>.\n\nIt is made with San Marzano tomatoes, mozzarella cheese, fresh basil, salt, and extra-virgin olive oil.',
|
|
839
853
|
image:
|
|
840
854
|
'https://developers.seamly.ai/clients/web-ui/static/photos/card-square.jpg',
|
|
841
855
|
title: 'Pizza Margherita',
|
|
@@ -854,7 +868,8 @@ const cardNavigate = {
|
|
|
854
868
|
type: 'navigate',
|
|
855
869
|
},
|
|
856
870
|
buttonText: 'Order now!',
|
|
857
|
-
description:
|
|
871
|
+
description:
|
|
872
|
+
'Pizza Margherita is a <strong>typical Neapolitan pizza</strong>.',
|
|
858
873
|
image:
|
|
859
874
|
'https://developers.seamly.ai/clients/web-ui/static/photos/card-landscape.jpg',
|
|
860
875
|
title: 'Pizza Margherita',
|
|
@@ -1090,8 +1105,10 @@ const standardState = {
|
|
|
1090
1105
|
},
|
|
1091
1106
|
},
|
|
1092
1107
|
longTextMessage,
|
|
1108
|
+
participantTransferMessage,
|
|
1093
1109
|
userMessage,
|
|
1094
1110
|
textMessageBoldItalicUnderline,
|
|
1111
|
+
userMessageWithLinks,
|
|
1095
1112
|
newTopicDivider,
|
|
1096
1113
|
imageMessage,
|
|
1097
1114
|
fileDownloadAgentMessage,
|
|
@@ -1119,6 +1136,7 @@ const standardState = {
|
|
|
1119
1136
|
userMessageLong,
|
|
1120
1137
|
fileDownloadUserMessage,
|
|
1121
1138
|
emptyUrlFileDownloadUserMessage,
|
|
1139
|
+
userMessageWithLinks,
|
|
1122
1140
|
],
|
|
1123
1141
|
},
|
|
1124
1142
|
withParticipants: {
|
|
@@ -1196,12 +1214,12 @@ const standardState = {
|
|
|
1196
1214
|
body: {
|
|
1197
1215
|
text: 'Long ago when a dialog started',
|
|
1198
1216
|
type: 'text',
|
|
1199
|
-
variables: {},
|
|
1200
1217
|
},
|
|
1201
1218
|
},
|
|
1202
1219
|
},
|
|
1203
1220
|
participantMessage,
|
|
1204
1221
|
participantMessageDefaultIcon,
|
|
1222
|
+
participantTransferMessage,
|
|
1205
1223
|
newTopicDivider,
|
|
1206
1224
|
transcriptInfoMessage,
|
|
1207
1225
|
...[newTranslationDividerStart, newTranslationDividerStop].map(
|
|
@@ -1258,7 +1276,6 @@ const standardState = {
|
|
|
1258
1276
|
body: {
|
|
1259
1277
|
text: 'Long ago when a dialog started',
|
|
1260
1278
|
type: 'text',
|
|
1261
|
-
variables: {},
|
|
1262
1279
|
},
|
|
1263
1280
|
},
|
|
1264
1281
|
},
|
|
@@ -1271,7 +1288,6 @@ const standardState = {
|
|
|
1271
1288
|
body: {
|
|
1272
1289
|
text: 'Above me should be a time indicator showing the full date',
|
|
1273
1290
|
type: 'text',
|
|
1274
|
-
variables: {},
|
|
1275
1291
|
},
|
|
1276
1292
|
},
|
|
1277
1293
|
},
|
|
@@ -1284,7 +1300,6 @@ const standardState = {
|
|
|
1284
1300
|
body: {
|
|
1285
1301
|
text: 'Another message',
|
|
1286
1302
|
type: 'text',
|
|
1287
|
-
variables: {},
|
|
1288
1303
|
},
|
|
1289
1304
|
},
|
|
1290
1305
|
},
|
|
@@ -1297,7 +1312,6 @@ const standardState = {
|
|
|
1297
1312
|
body: {
|
|
1298
1313
|
text: 'And another message',
|
|
1299
1314
|
type: 'text',
|
|
1300
|
-
variables: {},
|
|
1301
1315
|
},
|
|
1302
1316
|
},
|
|
1303
1317
|
},
|
|
@@ -1310,7 +1324,6 @@ const standardState = {
|
|
|
1310
1324
|
body: {
|
|
1311
1325
|
text: 'Above me should be a time indicator showing "yesterday"',
|
|
1312
1326
|
type: 'text',
|
|
1313
|
-
variables: {},
|
|
1314
1327
|
},
|
|
1315
1328
|
},
|
|
1316
1329
|
},
|
|
@@ -1323,7 +1336,6 @@ const standardState = {
|
|
|
1323
1336
|
body: {
|
|
1324
1337
|
text: 'Another message',
|
|
1325
1338
|
type: 'text',
|
|
1326
|
-
variables: {},
|
|
1327
1339
|
},
|
|
1328
1340
|
},
|
|
1329
1341
|
},
|
|
@@ -1336,7 +1348,6 @@ const standardState = {
|
|
|
1336
1348
|
body: {
|
|
1337
1349
|
text: 'And another message',
|
|
1338
1350
|
type: 'text',
|
|
1339
|
-
variables: {},
|
|
1340
1351
|
},
|
|
1341
1352
|
},
|
|
1342
1353
|
},
|
|
@@ -1349,7 +1360,6 @@ const standardState = {
|
|
|
1349
1360
|
body: {
|
|
1350
1361
|
text: 'Above me should be a time indicator showing me the dialog continues today',
|
|
1351
1362
|
type: 'text',
|
|
1352
|
-
variables: {},
|
|
1353
1363
|
},
|
|
1354
1364
|
},
|
|
1355
1365
|
},
|
|
@@ -1772,6 +1782,30 @@ const inlineInterface = {
|
|
|
1772
1782
|
},
|
|
1773
1783
|
},
|
|
1774
1784
|
},
|
|
1785
|
+
minimizedInlineCharacterLimit: {
|
|
1786
|
+
category: categoryKeys.minimizedInline,
|
|
1787
|
+
headingText: 'Inline minimized with limited characters',
|
|
1788
|
+
description: '',
|
|
1789
|
+
inline: {
|
|
1790
|
+
...baseState,
|
|
1791
|
+
config: {
|
|
1792
|
+
...baseState.config,
|
|
1793
|
+
layoutMode: 'inline',
|
|
1794
|
+
},
|
|
1795
|
+
visibility: {
|
|
1796
|
+
...baseState.visibility,
|
|
1797
|
+
visibility: visibilityStates.minimized,
|
|
1798
|
+
},
|
|
1799
|
+
entryMeta: {
|
|
1800
|
+
...baseState.entryMeta,
|
|
1801
|
+
options: {
|
|
1802
|
+
text: {
|
|
1803
|
+
limit: 120,
|
|
1804
|
+
},
|
|
1805
|
+
},
|
|
1806
|
+
},
|
|
1807
|
+
},
|
|
1808
|
+
},
|
|
1775
1809
|
minimizedInlinePrechat: {
|
|
1776
1810
|
category: categoryKeys.minimizedInline,
|
|
1777
1811
|
headingText: 'Inline minimized with pre-chat messages',
|
|
@@ -1908,6 +1942,7 @@ const newInterface = {
|
|
|
1908
1942
|
description: '',
|
|
1909
1943
|
...baseState,
|
|
1910
1944
|
events: [
|
|
1945
|
+
getCustomMessage(shortTextMessage.payload.body),
|
|
1911
1946
|
{
|
|
1912
1947
|
type: 'service_data',
|
|
1913
1948
|
payload: {
|
|
@@ -6,55 +6,57 @@ import {
|
|
|
6
6
|
useSkiplink,
|
|
7
7
|
useSkiplinkTargetFocusing,
|
|
8
8
|
} from 'ui/hooks/seamly-hooks'
|
|
9
|
-
import { useEvents } from 'ui/hooks/seamly-state-hooks'
|
|
9
|
+
import { useEvents, useLoadedImageEventIds } from 'ui/hooks/seamly-state-hooks'
|
|
10
10
|
import PrivacyDisclaimer from 'ui/components/layout/privacy-disclaimer'
|
|
11
11
|
import { useVisibility } from 'domains/visibility'
|
|
12
12
|
import Event from './event/event'
|
|
13
13
|
import Loader from './loader'
|
|
14
14
|
import ComponentFilter from './component-filter'
|
|
15
15
|
|
|
16
|
+
const Events = () => {
|
|
17
|
+
const events = useEvents()
|
|
18
|
+
|
|
19
|
+
let prevParticipant = null
|
|
20
|
+
return events.map((event) => {
|
|
21
|
+
const { type, payload } = event
|
|
22
|
+
const { participant, fromClient } = payload
|
|
23
|
+
let participantChanged = false
|
|
24
|
+
if (type !== 'participant') {
|
|
25
|
+
const currentParticipant = fromClient
|
|
26
|
+
? 'seamly-client-participant'
|
|
27
|
+
: participant
|
|
28
|
+
if (event.type !== 'info' && prevParticipant !== currentParticipant) {
|
|
29
|
+
participantChanged = true
|
|
30
|
+
}
|
|
31
|
+
prevParticipant = currentParticipant
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Event
|
|
36
|
+
key={event.payload.key || event.payload.id}
|
|
37
|
+
event={event}
|
|
38
|
+
newParticipant={participantChanged}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
16
44
|
const Conversation = () => {
|
|
17
45
|
const { t } = useI18n()
|
|
18
|
-
const
|
|
46
|
+
const chatBodyContainer = useRef(null)
|
|
19
47
|
const events = useEvents()
|
|
20
48
|
const isLoading = useSeamlyIsLoading()
|
|
21
49
|
const { isOpen } = useVisibility()
|
|
22
50
|
const skiplinkTargetId = useSkiplink()
|
|
23
51
|
const focusSkiplinkTarget = useSkiplinkTargetFocusing()
|
|
52
|
+
const loadedImageEventIds = useLoadedImageEventIds()
|
|
24
53
|
|
|
25
54
|
useEffect(() => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
})
|
|
32
|
-
}, [events, isLoading, isOpen])
|
|
33
|
-
|
|
34
|
-
const renderEvents = () => {
|
|
35
|
-
let prevParticipant = null
|
|
36
|
-
return events.map((event) => {
|
|
37
|
-
const { type, payload } = event
|
|
38
|
-
const { participant, fromClient } = payload
|
|
39
|
-
let participantChanged = false
|
|
40
|
-
if (type !== 'participant') {
|
|
41
|
-
const currentParticipant = fromClient
|
|
42
|
-
? 'seamly-client-participant'
|
|
43
|
-
: participant
|
|
44
|
-
if (event.type !== 'info' && prevParticipant !== currentParticipant) {
|
|
45
|
-
participantChanged = true
|
|
46
|
-
}
|
|
47
|
-
prevParticipant = currentParticipant
|
|
48
|
-
}
|
|
49
|
-
return (
|
|
50
|
-
<Event
|
|
51
|
-
key={event.payload.id}
|
|
52
|
-
event={event}
|
|
53
|
-
newParticipant={participantChanged}
|
|
54
|
-
/>
|
|
55
|
-
)
|
|
56
|
-
})
|
|
57
|
-
}
|
|
55
|
+
const containerElement = chatBodyContainer.current
|
|
56
|
+
if (containerElement) {
|
|
57
|
+
containerElement.scrollTop = containerElement.scrollHeight
|
|
58
|
+
}
|
|
59
|
+
}, [events, isLoading, isOpen, loadedImageEventIds])
|
|
58
60
|
|
|
59
61
|
const onClickHandler = (e) => {
|
|
60
62
|
e.preventDefault()
|
|
@@ -72,11 +74,13 @@ const Conversation = () => {
|
|
|
72
74
|
{t('skiplinkText')}
|
|
73
75
|
</a>
|
|
74
76
|
)}
|
|
75
|
-
<div className={className('chat__body')} ref={
|
|
77
|
+
<div className={className('chat__body')} ref={chatBodyContainer}>
|
|
76
78
|
<div className={className('conversation__container')}>
|
|
77
79
|
<PrivacyDisclaimer />
|
|
78
80
|
<ol className={className('conversation')}>
|
|
79
|
-
<ComponentFilter>
|
|
81
|
+
<ComponentFilter>
|
|
82
|
+
<Events />
|
|
83
|
+
</ComponentFilter>
|
|
80
84
|
{isLoading && <Loader />}
|
|
81
85
|
</ol>
|
|
82
86
|
</div>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef } from 'preact/hooks'
|
|
2
2
|
import { className } from 'lib/css'
|
|
3
|
-
import parseBody from 'lib/parse-body'
|
|
4
3
|
import { useGeneratedId, useSeamlyCommands } from 'ui/hooks/seamly-hooks'
|
|
5
4
|
import { cardTypes, actionTypes } from 'ui/utils/seamly-utils'
|
|
6
5
|
|
|
@@ -84,7 +83,7 @@ const CardComponent = ({
|
|
|
84
83
|
{description && (
|
|
85
84
|
<div
|
|
86
85
|
className={className('card__description')}
|
|
87
|
-
dangerouslySetInnerHTML={{ __html:
|
|
86
|
+
dangerouslySetInnerHTML={{ __html: description }}
|
|
88
87
|
/>
|
|
89
88
|
)}
|
|
90
89
|
<CardActionComponent
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { useCallback, useState } from 'preact/hooks'
|
|
1
|
+
import { useCallback, useMemo, useState } from 'preact/hooks'
|
|
2
2
|
import { className } from 'lib/css'
|
|
3
|
+
import {
|
|
4
|
+
useEvents,
|
|
5
|
+
useSeamlyCommands,
|
|
6
|
+
useSeamlyDispatchContext,
|
|
7
|
+
} from 'ui/hooks/seamly-hooks'
|
|
3
8
|
import { useI18n } from 'domains/i18n'
|
|
4
9
|
import { useTranslatedEventData } from 'domains/translations'
|
|
5
10
|
import { useUserHasResponded } from 'domains/app'
|
|
6
11
|
import { setHasResponded } from 'domains/app/actions'
|
|
7
|
-
import { actionTypes } from '
|
|
8
|
-
import MessageContainer from '
|
|
9
|
-
import
|
|
10
|
-
useSeamlyCommands,
|
|
11
|
-
useSeamlyDispatchContext,
|
|
12
|
-
} from '../../../hooks/seamly-hooks'
|
|
13
|
-
import SuggestionsList from '../../suggestions/suggestions-list'
|
|
12
|
+
import { actionTypes } from 'ui/utils/seamly-utils'
|
|
13
|
+
import MessageContainer from 'ui/components/conversation/message-container'
|
|
14
|
+
import SuggestionsList from 'ui/components/suggestions/suggestions-list'
|
|
14
15
|
|
|
15
16
|
export const useSuggestions = (event) => {
|
|
16
17
|
const { payload } = event
|
|
@@ -28,11 +29,20 @@ const ConversationSuggestions = ({ event, ...props }) => {
|
|
|
28
29
|
const userResponded = useUserHasResponded()
|
|
29
30
|
const { sendAction, addMessageBubble } = useSeamlyCommands()
|
|
30
31
|
const { suggestions, payload } = useSuggestions(event)
|
|
32
|
+
const events = useEvents()
|
|
31
33
|
|
|
32
34
|
const { t } = useI18n()
|
|
33
35
|
const headingText = t('suggestions.headingText')
|
|
34
36
|
const footerText = t('suggestions.footerText')
|
|
35
37
|
|
|
38
|
+
// We check if there is at least one last transaction
|
|
39
|
+
// to avoid rendering the suggestions before prior events are rendered.
|
|
40
|
+
const hasLastTransactionEvent = useMemo(
|
|
41
|
+
() =>
|
|
42
|
+
events.some(({ payload: eventPayload }) => eventPayload?.transactionLast),
|
|
43
|
+
[events],
|
|
44
|
+
)
|
|
45
|
+
|
|
36
46
|
const handleClick = useCallback(
|
|
37
47
|
({ id, question }) => {
|
|
38
48
|
setIsExpanded(false)
|
|
@@ -56,7 +66,7 @@ const ConversationSuggestions = ({ event, ...props }) => {
|
|
|
56
66
|
[dispatch, sendAction, payload.id, addMessageBubble],
|
|
57
67
|
)
|
|
58
68
|
|
|
59
|
-
if (!isExpanded || userResponded) {
|
|
69
|
+
if (!isExpanded || userResponded || !hasLastTransactionEvent) {
|
|
60
70
|
return null
|
|
61
71
|
}
|
|
62
72
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useCallback } from 'preact/hooks'
|
|
2
2
|
import { className } from 'lib/css'
|
|
3
|
-
import parseBody from 'lib/parse-body'
|
|
4
3
|
import { useGeneratedId, useSeamlyCommands } from 'ui/hooks/seamly-hooks'
|
|
5
4
|
import { actionTypes } from 'ui/utils/seamly-utils'
|
|
6
5
|
import MessageContainer from 'ui/components/conversation/message-container'
|
|
@@ -31,7 +30,7 @@ const Cta = ({ event }) => {
|
|
|
31
30
|
<div
|
|
32
31
|
className={className('cta__content')}
|
|
33
32
|
id={descriptionId}
|
|
34
|
-
dangerouslySetInnerHTML={{ __html:
|
|
33
|
+
dangerouslySetInnerHTML={{ __html: body.description }}
|
|
35
34
|
onClick={eventClick}
|
|
36
35
|
/>
|
|
37
36
|
<a
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { useState } from 'preact/hooks'
|
|
2
2
|
import MessageContainer from 'ui/components/conversation/message-container'
|
|
3
3
|
import { useTranslatedEventData } from 'domains/translations'
|
|
4
|
+
import { useStoreDispatch } from 'domains/redux'
|
|
4
5
|
import ImageLightbox from './image-lightbox'
|
|
6
|
+
import { seamlyActions } from '../../../utils/seamly-utils'
|
|
7
|
+
|
|
8
|
+
const { SET_LOADED_IMAGE_EVENT_IDS } = seamlyActions
|
|
5
9
|
|
|
6
10
|
const Image = ({ event, descriptorId, ...props }) => {
|
|
7
11
|
const [body] = useTranslatedEventData(event)
|
|
8
12
|
const { description, url, isZoomable } = body
|
|
9
13
|
const [showLighbox, setShowLightbox] = useState(false)
|
|
14
|
+
const dispatch = useStoreDispatch()
|
|
15
|
+
|
|
16
|
+
const handleOnLoad = () => {
|
|
17
|
+
dispatch({ type: SET_LOADED_IMAGE_EVENT_IDS, eventId: event.payload.id })
|
|
18
|
+
setShowLightbox(true)
|
|
19
|
+
}
|
|
10
20
|
|
|
11
21
|
return (
|
|
12
22
|
<MessageContainer event={event} type="image" {...props}>
|
|
@@ -14,9 +24,7 @@ const Image = ({ event, descriptorId, ...props }) => {
|
|
|
14
24
|
src={url}
|
|
15
25
|
id={descriptorId}
|
|
16
26
|
alt={description}
|
|
17
|
-
onLoad={
|
|
18
|
-
setShowLightbox(true)
|
|
19
|
-
}}
|
|
27
|
+
onLoad={handleOnLoad}
|
|
20
28
|
/>
|
|
21
29
|
{isZoomable && showLighbox && (
|
|
22
30
|
<ImageLightbox description={description} url={url} />
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { useMemo } from 'preact/hooks'
|
|
2
|
-
import Mustache from 'mustache'
|
|
3
|
-
import parseBody from 'lib/parse-body'
|
|
4
1
|
import EventDivider from 'ui/components/conversation/event-divider'
|
|
5
2
|
import { useTranslatedEventData } from 'domains/translations'
|
|
6
3
|
|
|
@@ -8,13 +5,7 @@ const Participant = ({ event }) => {
|
|
|
8
5
|
const { participant } = event.payload
|
|
9
6
|
const [introduction] = useTranslatedEventData(event)
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
return introduction
|
|
13
|
-
? Mustache.render(parseBody(introduction), participant)
|
|
14
|
-
: undefined
|
|
15
|
-
}, [introduction, participant])
|
|
16
|
-
|
|
17
|
-
if (!intro) {
|
|
8
|
+
if (!introduction) {
|
|
18
9
|
return null
|
|
19
10
|
}
|
|
20
11
|
|
|
@@ -23,7 +14,7 @@ const Participant = ({ event }) => {
|
|
|
23
14
|
graphicSrc={participant.avatar}
|
|
24
15
|
graphicType={participant.avatar ? 'avatar' : undefined}
|
|
25
16
|
iconName={!participant.avatar ? 'balloon' : undefined}
|
|
26
|
-
childrenHTML={
|
|
17
|
+
childrenHTML={introduction}
|
|
27
18
|
dividerType="participant"
|
|
28
19
|
/>
|
|
29
20
|
)
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import parseBody from '../../../../lib/parse-body'
|
|
2
1
|
import useEventLinkClickHandler from './hooks/use-event-link-click-handler'
|
|
3
|
-
import { parseRichText } from './hooks/use-text-rendering'
|
|
4
2
|
import MessageContainer from '../message-container'
|
|
5
3
|
import { useTranslatedEventData } from '../../../../domains/translations'
|
|
6
4
|
|
|
@@ -17,7 +15,7 @@ const Splash = ({ event, ...props }) => {
|
|
|
17
15
|
{...props}
|
|
18
16
|
bodyProps={{
|
|
19
17
|
dangerouslySetInnerHTML: {
|
|
20
|
-
__html:
|
|
18
|
+
__html: body.text,
|
|
21
19
|
},
|
|
22
20
|
}}
|
|
23
21
|
/>
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { useMemo } from 'preact/hooks'
|
|
2
|
-
import parseBody from 'lib/parse-body'
|
|
3
2
|
import MessageContainer from 'ui/components/conversation/message-container'
|
|
4
3
|
import { useTranslatedEventData } from 'domains/translations'
|
|
5
4
|
import useEventLinkClickHandler from './hooks/use-event-link-click-handler'
|
|
6
|
-
import { parseRichText } from './hooks/use-text-rendering'
|
|
7
5
|
|
|
8
6
|
const Text = ({ event, ...props }) => {
|
|
9
7
|
const [body] = useTranslatedEventData(event)
|
|
10
8
|
const eventClick = useEventLinkClickHandler(event.payload.id)
|
|
11
9
|
|
|
12
10
|
const containerProps = useMemo(() => {
|
|
13
|
-
if (
|
|
11
|
+
if (event.payload.optimisticallyInjected) {
|
|
14
12
|
return {
|
|
15
|
-
|
|
16
|
-
dangerouslySetInnerHTML: {
|
|
17
|
-
__html: parseRichText(parseBody(body.text), body.variables),
|
|
18
|
-
},
|
|
19
|
-
},
|
|
13
|
+
children: <p>{body.text}</p>,
|
|
20
14
|
}
|
|
21
15
|
}
|
|
16
|
+
|
|
22
17
|
return {
|
|
23
|
-
|
|
18
|
+
bodyProps: {
|
|
19
|
+
dangerouslySetInnerHTML: {
|
|
20
|
+
__html: body.text,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
24
23
|
}
|
|
25
24
|
}, [body, event])
|
|
25
|
+
|
|
26
26
|
return (
|
|
27
27
|
<MessageContainer
|
|
28
28
|
type="text"
|