@microsoft/omnichannel-chat-sdk 1.1.1-main.131f36d → 1.1.1-main.3ce5a59

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