@kindly/react-chat 2.35.2 → 2.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,602 @@
1
+ /* eslint-disable react-hooks/exhaustive-deps */
2
+ /* eslint-disable react/prop-types */
3
+ import { expect } from '@storybook/jest';
4
+ import { screen, userEvent } from '@storybook/testing-library';
5
+ import React from 'react';
6
+ import withFetchMock from 'storybook-addon-mock';
7
+
8
+ import { IMAGE_SIZE } from 'app/constants';
9
+
10
+ import KindlyChatButton from '../../src/features/KindlyChatButton/KindlyChatButton';
11
+ import settingsJSON from '../assets/settingsJson';
12
+ import withContainer from '../decorators/withContainer';
13
+ import withMockProvider from '../decorators/withProvider';
14
+
15
+ const defaultBotSettings = {
16
+ welcomePage: settingsJSON.welcome_page,
17
+ feedbackForm: settingsJSON.feedback_form,
18
+ maintenanceAlert: settingsJSON.maintenance_alert,
19
+ ...settingsJSON.settings,
20
+ ...settingsJSON,
21
+ };
22
+
23
+ const Template = (args, context) => {
24
+ return <KindlyChatButton {...args} {...context} />;
25
+ };
26
+
27
+ export default {
28
+ title: 'Screen/Chat',
29
+ component: KindlyChatButton,
30
+ decorators: [withFetchMock, withContainer, withMockProvider],
31
+ argTypes: {
32
+ initialStateModifierFromArgs: {
33
+ table: {
34
+ disable: true,
35
+ },
36
+ },
37
+ },
38
+ };
39
+
40
+ export const Regular = Template.bind({});
41
+ Regular.parameters = {
42
+ botSettings: defaultBotSettings,
43
+ initialStateModifier: {
44
+ chatbubble: {
45
+ active: true,
46
+ chatHasStarted: true,
47
+ currentLanguage: 'en',
48
+ },
49
+ messages: {
50
+ chatMessages: [
51
+ {
52
+ session_id: '1',
53
+ bot_id: 1234,
54
+ chat_id: '1',
55
+ chat_source: 'web',
56
+ chat_language_code: 'en',
57
+ from_bot: true,
58
+ sender: 'BOT',
59
+ message:
60
+ "Hi! I'm Kindly's Chatbot. I can answer questions about Kindly and our services. How can I help you? 🙂\n<br>\n<br>Feel free to ask me a short and concise question!",
61
+ message_format: 'txt',
62
+ exchange_type: 'greeting',
63
+ exchange_id: '1',
64
+ reply_type: 'STANDARD',
65
+ created: '2022-06-09T18:46:51.672Z',
66
+ id: '1',
67
+ },
68
+ {
69
+ id: '2',
70
+ created: '2022-06-09T18:47:03.919Z',
71
+ message: 'What is the meaning of life?',
72
+ status: null,
73
+ },
74
+ {
75
+ session_id: '6061c1d4-54da-4886-85a2-7f555c9cd42c',
76
+ bot_id: 3875,
77
+ chat_id: '1',
78
+ chat_source: 'web',
79
+ chat_language_code: 'en',
80
+ from_bot: true,
81
+ sender: 'BOT',
82
+ reply_to_id: '2',
83
+ last_user_message_id: '2',
84
+ message:
85
+ 'Well... I don\'t have a conclusive answer for what the meaning of life is, but here are some suggestions:\n<ul style="padding-left:12px;">\n<li>To live a good life\n<li>To spread love\n<li>42\n</ul>',
86
+ message_format: 'txt',
87
+ exchange_type: 'usersays',
88
+ exchange_id: '3',
89
+ title: 'The meaning of life',
90
+ created: '2022-06-09T18:47:04.009Z',
91
+ id: '3',
92
+ },
93
+ ],
94
+ messageSentTime: '2022-06-09T18:47:03.697Z',
95
+ lastMessageSeen: {
96
+ id: '3',
97
+ index: 3,
98
+ },
99
+ },
100
+ },
101
+ };
102
+
103
+ export const BotIsTyping = Template.bind({});
104
+ BotIsTyping.parameters = {
105
+ botSettings: defaultBotSettings,
106
+ initialStateModifier: {
107
+ chatbubble: {
108
+ active: true,
109
+ chatHasStarted: true,
110
+ currentLanguage: 'en',
111
+ },
112
+ messages: {
113
+ chatMessages: [
114
+ {
115
+ id: '2',
116
+ created: '2022-06-09T18:47:03.919Z',
117
+ message: 'What is the meaning of life?',
118
+ status: null,
119
+ },
120
+ ],
121
+ },
122
+ bot: {
123
+ isTyping: true,
124
+ },
125
+ },
126
+ };
127
+
128
+ export const Maintenance = Template.bind({});
129
+ Maintenance.parameters = {
130
+ botSettings: defaultBotSettings,
131
+ initialStateModifier: {
132
+ chatbubble: {
133
+ active: true,
134
+ chatHasStarted: true,
135
+ currentLanguage: 'en',
136
+ },
137
+ maintenanceAlert: {
138
+ show: true,
139
+ textContent: 'Maintenance mode!',
140
+ linkText: 'Click here to know more',
141
+ linkLocation: 'https://example.com',
142
+ },
143
+ },
144
+ };
145
+
146
+ export const HiddenInput = Template.bind({});
147
+ HiddenInput.parameters = {
148
+ botSettings: defaultBotSettings,
149
+ initialStateModifier: {
150
+ chatbubble: {
151
+ active: true,
152
+ chatHasStarted: true,
153
+ currentLanguage: 'en',
154
+ hideInputField: true,
155
+ },
156
+ messages: {
157
+ chatMessages: [
158
+ {
159
+ id: '1',
160
+ chat_source: 'web',
161
+ chat_language_code: 'en',
162
+ from_bot: true,
163
+ sender: 'BOT',
164
+ message: 'Here is a button',
165
+ message_format: 'txt',
166
+ buttons: [
167
+ {
168
+ id: '1',
169
+ button_type: 'quick_reply',
170
+ language_code: 'en',
171
+ label: 'Click here to continue',
172
+ value: 'clicked',
173
+ index: 0,
174
+ created_at: '2022-06-11T20:14:06.290705Z',
175
+ updated_at: '2022-06-11T20:14:06.291003Z',
176
+ is_active: true,
177
+ },
178
+ ],
179
+ created: '2022-06-11T20:14:06.290705Z',
180
+ title: 'noinput',
181
+ chatbubble_hide_input_field: true,
182
+ },
183
+ ],
184
+ },
185
+ },
186
+ };
187
+
188
+ export const MultilineBotMessage = Template.bind({});
189
+ MultilineBotMessage.parameters = {
190
+ ...Regular.parameters,
191
+ initialStateModifier: {
192
+ ...Regular.parameters.initialStateModifier,
193
+ messages: {
194
+ chatMessages: [
195
+ {
196
+ from_bot: true,
197
+ sender: 'BOT',
198
+ message: 'This is a \n\n multiline \n\n bot message',
199
+ created: '2022-06-09T18:46:51.672Z',
200
+ id: '1',
201
+ },
202
+ ],
203
+ },
204
+ },
205
+ };
206
+
207
+ export const GroupsOfMessages = Template.bind({});
208
+ GroupsOfMessages.parameters = {
209
+ botSettings: defaultBotSettings,
210
+ initialStateModifier: {
211
+ chatbubble: {
212
+ active: true,
213
+ chatHasStarted: true,
214
+ currentLanguage: 'en',
215
+ },
216
+ messages: {
217
+ chatMessages: [
218
+ {
219
+ id: '1',
220
+ created: '2022-06-09T18:47:03.919Z',
221
+ message: 'Hipp',
222
+ status: null,
223
+ },
224
+ {
225
+ id: '2',
226
+ created: '2022-06-09T18:47:03.919Z',
227
+ message: 'Hipp',
228
+ status: null,
229
+ },
230
+ {
231
+ id: '3',
232
+ created: '2022-06-09T18:47:03.919Z',
233
+ message: 'Hurra!',
234
+ status: null,
235
+ },
236
+ {
237
+ id: '4',
238
+ from_bot: true,
239
+ sender: 'BOT',
240
+ message: 'Hipp',
241
+ created: '2022-06-09T18:47:04.009Z',
242
+ },
243
+ {
244
+ id: '5',
245
+ from_bot: true,
246
+ sender: 'BOT',
247
+ message: 'Hipp',
248
+ created: '2022-06-09T18:47:04.009Z',
249
+ },
250
+ {
251
+ id: '6',
252
+ from_bot: true,
253
+ sender: 'BOT',
254
+ message: 'Hurra!',
255
+ created: '2022-06-09T18:47:04.009Z',
256
+ },
257
+ ],
258
+ },
259
+ },
260
+ };
261
+
262
+ export const HandoverRequested = Template.bind({});
263
+ HandoverRequested.parameters = {
264
+ botSettings: defaultBotSettings,
265
+ initialStateModifier: {
266
+ chatbubble: {
267
+ active: true,
268
+ chatHasStarted: true,
269
+ currentLanguage: 'en',
270
+ },
271
+ agent: {
272
+ requestedTakeover: true,
273
+ takeoverClosed: false,
274
+ },
275
+ messages: {
276
+ chatMessages: [
277
+ {
278
+ id: '1',
279
+ created: '2022-06-09T18:47:03.919Z',
280
+ message: 'Could I please talk with a human person?',
281
+ status: null,
282
+ },
283
+ ],
284
+ },
285
+ },
286
+ };
287
+
288
+ export const HandoverCancelled = Template.bind({});
289
+ HandoverCancelled.parameters = HandoverRequested.parameters;
290
+ HandoverCancelled.play = async () => {
291
+ expect(await screen.findByText(defaultBotSettings.text.takeover_queue_text.en)).toBeInTheDocument();
292
+ const leaveQueueButton = await screen.findByText(defaultBotSettings.text.takeover_queue_link.en);
293
+ await userEvent.click(leaveQueueButton);
294
+ expect(await screen.findByText(defaultBotSettings.text.leave_queue_text.en)).toBeInTheDocument();
295
+ };
296
+
297
+ export const Checkbox = Template.bind({});
298
+ Checkbox.parameters = {
299
+ ...Regular.parameters,
300
+ initialStateModifier: {
301
+ ...Regular.parameters.initialStateModifier,
302
+ messages: {
303
+ chatMessages: [
304
+ {
305
+ chat_language_code: 'en',
306
+ from_bot: true,
307
+ sender: 'BOT',
308
+ message: 'Check out those checkboxes!',
309
+ message_format: 'txt',
310
+ buttons: [
311
+ {
312
+ id: '1',
313
+ button_type: 'checkbox',
314
+ language_code: 'en',
315
+ label: 'Checkbox label',
316
+ value: 'Checkbox value',
317
+ index: 0,
318
+ is_active: true,
319
+ },
320
+ {
321
+ id: '2',
322
+ button_type: 'checkbox',
323
+ language_code: 'en',
324
+ label: 'Checkbox label 2',
325
+ value: 'Checkbox value 2',
326
+ index: 1,
327
+ is_active: true,
328
+ },
329
+ {
330
+ id: '3',
331
+ button_type: 'submit',
332
+ language_code: 'en',
333
+ label: 'Submit',
334
+ index: 2,
335
+ is_active: true,
336
+ },
337
+ ],
338
+ created: '2022-06-11T16:13:00.143Z',
339
+ },
340
+ ],
341
+ },
342
+ },
343
+ };
344
+
345
+ const videoSources = [
346
+ ['YouTube', 'https://www.youtube.com/watch?v=vvg5AfQEmUc'],
347
+ ['Vimeo', 'https://vimeo.com/148751763'],
348
+ ['Self hosted', 'https://www.crockpot.se/wp-content/uploads/2019/02/Comp-1-1.mp4'],
349
+ ];
350
+ export const VideoEmbed = Template.bind({});
351
+ VideoEmbed.args = {
352
+ videoSource: videoSources[0][0],
353
+ videoSourceList: videoSources,
354
+ initialStateModifierFromArgs: ({ videoSource, videoSourceList }) => ({
355
+ ...Regular.parameters.initialStateModifier,
356
+ messages: {
357
+ chatMessages: [
358
+ {
359
+ id: '1',
360
+ chat_language_code: 'en',
361
+ from_bot: true,
362
+ sender: 'BOT',
363
+ message: 'Here is Video embed',
364
+ message_format: 'txt',
365
+ video_source: videoSourceList.find((videoSourceMap) => videoSourceMap[0] === videoSource)[1],
366
+ title: 'embed',
367
+ created: '2022-06-11T16:22:15.425Z',
368
+ },
369
+ ],
370
+ },
371
+ }),
372
+ };
373
+ VideoEmbed.argTypes = {
374
+ videoSource: {
375
+ options: videoSources.map((videoSource) => videoSource[0]),
376
+ control: { type: 'select' },
377
+ },
378
+ videoSourceList: {
379
+ table: {
380
+ disable: true,
381
+ },
382
+ },
383
+ };
384
+ VideoEmbed.parameters = {
385
+ botSettings: defaultBotSettings,
386
+ };
387
+
388
+ export const ImageGallery = Template.bind({});
389
+ const textSizes = [
390
+ undefined,
391
+ 'Lorem ipsum dolor sit amet.',
392
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
393
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
394
+ ];
395
+ ImageGallery.args = {
396
+ imageCarouselSize: 1000,
397
+ titleSize: 0,
398
+ descriptionSize: 0,
399
+ hasLink: false,
400
+ newTab: false,
401
+ initialStateModifierFromArgs: ({ imageCarouselSize, titleSize, descriptionSize, hasLink, newTab }) => ({
402
+ ...Regular.parameters.initialStateModifier,
403
+ messages: {
404
+ chatMessages: [
405
+ {
406
+ id: '1',
407
+ chat_source: 'web',
408
+ chat_language_code: 'en',
409
+ from_bot: true,
410
+ sender: 'BOT',
411
+ message: 'Here is an image gallery',
412
+ message_format: 'txt',
413
+ image_carousel: [
414
+ {
415
+ id: '1',
416
+ imageUrl: 'https://i.imgur.com/Iz1nJrw.jpg',
417
+ title: textSizes[titleSize],
418
+ description: textSizes[descriptionSize],
419
+ linkUrl: hasLink ? 'https://example.com' : undefined,
420
+ altText: textSizes[titleSize],
421
+ newTab,
422
+ },
423
+ {
424
+ id: '2',
425
+ imageUrl: 'https://i.imgur.com/H49sTpN.jpg',
426
+ title: textSizes[titleSize],
427
+ description: textSizes[descriptionSize],
428
+ linkUrl: hasLink ? 'https://example.com' : undefined,
429
+ altText: textSizes[titleSize],
430
+ newTab,
431
+ },
432
+ {
433
+ id: '3',
434
+ imageUrl: 'https://i.imgur.com/Htlr2rv.jpg',
435
+ title: textSizes[titleSize],
436
+ description: textSizes[descriptionSize],
437
+ linkUrl: hasLink ? 'https://example.com' : undefined,
438
+ altText: textSizes[titleSize],
439
+ newTab,
440
+ },
441
+ ],
442
+ image_carousel_size: imageCarouselSize,
443
+ title: 'Image Gallery',
444
+ created: '2022-06-11T16:44:33.885Z',
445
+ },
446
+ ],
447
+ },
448
+ }),
449
+ };
450
+ ImageGallery.argTypes = {
451
+ imageCarouselSize: {
452
+ options: Object.keys(IMAGE_SIZE).map((size) => parseInt(size, 10)),
453
+ control: { type: 'radio' },
454
+ },
455
+ titleSize: {
456
+ control: { type: 'range', min: 0, max: textSizes.length - 1, step: 1 },
457
+ },
458
+ descriptionSize: {
459
+ control: { type: 'range', min: 0, max: textSizes.length - 1, step: 1 },
460
+ },
461
+ hasLink: {
462
+ control: 'boolean',
463
+ },
464
+ newTab: {
465
+ control: 'boolean',
466
+ },
467
+ };
468
+ ImageGallery.parameters = {
469
+ botSettings: defaultBotSettings,
470
+ };
471
+
472
+ export const ImageGalleryWithDescription = Template.bind({});
473
+ ImageGalleryWithDescription.args = {
474
+ ...ImageGallery.args,
475
+ titleSize: 2,
476
+ descriptionSize: 2,
477
+ hasLink: true,
478
+ };
479
+ ImageGalleryWithDescription.argTypes = ImageGallery.argTypes;
480
+ ImageGalleryWithDescription.parameters = ImageGallery.parameters;
481
+
482
+ export const Slider = Template.bind({});
483
+ Slider.parameters = {
484
+ ...Regular.parameters,
485
+ initialStateModifier: {
486
+ ...Regular.parameters.initialStateModifier,
487
+ messages: {
488
+ chatMessages: [
489
+ {
490
+ chat_source: 'web',
491
+ chat_language_code: 'en',
492
+ from_bot: true,
493
+ sender: 'BOT',
494
+ message: 'Slide me!',
495
+ message_format: 'txt',
496
+ buttons: [
497
+ {
498
+ id: '1',
499
+ button_type: 'slider',
500
+ language_code: 'en',
501
+ label: 'Choose a value between 1 and 42',
502
+ index: 0,
503
+ created_at: '2022-06-15T19:03:46.186406Z',
504
+ slider_details: {
505
+ id: '1',
506
+ from_value: 1,
507
+ to_value: 42,
508
+ step_value: 1,
509
+ value: 10,
510
+ affix: 'SUFFIX',
511
+ affix_value: '%',
512
+ },
513
+ },
514
+ {
515
+ id: '2',
516
+ button_type: 'submit',
517
+ language_code: 'en',
518
+ label: 'Submit',
519
+ value: '1',
520
+ index: 1,
521
+ created_at: '2022-06-15T19:03:46.186495Z',
522
+ },
523
+ ],
524
+ created: '2022-06-15T19:03:46.186495Z',
525
+ title: 'slider',
526
+ id: '1',
527
+ },
528
+ ],
529
+ },
530
+ },
531
+ };
532
+
533
+ export const LeaveContactDetails = Template.bind({});
534
+ LeaveContactDetails.parameters = {
535
+ ...Regular.parameters,
536
+ initialStateModifier: {
537
+ ...Regular.parameters.initialStateModifier,
538
+ messages: {
539
+ chatMessages: [
540
+ {
541
+ id: '1',
542
+ chat_language_code: 'en',
543
+ from_bot: true,
544
+ sender: 'BOT',
545
+ message: "Let's get in touch!",
546
+ message_format: 'txt',
547
+ buttons: [
548
+ {
549
+ id: '1',
550
+ button_type: 'phone',
551
+ language_code: 'en',
552
+ label: 'Call us',
553
+ value: '69420',
554
+ index: 0,
555
+ created_at: '2022-06-11T19:49:29.870793Z',
556
+ updated_at: '2022-06-11T19:49:29.871010Z',
557
+ is_active: true,
558
+ },
559
+ {
560
+ id: '2',
561
+ button_type: 'email',
562
+ language_code: 'en',
563
+ label: 'Email us',
564
+ value: "contact@kindly.ai?subject=Email%20from%20storybook&body=Don't%20send%20that!",
565
+ index: 1,
566
+ created_at: '2022-06-11T19:49:29.870865Z',
567
+ updated_at: '2022-06-11T19:49:29.871033Z',
568
+ is_active: true,
569
+ email_details: {
570
+ id: '1',
571
+ subject: 'Email from storybook',
572
+ body: "Don't send that!",
573
+ },
574
+ },
575
+ {
576
+ id: '3',
577
+ button_type: 'contact_details',
578
+ label: 'Contact me back',
579
+ index: 2,
580
+ is_active: true,
581
+ contact_details: {
582
+ id: 'ae14453c-0156-40c9-a13a-0037f46bd14a',
583
+ contact_type: 'email',
584
+ label: 'Your email:',
585
+ edit_text: 'Contact me back',
586
+ placeholder: 'me@example.com',
587
+ },
588
+ },
589
+ ],
590
+ title: 'Contacts',
591
+ created: '2022-06-11T19:58:43.883Z',
592
+ },
593
+ ],
594
+ },
595
+ },
596
+ };
597
+ LeaveContactDetails.play = async () => {
598
+ const LeaveContactButton = await screen.findByText(
599
+ LeaveContactDetails.parameters.initialStateModifier.messages.chatMessages[0].buttons[2].label,
600
+ );
601
+ await userEvent.click(LeaveContactButton);
602
+ };
@@ -0,0 +1,87 @@
1
+ /* eslint-disable react/prop-types */
2
+ import React from 'react';
3
+ import withMock from 'storybook-addon-mock';
4
+
5
+ import KindlyChat from '../../src/KindlyChat';
6
+ import settings from '../assets/settingsJson';
7
+
8
+ const mockSettings = (response = settings) => ({
9
+ mockData: [
10
+ {
11
+ url: 'https://example.com/mockme/settings/1234.json?version=:version&kindly-chat-browser-id=:browserId',
12
+ method: 'GET',
13
+ status: 200,
14
+ response,
15
+ },
16
+ ],
17
+ });
18
+
19
+ const Template = (args) => {
20
+ return <KindlyChat botKey={'1234'} options={args.options || {}} {...args} />;
21
+ };
22
+
23
+ export default {
24
+ title: 'Screen/Button',
25
+ component: KindlyChat,
26
+ decorators: [withMock],
27
+ argTypes: {
28
+ options: {
29
+ table: {
30
+ disable: true,
31
+ },
32
+ },
33
+ setKindlyChatRef: {
34
+ table: {
35
+ disable: true,
36
+ },
37
+ },
38
+ },
39
+ };
40
+
41
+ export const Regular = Template.bind({});
42
+ Regular.parameters = mockSettings();
43
+
44
+ export const Christmas = Template.bind({});
45
+ Christmas.parameters = mockSettings({
46
+ ...settings,
47
+ settings: {
48
+ ...settings.settings,
49
+ seasonal_appearance: 'CHRISTMAS',
50
+ },
51
+ });
52
+
53
+ export const Pride = Template.bind({});
54
+ Pride.parameters = mockSettings({
55
+ ...settings,
56
+ settings: {
57
+ ...settings.settings,
58
+ seasonal_appearance: 'PRIDE',
59
+ },
60
+ });
61
+
62
+ export const Easter = Template.bind({});
63
+ Easter.parameters = mockSettings({
64
+ ...settings,
65
+ settings: {
66
+ ...settings.settings,
67
+ seasonal_appearance: 'EASTER',
68
+ },
69
+ });
70
+
71
+ export const SmallerOnTablet = Template.bind({});
72
+ SmallerOnTablet.parameters = mockSettings({
73
+ ...settings,
74
+ settings: {
75
+ ...settings.settings,
76
+ bubble_size: 'SMALL',
77
+ },
78
+ });
79
+
80
+ export const WithOutline = Template.bind({});
81
+ WithOutline.parameters = mockSettings({
82
+ ...settings,
83
+ settings: {
84
+ ...settings.settings,
85
+ use_bubble_outline: true,
86
+ },
87
+ });