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