@microsoft/omnichannel-chat-sdk 1.1.0 → 1.1.1-main.502460d

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 (2) hide show
  1. package/README.md +517 -380
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Omnichannel Chat SDK
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk.svg)](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk)
4
+ [![install size](https://packagephobia.com/badge?p=@microsoft/omnichannel-chat-sdk)](https://packagephobia.com/result?p=@microsoft/omnichannel-chat-sdk)
4
5
  ![Release CI](https://github.com/microsoft/omnichannel-chat-sdk/workflows/Release%20CI/badge.svg)
5
6
  ![npm](https://img.shields.io/npm/dm/@microsoft/omnichannel-chat-sdk)
6
7
 
@@ -12,12 +13,45 @@ Please make sure you have a chat widget configured before using this package or
12
13
  - [Live Chat Widget vs. Chat SDK](#live-chat-widget-vs-chat-sdk)
13
14
  - [Installation](#installation)
14
15
  - [Installation on React Native](#installation-on-react-native)
15
- - [API Reference](#api-reference)
16
- - [API Examples](#api-examples)
17
- - [Sample Apps](https://github.com/microsoft/omnichannel-chat-sdk-samples)
16
+ - [SDK Methods](#sdk-methods)
17
+ - [Initialization](#initialization)
18
+ - [Start Chat](#start-chat)
19
+ - [End Chat](#end-chat)
20
+ - [Get Pre-Chat Survey](#get-pre-chat-survey)
21
+ - [Get Live Chat Config](#get-live-chat-config)
22
+ - [Get Current Live Chat Context](#get-current-live-chat-context)
23
+ - [Get Data Masking Rules](#get-data-masking-rules)
24
+ - [Get Chat Reconnect Context](#get-chat-reconnect-context)
25
+ - [Get Conversation Details](#get-conversation-details)
26
+ - [Get Chat Token](#get-chat-token)
27
+ - [Get Calling Token](#get-calling-token)
28
+ - [Get Messages](#get-messages)
29
+ - [Send Messages](#send-messages)
30
+ - [On New Message](#on-new-message)
31
+ - [On Typing Event](#on-typing-event)
32
+ - [On Agent End Session](#on-agent-end-session)
33
+ - [Send Typing Event](#send-typing-event)
34
+ - [Email Live Chat Transcript](#email-live-chat-transcript)
35
+ - [Get Live Chat Transcript](#get-live-chat-transcript)
36
+ - [Upload File Attachment](#upload-file-attachment)
37
+ - [Download File Attachment](#download-file-attachment)
38
+ - [Create Chat Adapter](#create-chat-adapter)
39
+ - [Get Voice & Video Calling](#get-voice--video-calling)
40
+ - [Get Post Chat Survey Context](#get-post-chat-survey-context)
18
41
  - [Common Scenarios](#common-scenarios)
42
+ - [Using BotFramework-WebChat](#using-botframework-webchat)
43
+ - [Pre-Chat Survey](#pre-chat-survey)
44
+ - [Post-Chat Survey](#post-chat-survey)
45
+ - [Reconnect to existing Chat](#reconnect-to-existing-chat)
46
+ - [Authenticated Chat](#authenticated-chat)
47
+ - [Persistent Chat](#persistent-chat)
48
+ - [Chat Reconnect with Authenticated User](#chat-reconnect-with-authenticated-user)
49
+ - [Chat Reconnect with Unauthenticated User](#chat-reconnect-with-unauthenticated-user)
50
+ - [Operating Hours](#operating-hours)
51
+ - [Sample Apps](https://github.com/microsoft/omnichannel-chat-sdk-samples)
19
52
  - [Feature Comparisons](#feature-comparisons)
20
53
  - [Telemetry](#telemetry)
54
+ - [Development Guide](docs/DEVELOPMENT_GUIDE.md)
21
55
  - [Troubleshooting Guide](docs/TROUBLESHOOTING_GUIDE.md)
22
56
 
23
57
  ## Live Chat Widget vs. Chat SDK
@@ -58,7 +92,7 @@ Omnichannel offers an live chat widget (LCW) by default. You can use the Chat SD
58
92
  ## Installation
59
93
 
60
94
  ```
61
- npm install @microsoft/omnichannel-chat-sdk --save
95
+ npm install @microsoft/omnichannel-chat-sdk --save
62
96
  ```
63
97
 
64
98
  ## Installation on React Native
@@ -106,243 +140,301 @@ The following steps will be required to run Omnichannel Chat SDK on React Native
106
140
  import 'react-native-url-polyfill';
107
141
  ```
108
142
 
109
- ## API Reference
110
-
111
- | Method | Description | Notes |
112
- | ------ | ----------- | ----- |
113
- | OmnichannelChatSDK.initialize() | Initializes ChatSDK internal data | |
114
- | OmnichannelChatSDK.startChat() | Starts OC chat, handles prechat response | |
115
- | OmnichannelChatSDK.endChat() | Ends OC chat | |
116
- | OmnichannelChatSDK.getPreChatSurvey() | Adaptive card data of PreChat survey | |
117
- | OmnichannelChatSDK.getLiveChatConfig() | Get live chat config | |
118
- | OmnichannelChatSDK.getDataMaskingRules() | Get active data masking rules | |
119
- | OmnichannelChatSDK.getCurrentLiveChatContext() | Get current live chat context information to reconnect to the same chat | |
120
- | OmnichannelChatSDK.getChatReconnectContext() | Get current reconnectable chat context information to reconnect to a previous existing chat session | |
121
- | OmnichannelChatSDK.getConversationDetails() | Get details of the current conversation such as its state & when the agent joined the conversation | |
122
- | OmnichannelChatSDK.getChatToken() | Get chat token | |
123
- | OmnichannelChatSDK.getCallingToken() | Get calling token | |
124
- | OmnichannelChatSDK.getMessages() | Get all messages | |
125
- | OmnichannelChatSDK.sendMessage() | Send message | |
126
- | OmnichannelChatSDK.onNewMessage() | Handles system message, client/agent messages, adaptive cards, attachments to download | |
127
- | OmnichannelChatSDK.onTypingEvent() | Handles agent typing event | |
128
- | OmnichannelChatSDK.onAgentEndSession() | Handler when agent ends session | |
129
- | OmnichannelChatSDK.sendTypingEvent() | Sends customer typing event | |
130
- | OmnichannelChatSDK.emailLiveChatTranscript() | Email transcript | |
131
- | OmnichannelChatSDK.getLiveChatTranscript() | Get transcript data (JSON) | |
132
- | OmnichannelChatSDK.uploadFileAttachment() | Send file attachment | |
133
- | OmnichannelChatSDK.downloadFileAttachment() | Download file attachment | |
134
- | OmnichannelChatSDK.createChatAdapter() | Get Chat Adapter | **Web only** |
135
- | OmnichannelChatSDK.getVoiceVideoCalling() | Get VoiceVideoCall SDK for Escalation to Voice & Video | **Web only** |
136
- | OmnichannelChatSDK.getPostChatSurveyContext() | Get post chat survey link, survey locale, and whether an agent has joined the survey | |
137
-
138
- ## API examples
139
-
140
- ### Import
141
- ```ts
142
- import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
143
- ```
143
+ ## SDK Methods
144
144
 
145
145
  ### Initialization
146
+
147
+ It handles the initialization of ChatSDK internal data.
148
+
146
149
  ```ts
147
- const omnichannelConfig = {
148
- orgUrl: "",
149
- orgId: "",
150
- widgetId: ""
151
- };
150
+ import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
152
151
 
153
- const chatSDKConfig = { // Optional
154
- dataMasking: {
155
- disable: false,
156
- maskingCharacter: '#'
157
- }
158
- };
152
+ const omnichannelConfig = {
153
+ orgUrl: "",
154
+ orgId: "",
155
+ widgetId: ""
156
+ };
159
157
 
160
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
161
- await chatSDK.initialize();
162
- ```
158
+ const chatSDKConfig = { // Optional
159
+ dataMasking: {
160
+ disable: false,
161
+ maskingCharacter: '#'
162
+ }
163
+ };
163
164
 
164
- ### Get Current Live Chat Context
165
- ```ts
166
- const liveChatContext = await chatSDK.getCurrentLiveChatContext();
165
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
166
+ await chatSDK.initialize();
167
167
  ```
168
168
 
169
- ### Get Current Chat Reconnect Context
169
+ ### Start Chat
170
+
171
+ It starts an Omnichannel conversation.
172
+
170
173
  ```ts
171
- const optionalParams = {
172
- reconnectId: '', // reconnect Id
173
- };
174
+ const customContext = {
175
+ 'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
176
+ 'contextKey2': {'value': 12.34, 'isDisplayable': false},
177
+ 'contextKey3': {'value': true}
178
+ };
179
+
180
+ const optionalParams = {
181
+ preChatResponse: '', // PreChatSurvey response
182
+ liveChatContext: {}, // EXISTING chat context data
183
+ customContext // Custom Context
184
+ };
174
185
 
175
- const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
186
+ await chatSDK.startChat(optionalParams);
176
187
  ```
177
188
 
178
- ### Get Conversation Details
189
+ ### End Chat
190
+
191
+ It ends the current Omnichannel conversation.
192
+
179
193
  ```ts
180
- const conversationDetails = await chatSDK.getConversationDetails();
194
+ await chatSDK.endChat();
181
195
  ```
182
196
 
183
- ### Get Chat Token
197
+ ### Get Pre-Chat Survey
198
+
199
+ It gets the Pre-Chat Survey from Live Chat Config. Pre-Chat Survey is in Adaptive Card format.
200
+
201
+ `Option 1`
184
202
  ```ts
185
- const chatToken = await chatSDK.getChatToken();
203
+ const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
186
204
  ```
187
-
188
- ### Get Calling Token
205
+ `Option 2`
189
206
  ```ts
190
- const callingToken = await chatSDK.getCallingToken();
207
+ const parseToJSON = false;
208
+ const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
191
209
  ```
192
210
 
193
211
  ### Get Live Chat Config
212
+
213
+ It fetches the Live Chat Config.
214
+
194
215
  ```ts
195
- const liveChatConfig = await chatSDK.getLiveChatConfig();
216
+ const liveChatConfig = await chatSDK.getLiveChatConfig();
196
217
  ```
197
218
 
198
- ### Get Data Masking Rules
219
+ ### Get Current Live Chat Context
220
+
221
+ It gets the current live chat context information to be used to reconnect to the same conversation.
222
+
199
223
  ```ts
200
- const dataMaskingRules = await chatSDK.getDataMaskingRules();
224
+ const liveChatContext = await chatSDK.getCurrentLiveChatContext();
201
225
  ```
202
226
 
203
- ### Get PreChat Survey
204
- `Option 1`
227
+ ### Get Data Masking Rules
228
+
229
+ It gets the active data masking rules from Live Chat Config.
230
+
205
231
  ```ts
206
- const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
232
+ const dataMaskingRules = await chatSDK.getDataMaskingRules();
207
233
  ```
208
- `Option 2`
234
+
235
+ ### Get Chat Reconnect Context
236
+
237
+ It gets the current reconnectable chat context information to connect to a previous existing chat session.
238
+
239
+ `Reconnection options` is required. See [documentation](https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session)
240
+
209
241
  ```ts
210
- const parseToJSON = false;
211
- const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
242
+ const optionalParams = {
243
+ reconnectId: '', // reconnect Id
244
+ };
245
+
246
+ const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
212
247
  ```
213
248
 
214
- ### Get PostChat Survey
249
+ ### Get Conversation Details
250
+
251
+ It gets the details of the current conversation such as its state & when the agent joined the conversation.
252
+
215
253
  ```ts
216
- try {
217
- const context = await chatSDK.getPostChatSurveyContext();
218
- if (context.participantJoined) { // participantJoined will be true if an agent has joined the conversation, or a bot has joined the conversation and the bot survey flag has been turned on on the admin side.
219
- // formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
220
- // If "&lang=" is not set on the url, the locale will be English.
221
- const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
222
- // This link is accessible and will redirect to the survey page. Use it as you see fit.
223
- }
224
- } catch (ex) {
225
- // If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
226
- }
254
+ const conversationDetails = await chatSDK.getConversationDetails();
227
255
  ```
228
256
 
229
- ### Start Chat
257
+ ### Get chat Token
258
+
259
+ It gets the chat token used to initiates a chat with Omnichannel messaging client.
260
+
230
261
  ```ts
231
- const customContext = {
232
- 'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
233
- 'contextKey2': {'value': 12.34, 'isDisplayable': false},
234
- 'contextKey3': {'value': true}
235
- };
262
+ const chatToken = await chatSDK.getChatToken();
263
+ ```
236
264
 
237
- const optionalParams = {
238
- preChatResponse: '', // PreChatSurvey response
239
- liveChatContext: {}, // EXISTING chat context data
240
- customContext // Custom Context
241
- };
242
- await chatSDK.startChat(optionalParams);
265
+ ### Get Calling Token
266
+
267
+ It gets the calling token used to initiates a Voice & Video Call.
268
+
269
+ ```ts
270
+ const callingToken = await chatSDK.getCallingToken();
243
271
  ```
244
272
 
245
- ### End Chat
273
+ ### Get Messages
274
+
275
+ It gets all the messages of the current conversation.
276
+
246
277
  ```ts
247
- await chatSDK.endChat();
278
+ const messages = await chatSDK.getMessages();
248
279
  ```
249
280
 
250
- ### On New Message Handler
281
+ ### Send Messages
282
+
283
+ It sends a message to Omnichannel.
284
+
251
285
  ```ts
252
- const optionalParams = {
253
- rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
254
- }
286
+ import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
255
287
 
256
- chatSDK.onNewMessage((message) => {
257
- console.log(`[NewMessage] ${message.content}`); // IC3 protocol message data
258
- console.log(message);
259
- }, optionalParams);
288
+ ...
289
+
290
+ const displayName = "Contoso"
291
+ const message = "Sample message from customer";
292
+ const messageToSend = {
293
+ content: message
294
+ };
295
+
296
+ await chatSDK.sendMessage(messageToSend);
260
297
  ```
261
298
 
262
- ### On Agent End Session
299
+ ### On New Message
300
+
301
+ It subscribes to new incoming messages of the current conversation such as system messages, client messages, agent messages, adaptive cards and attachments.
302
+
263
303
  ```ts
264
- chatSDK.onAgentEndSession(() => {
265
- console.log("Session ended!");
266
- });
267
- ```
304
+ const optionalParams = {
305
+ rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
306
+ }
268
307
 
308
+ chatSDK.onNewMessage((message) => {
309
+ console.log(`[NewMessage] ${message.content}`);
310
+ console.log(message);
311
+ }, optionalParams);
312
+ ```
269
313
  ### On Typing Event
314
+
315
+ It subscribes to agent typing event.
316
+
270
317
  ```ts
271
- chatSDK.onTypingEvent(() => {
272
- console.log("Agent is typing...");
273
- })
318
+ chatSDK.onTypingEvent(() => {
319
+ console.log("Agent is typing...");
320
+ })
274
321
  ```
275
322
 
276
- ### Get Messages
323
+ ### On Agent End Session
324
+
325
+ It subscribes to agent ending the session of the conversation.
326
+
277
327
  ```ts
278
- const messages = await chatSDK.getMessages();
328
+ chatSDK.onAgentEndSession(() => {
329
+ console.log("Session ended!");
330
+ });
279
331
  ```
280
332
 
281
- ### Send Message
333
+ ### Send Typing Event
334
+
335
+ It sends a customer typing event.
336
+
282
337
  ```ts
283
- import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
338
+ await chatSDK.sendTypingEvent();
339
+ ```
284
340
 
285
- ...
341
+ ### Email Live Chat Transcript
286
342
 
287
- const displayName = "Contoso"
288
- const message = "Sample message from customer";
289
- const messageToSend = {
290
- content: message
291
- };
343
+ It sends an email of the live chat transcript.
292
344
 
293
- await chatSDK.sendMessage(messageToSend);
345
+ ```ts
346
+ const body = {
347
+ emailAddress: 'contoso@microsoft.com',
348
+ attachmentMessage: 'Attachment Message'
349
+ };
350
+ await chatSDK.emailLiveChatTranscript(body);
294
351
  ```
295
352
 
296
- ### Send Typing
353
+ ### Get Live Chat Transcript
354
+
355
+ It fetches the current conversation transcript data in JSON.
356
+
297
357
  ```ts
298
- await chatSDK.sendTypingEvent();
358
+ await chatSDK.getLiveChatTranscript();
299
359
  ```
300
360
 
301
- ### Upload Attachment
361
+ ### Upload File Attachment
362
+
363
+ It sends a file attachment to the current conversation.
364
+
302
365
  ```ts
303
- const fileInfo = {
304
- name: '',
305
- type: '',
306
- size: '',
307
- data: ''
308
- };
309
- await chatSDK.uploadFileAttachment(fileInfo);
366
+ const fileInfo = {
367
+ name: '',
368
+ type: '',
369
+ size: '',
370
+ data: ''
371
+ };
372
+ await chatSDK.uploadFileAttachment(fileInfo);
310
373
  ```
311
374
 
312
- ### Download Attachment
375
+ ### Download File Attachment
376
+
377
+ It downloads the file attachment of the incoming message as a Blob response.
378
+
313
379
  ```ts
314
- const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
380
+ const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
315
381
 
316
- ...
382
+ ...
317
383
 
318
- // React Native implementation
319
- const fileReaderInstance = new FileReader();
320
- fileReaderInstance.readAsDataURL(blobResponse);
321
- fileReaderInstance.onload = () => {
322
- const base64data = fileReaderInstance.result;
323
- return <Image source={{uri: base64data}}/>
324
- }
384
+ // React Native implementation
385
+ const fileReaderInstance = new FileReader();
386
+ fileReaderInstance.readAsDataURL(blobResponse);
387
+ fileReaderInstance.onload = () => {
388
+ const base64data = fileReaderInstance.result;
389
+ return <Image source={{uri: base64data}}/>
390
+ }
325
391
  ```
326
392
 
327
- ### Get Live Chat Transcript
393
+ ### Create Chat Adapter
394
+
395
+ > :warning: Currently supported on web only
396
+
397
+ It creates a chat adapter to use with [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat).
328
398
 
329
399
  ```ts
330
- await chatSDK.getLiveChatTranscript();
400
+ const chatAdapter = await chatSDK.createChatAdapter();
331
401
  ```
332
402
 
333
- ### Email Live Chat Transcript
403
+ ### Get Voice & Video Calling
404
+
405
+ > :warning: Currently supported on web only
406
+
407
+ It fetches the SDK for Escalation to Voice & Video.
334
408
 
335
409
  ```ts
336
- const body = {
337
- emailAddress: 'contoso@microsoft.com',
338
- attachmentMessage: 'Attachment Message'
339
- };
340
- await chatSDK.emailLiveChatTranscript(body);
410
+ try {
411
+ const VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
412
+ console.log("VoiceVideoCalling loaded");
413
+ } catch (e) {
414
+ console.log(`Failed to load VoiceVideoCalling: ${e}`);
415
+
416
+ if (e.message === 'UnsupportedPlatform') {
417
+ // Voice Video Calling feature is not supported on this platform
418
+ }
419
+
420
+ if (e.message === 'FeatureDisabled') {
421
+ // Voice Video Calling feature is disabled on admin side
422
+ }
423
+ }
424
+ ```
425
+ ### Get Post Chat Survey Context
426
+
427
+ It gets post chat survey link, survey locale, and whether an agent has joined the survey.
428
+
429
+ ```ts
430
+ const context = await chatSDK.getPostChatSurveyContext();
341
431
  ```
342
432
 
343
433
  ## Common Scenarios
344
434
 
345
- ### PreChatSurvey
435
+ ### Pre-Chat Survey
436
+
437
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-pre-chat-survey?tabs=customerserviceadmincenter on how to set up pre-conversation surveys
346
438
 
347
439
  ```ts
348
440
  import * as AdaptiveCards, { Action } from "adaptivecards";
@@ -375,314 +467,359 @@ The following steps will be required to run Omnichannel Chat SDK on React Native
375
467
 
376
468
  ```
377
469
 
470
+ ### Post-Chat Survey
471
+
472
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-post-conversation-survey?tabs=customerserviceadmincenter on how to set up post-conversation surveys
473
+
474
+ > ❗ `chatSDK.getPostChatSurveyContext()` needs to be called before `chatSDK.endChat()` is called
475
+
476
+ ```ts
477
+ // 1. Start chat
478
+ await chatSDK.startChat();
479
+
480
+ // 2. Save post chat survey context before ending chat
481
+ try {
482
+ const context = await chatSDK.getPostChatSurveyContext();
483
+ if (context.participantJoined) { // participantJoined will be true if an agent has joined the conversation, or a bot has joined the conversation and the bot survey flag has been turned on on the admin side.
484
+ // formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
485
+ // If "&lang=" is not set on the url, the locale will be English.
486
+ const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
487
+ // This link is accessible and will redirect to the survey page. Use it as you see fit.
488
+ }
489
+ } catch (ex) {
490
+ // If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
491
+ }
492
+
493
+ // 3. End chat
494
+ await chatSDK.endChat();
495
+
496
+ // 4. Display Post Chat
497
+ ```
498
+
378
499
  ### Reconnect to existing Chat
379
500
 
380
501
  ```ts
381
- await chatSDK.startChat(); // Starts NEW chat
502
+ await chatSDK.startChat(); // Starts NEW chat
382
503
 
383
- const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
504
+ const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
384
505
 
385
- cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
506
+ cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
386
507
 
387
- ...
508
+ ...
388
509
 
389
- // Page/component reloads, ALL previous states are GONE
510
+ // Page/component reloads, ALL previous states are GONE
390
511
 
391
- ...
512
+ ...
392
513
 
393
- const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
514
+ const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
394
515
 
395
- const optionalParams = {};
396
- optionalParams.liveChatContext = liveChatContext;
516
+ const optionalParams = {};
517
+ optionalParams.liveChatContext = liveChatContext;
397
518
 
398
- await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
519
+ await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
399
520
 
400
- ...
521
+ ...
401
522
 
402
- const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
403
- messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
523
+ const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
524
+ messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
404
525
  ```
405
526
 
406
527
  ### Authenticated Chat
407
528
 
408
- ```ts
409
- // add if using against an authenticated chat endpoint
410
- // see https://docs.microsoft.com/en-us/dynamics365/omnichannel/administrator/create-chat-auth-settings on how to set up an authenticated chat widget
529
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-chat-auth-settings?tabs=customerserviceadmincenter#create-a-chat-authentication-setting-record on how to set up an authenticated chat
411
530
 
412
- const chatSDKConfig = {
413
- getAuthToken: async () => {
414
- const response = await fetch("http://contosohelp.com/token");
415
- if (response.ok) {
416
- return await response.text();
417
- }
418
- else {
419
- return null
420
- }
531
+ ```ts
532
+ const chatSDKConfig = {
533
+ getAuthToken: async () => {
534
+ const response = await fetch("http://contosohelp.com/token");
535
+ if (response.ok) {
536
+ return await response.text();
537
+ }
538
+ else {
539
+ return null
421
540
  }
422
541
  }
542
+ }
423
543
 
424
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
425
- await chatSDK.initialize();
544
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
545
+ await chatSDK.initialize();
426
546
 
427
- // from this point, this acts like a regular chat widget
547
+ // from this point, this acts like a regular chat widget
428
548
  ```
429
549
 
430
550
  ### Persistent Chat
431
551
 
552
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/persistent-chat on how to set up persistent chat
553
+
432
554
  ```ts
433
- const chatSDKConfig = {
434
- persistentChat: {
435
- disable: false,
436
- tokenUpdateTime: 21600000
437
- },
438
- getAuthToken: async () => {
439
- const response = await fetch("http://contosohelp.com/token");
440
- if (response.ok) {
441
- return await response.text();
442
- }
443
- else {
444
- return null
445
- }
555
+ const chatSDKConfig = {
556
+ persistentChat: {
557
+ disable: false,
558
+ tokenUpdateTime: 21600000
559
+ },
560
+ getAuthToken: async () => {
561
+ const response = await fetch("http://contosohelp.com/token");
562
+ if (response.ok) {
563
+ return await response.text();
564
+ }
565
+ else {
566
+ return null
446
567
  }
447
568
  }
569
+ }
448
570
 
449
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
450
- await chatSDK.initialize();
571
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
572
+ await chatSDK.initialize();
451
573
 
452
- // from this point, this acts like a persistent chat
574
+ // from this point, this acts like a persistent chat
453
575
  ```
454
576
  ### Chat Reconnect with Authenticated User
455
577
 
578
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session on how to set up chat reconnect
579
+
456
580
  ```ts
457
- const chatSDKConfig = {
458
- chatReconnect: {
459
- disable: false,
460
- },
461
- getAuthToken: async () => {
462
- const response = await fetch("http://contosohelp.com/token");
463
- if (response.ok) {
464
- return await response.text();
465
- }
466
- else {
467
- return null
468
- }
581
+ const chatSDKConfig = {
582
+ chatReconnect: {
583
+ disable: false,
584
+ },
585
+ getAuthToken: async () => {
586
+ const response = await fetch("http://contosohelp.com/token");
587
+ if (response.ok) {
588
+ return await response.text();
589
+ }
590
+ else {
591
+ return null
469
592
  }
470
593
  }
594
+ }
471
595
 
472
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
473
- await chatSDK.initialize();
596
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
597
+ await chatSDK.initialize();
474
598
 
475
- ...
599
+ ...
476
600
 
477
- const chatReconnectContext = await chatSDK.getChatReconnectContext();
601
+ const chatReconnectContext = await chatSDK.getChatReconnectContext();
478
602
 
479
- if (chatReconnectContext.reconnectId) {
480
- // Add UX with options to reconnect to previous existing chat or start new chat
481
- }
603
+ if (chatReconnectContext.reconnectId) {
604
+ // Add UX with options to reconnect to previous existing chat or start new chat
605
+ }
482
606
 
483
- // Reconnect chat option
484
- const optionalParams = {};
485
- optionalParams.reconnectId = chatReconnectContext.reconnectId;
486
- chatSDK.startChat(optionalParams);
607
+ // Reconnect chat option
608
+ const optionalParams = {};
609
+ optionalParams.reconnectId = chatReconnectContext.reconnectId;
610
+ chatSDK.startChat(optionalParams);
487
611
 
488
- // Start new chat option
489
- chatSDK.startChat();
612
+ // Start new chat option
613
+ chatSDK.startChat();
490
614
  ```
491
615
 
492
616
  ### Chat Reconnect with Unauthenticated User
493
617
 
618
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session on how to set up chat reconnect
619
+
494
620
  ```ts
495
- const chatSDKConfig = {
496
- chatReconnect: {
497
- disable: false,
498
- },
499
- }
621
+ const chatSDKConfig = {
622
+ chatReconnect: {
623
+ disable: false,
624
+ },
625
+ }
500
626
 
501
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
502
- await chatSDK.initialize();
627
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
628
+ await chatSDK.initialize();
503
629
 
504
- ....
630
+ ....
505
631
 
506
- const optionalParams: any = {};
632
+ const optionalParams: any = {};
507
633
 
508
- // Retrieve reconnect id from the URL
509
- const urlParams = new URLSearchParams(window.location.search);
510
- const reconnectId = urlParams.get('oc.reconnectid');
634
+ // Retrieve reconnect id from the URL
635
+ const urlParams = new URLSearchParams(window.location.search);
636
+ const reconnectId = urlParams.get('oc.reconnectid');
511
637
 
512
- const params = {
513
- reconnectId
514
- };
638
+ const params = {
639
+ reconnectId
640
+ };
515
641
 
516
- // Validate reconnect id
517
- const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
642
+ // Validate reconnect id
643
+ const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
518
644
 
519
- // If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
520
- if (chatReconnectContext.redirectURL) {
521
- window.location.replace(chatReconnectContext.redirectURL);
522
- }
645
+ // If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
646
+ if (chatReconnectContext.redirectURL) {
647
+ window.location.replace(chatReconnectContext.redirectURL);
648
+ }
523
649
 
524
- // Valid reconnect id, reconnect to previous chat
525
- if (chatReconnectContext.reconnectId) {
526
- await chatSDK.startChat({
527
- reconnectId: chatReconnectContext.reconnectId
528
- });
529
- } else { // Reconnect id from URL is not valid, start new chat session
530
- await chatSDK.startChat();
531
- }
650
+ // Valid reconnect id, reconnect to previous chat
651
+ if (chatReconnectContext.reconnectId) {
652
+ await chatSDK.startChat({
653
+ reconnectId: chatReconnectContext.reconnectId
654
+ });
655
+ } else { // Reconnect id from URL is not valid, start new chat session
656
+ await chatSDK.startChat();
657
+ }
532
658
  ```
533
659
 
534
660
  ### Operating Hours
535
661
 
662
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-operating-hours?tabs=customerserviceadmincenter on how to set up operating hours
663
+
536
664
  ```ts
537
- const chatConfig = await chatSDK.getLiveChatConfig();
538
- const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
539
- const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
665
+ const chatConfig = await chatSDK.getLiveChatConfig();
666
+ const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
667
+ const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
540
668
 
541
- if (outOfOperatingHours === "True") {
542
- // Handles UX on Out of Operating Hours
543
- } else {
544
- await chatSDK.startChat();
545
- // Renders Custom Chat Widget
546
- }
669
+ if (outOfOperatingHours === "True") {
670
+ // Handles UX on Out of Operating Hours
671
+ } else {
672
+ await chatSDK.startChat();
673
+ // Renders Custom Chat Widget
674
+ }
547
675
  ```
548
676
 
549
- ### Use [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
677
+ ### Using [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
678
+ > :warning: Currently supported on web only
550
679
 
551
- **NOTE**: Currently supported on web only
552
- ```ts
553
- import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
554
- import ReactWebChat from 'botframework-webchat';
555
-
556
- ...
680
+ Minimum Requirement Checklist
681
+ 1. [ ] Initialize ChatSDK
682
+ 1. [ ] Start new conversation
683
+ 1. [ ] Create Chat Adapter
684
+ 1. [ ] Create WebChat store with default middlewares
685
+ 1. [ ] Send Default Channel Message Tags using Store Middleware (See [here](/docs//DEVELOPMENT_GUIDE.md#send-default-channel-message-tags-using-store-middleware)) ❗ Required
686
+ 1. [ ] Render WebChat
557
687
 
558
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
559
- await chatSDK.initialize();
688
+ ```ts
689
+ import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
690
+ import ReactWebChat, {createStore} from 'botframework-webchat';
560
691
 
561
- const optionalParams = {
562
- preChatResponse: '' // PreChatSurvey response
563
- };
692
+ // 1. ChatSDK Initialization
693
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig);
694
+ await chatSDK.initialize();
564
695
 
565
- await chatSDK.startChat(optionalParams);
566
- const chatAdapter = await chatSDK.createChatAdapter();
696
+ // 2. Start new conversation
697
+ await chatSDK.startChat();
567
698
 
568
- // Subscribes to incoming message
569
- chatSDK.onNewMessage((message) => {
570
- console.log(`[NewMessage] ${message.content}`); // IC3 protocol message data
571
- console.log(message);
572
- });
699
+ // 3. Create chat adapter
700
+ const chatAdapter = await chatSDK.createChatAdapter();
573
701
 
574
- ...
702
+ // 4. Create WebChat store with middlewares
703
+ const store = createStore(
704
+ {}, // initial state
705
+ sendDefaultMessagingTagsMiddleware // ❗ Required
706
+ );
575
707
 
576
- <ReactWebChat
577
- userID="teamsvisitor"
578
- directLine={chatAdapter}
579
- sendTypingIndicator={true}
580
- />
708
+ // 5. Render WebChat
709
+ <ReactWebChat
710
+ store={store}
711
+ userID="teamsvisitor"
712
+ directLine={chatAdapter}
713
+ sendTypingIndicator={true}
714
+ />
581
715
  ```
582
716
 
583
717
  ### Escalation to Voice & Video
584
- **NOTE**: Currently supported on web only
718
+ > :warning: Currently supported on web only
719
+
720
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/call-options-visual-engagement on how to set up calling options
721
+
585
722
  ```ts
586
- import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
723
+ import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
587
724
 
588
- ...
725
+ ...
589
726
 
590
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
591
- await chatSDK.initialize();
727
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
728
+ await chatSDK.initialize();
592
729
 
593
- let VoiceVideoCallingSDK;
594
- try {
595
- VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
596
- console.log("VoiceVideoCalling loaded");
597
- } catch (e) {
598
- console.log(`Failed to load VoiceVideoCalling: ${e}`);
730
+ let VoiceVideoCallingSDK;
731
+ try {
732
+ VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
733
+ console.log("VoiceVideoCalling loaded");
734
+ } catch (e) {
735
+ console.log(`Failed to load VoiceVideoCalling: ${e}`);
599
736
 
600
- if (e.message === 'UnsupportedPlatform') {
601
- // Voice Video Calling feature is not supported on this platform
602
- }
737
+ if (e.message === 'UnsupportedPlatform') {
738
+ // Voice Video Calling feature is not supported on this platform
739
+ }
603
740
 
604
- if (e.message === 'FeatureDisabled') {
605
- // Voice Video Calling feature is disabled on admin side
606
- }
741
+ if (e.message === 'FeatureDisabled') {
742
+ // Voice Video Calling feature is disabled on admin side
607
743
  }
744
+ }
608
745
 
609
- await chatSDK.startChat();
746
+ await chatSDK.startChat();
610
747
 
611
- const chatToken: any = await chatSDK.getChatToken();
612
-
613
- // Initialize only if VoiceVideoCallingSDK is defined
614
- if (VoiceVideoCallingSDK) {
615
- try {
616
- await VoiceVideoCallingSDK.initialize({
617
- chatToken,
618
- selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
619
- remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
620
- OCClient: chatSDK.OCClient
621
- });
622
- } catch (e) {
623
- console.error("Failed to initialize VoiceVideoCalling!");
624
- }
748
+ const chatToken: any = await chatSDK.getChatToken();
625
749
 
626
- // Triggered when there's an incoming call
627
- VoiceVideoCallingSDK.onCallAdded(() => {
628
- ...
750
+ // Initialize only if VoiceVideoCallingSDK is defined
751
+ if (VoiceVideoCallingSDK) {
752
+ try {
753
+ await VoiceVideoCallingSDK.initialize({
754
+ chatToken,
755
+ selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
756
+ remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
757
+ OCClient: chatSDK.OCClient
629
758
  });
759
+ } catch (e) {
760
+ console.error("Failed to initialize VoiceVideoCalling!");
761
+ }
630
762
 
631
- // Triggered when local video stream is available (e.g.: Local video added succesfully in selfVideoHTMLElement)
632
- VoiceVideoCallingSDK.onLocalVideoStreamAdded(() => {
633
- ...
634
- });
763
+ // Triggered when there's an incoming call
764
+ VoiceVideoCallingSDK.onCallAdded(() => {
765
+ ...
766
+ });
635
767
 
636
- // Triggered when local video stream is unavailable (e.g.: Customer turning off local video)
637
- VoiceVideoCallingSDK.onLocalVideoStreamRemoved(() => {
638
- ...
639
- });
768
+ // Triggered when local video stream is available (e.g.: Local video added succesfully in selfVideoHTMLElement)
769
+ VoiceVideoCallingSDK.onLocalVideoStreamAdded(() => {
770
+ ...
771
+ });
640
772
 
641
- // Triggered when remote video stream is available (e.g.: Remote video added succesfully in remoteVideoHTMLElement)
642
- VoiceVideoCallingSDK.onRemoteVideoStreamAdded(() => {
643
- ...
644
- });
773
+ // Triggered when local video stream is unavailable (e.g.: Customer turning off local video)
774
+ VoiceVideoCallingSDK.onLocalVideoStreamRemoved(() => {
775
+ ...
776
+ });
645
777
 
646
- // Triggered when remote video stream is unavailable (e.g.: Agent turning off remote video)
647
- VoiceVideoCallingSDK.onRemoteVideoStreamRemoved(() => {
648
- ...
649
- });
778
+ // Triggered when remote video stream is available (e.g.: Remote video added succesfully in remoteVideoHTMLElement)
779
+ VoiceVideoCallingSDK.onRemoteVideoStreamAdded(() => {
780
+ ...
781
+ });
650
782
 
651
- // Triggered when current call has ended or disconnected regardless the party
652
- VoiceVideoCalling.onCallDisconnected(() => {
653
- ...
654
- });
783
+ // Triggered when remote video stream is unavailable (e.g.: Agent turning off remote video)
784
+ VoiceVideoCallingSDK.onRemoteVideoStreamRemoved(() => {
785
+ ...
786
+ });
655
787
 
656
- // Check if microphone is muted
657
- const isMicrophoneMuted = VoiceVideoCallingSDK.isMicrophoneMuted();
788
+ // Triggered when current call has ended or disconnected regardless the party
789
+ VoiceVideoCalling.onCallDisconnected(() => {
790
+ ...
791
+ });
658
792
 
659
- // Check if remote video is available
660
- const isRemoteVideoEnabled = VoiceVideoCallingSDK.isRemoteVideoEnabled();
793
+ // Check if microphone is muted
794
+ const isMicrophoneMuted = VoiceVideoCallingSDK.isMicrophoneMuted();
661
795
 
662
- // Check if local video is available
663
- const isLocalVideoEnabled = VoiceVideoCallingSDK.isLocalVideoEnabled();
796
+ // Check if remote video is available
797
+ const isRemoteVideoEnabled = VoiceVideoCallingSDK.isRemoteVideoEnabled();
664
798
 
665
- // Accepts incoming call
666
- const acceptCallConfig = {
667
- withVideo: true // Accept call with/without video stream
668
- };
669
- await VoiceVideoCallingSDK.acceptCall(acceptCallConfig);
799
+ // Check if local video is available
800
+ const isLocalVideoEnabled = VoiceVideoCallingSDK.isLocalVideoEnabled();
670
801
 
671
- // Rejects incoming call
672
- await VoiceVideoCallingSDK.rejectCall();
802
+ // Accepts incoming call
803
+ const acceptCallConfig = {
804
+ withVideo: true // Accept call with/without video stream
805
+ };
806
+ await VoiceVideoCallingSDK.acceptCall(acceptCallConfig);
673
807
 
674
- // Ends/Stops current call
675
- await VoiceVideoCallingSDK.stopCall();
808
+ // Rejects incoming call
809
+ await VoiceVideoCallingSDK.rejectCall();
676
810
 
677
- // Mute/Unmute current call
678
- await VoiceVideoCallingSDK.toggleMute()
811
+ // Ends/Stops current call
812
+ await VoiceVideoCallingSDK.stopCall();
679
813
 
680
- // Display/Hide local video of current call
681
- await VoiceVideoCallingSDK.toggleLocalVideo()
814
+ // Mute/Unmute current call
815
+ await VoiceVideoCallingSDK.toggleMute()
682
816
 
683
- // Clean up VoiceVideoCallingSDK (e.g.: Usually called when customer ends chat session)
684
- VoiceVideoCallingSDK.close();
685
- }
817
+ // Display/Hide local video of current call
818
+ await VoiceVideoCallingSDK.toggleLocalVideo()
819
+
820
+ // Clean up VoiceVideoCallingSDK (e.g.: Usually called when customer ends chat session)
821
+ VoiceVideoCallingSDK.close();
822
+ }
686
823
  ```
687
824
 
688
825
  ## Feature Comparisons
@@ -727,20 +864,20 @@ Some of the data being collected are the following:
727
864
  If your organization is concerned about the data collected by the Chat SDK, you have the option to turn off automatic data collection by adding a flag in the `ChatSDKConfig`.
728
865
 
729
866
  ```ts
730
- const omnichannelConfig = {
731
- orgUrl: "",
732
- orgId: "",
733
- widgetId: ""
734
- };
867
+ const omnichannelConfig = {
868
+ orgUrl: "",
869
+ orgId: "",
870
+ widgetId: ""
871
+ };
735
872
 
736
- const chatSDKConfig = {
737
- telemetry: {
738
- disable: true // Disable telemetry
739
- }
740
- };
873
+ const chatSDKConfig = {
874
+ telemetry: {
875
+ disable: true // Disable telemetry
876
+ }
877
+ };
741
878
 
742
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
743
- await chatSDK.initialize();
879
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
880
+ await chatSDK.initialize();
744
881
  ```
745
882
 
746
883
  # Contributing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.1.1-main.502460d",
4
4
  "description": "Microsoft Omnichannel Chat SDK",
5
5
  "files": [
6
6
  "lib/**/*"