@microsoft/omnichannel-chat-sdk 1.0.1-main.fa78d5f → 1.1.1-main.063303c

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 (73) hide show
  1. package/CHANGELOG.md +36 -4
  2. package/README.md +482 -306
  3. package/lib/OmnichannelChatSDK.d.ts +10 -6
  4. package/lib/OmnichannelChatSDK.js +379 -317
  5. package/lib/OmnichannelChatSDK.js.map +1 -1
  6. package/lib/api/createVoiceVideoCalling.js +6 -2
  7. package/lib/api/createVoiceVideoCalling.js.map +1 -1
  8. package/lib/config/settings.d.ts +1 -1
  9. package/lib/config/settings.js +1 -1
  10. package/lib/core/ChatConfig.d.ts +4 -0
  11. package/lib/core/ChatSDKExceptionDetails.d.ts +5 -0
  12. package/lib/core/ChatSDKExceptionDetails.js +3 -0
  13. package/lib/core/ChatSDKExceptionDetails.js.map +1 -0
  14. package/lib/core/ChatTranscriptBody.d.ts +1 -1
  15. package/lib/core/GetLiveChatConfigOptionalParams.d.ts +5 -0
  16. package/lib/core/GetLiveChatConfigOptionalParams.js +3 -0
  17. package/lib/core/GetLiveChatConfigOptionalParams.js.map +1 -0
  18. package/lib/core/InitializeOptionalParams.d.ts +5 -0
  19. package/lib/core/InitializeOptionalParams.js +3 -0
  20. package/lib/core/InitializeOptionalParams.js.map +1 -0
  21. package/lib/core/LiveWorkItemDetails.d.ts +2 -0
  22. package/lib/core/OmnichannelErrorCodes.d.ts +4 -0
  23. package/lib/core/OmnichannelErrorCodes.js +8 -0
  24. package/lib/core/OmnichannelErrorCodes.js.map +1 -0
  25. package/lib/core/PostChatContext.d.ts +1 -0
  26. package/lib/core/StartChatOptionalParams.d.ts +1 -0
  27. package/lib/core/messaging/ACSClient.d.ts +1 -0
  28. package/lib/core/messaging/ACSClient.js +3 -0
  29. package/lib/core/messaging/ACSClient.js.map +1 -1
  30. package/lib/core/messaging/ChatAdapterOptionalParams.d.ts +14 -0
  31. package/lib/core/messaging/ChatAdapterOptionalParams.js +3 -0
  32. package/lib/core/messaging/ChatAdapterOptionalParams.js.map +1 -0
  33. package/lib/core/messaging/MessageTags.d.ts +2 -0
  34. package/lib/core/messaging/MessageTags.js +4 -2
  35. package/lib/core/messaging/MessageTags.js.map +1 -1
  36. package/lib/external/ACSAdapter/AMSFileManager.js +12 -0
  37. package/lib/external/ACSAdapter/AMSFileManager.js.map +1 -1
  38. package/lib/external/ACSAdapter/createChannelDataEgressMiddleware.d.ts +5 -0
  39. package/lib/external/ACSAdapter/createChannelDataEgressMiddleware.js +34 -0
  40. package/lib/external/ACSAdapter/createChannelDataEgressMiddleware.js.map +1 -0
  41. package/lib/external/CallingSDK/ICallingSDKLogData.d.ts +7 -0
  42. package/lib/external/CallingSDK/ICallingSDKLogData.js +3 -0
  43. package/lib/external/CallingSDK/ICallingSDKLogData.js.map +1 -0
  44. package/lib/external/IC3Adapter/IIC3AdapterOptions.d.ts +12 -0
  45. package/lib/index.d.ts +7 -6
  46. package/lib/index.js +13 -8
  47. package/lib/index.js.map +1 -1
  48. package/lib/telemetry/AriaTelemetry.d.ts +1 -0
  49. package/lib/telemetry/AriaTelemetry.js +55 -0
  50. package/lib/telemetry/AriaTelemetry.js.map +1 -1
  51. package/lib/telemetry/ScenarioMarker.d.ts +2 -0
  52. package/lib/telemetry/ScenarioMarker.js +7 -3
  53. package/lib/telemetry/ScenarioMarker.js.map +1 -1
  54. package/lib/telemetry/ScenarioType.d.ts +1 -0
  55. package/lib/telemetry/ScenarioType.js +1 -0
  56. package/lib/telemetry/ScenarioType.js.map +1 -1
  57. package/lib/telemetry/TelemetryEvent.d.ts +1 -3
  58. package/lib/telemetry/TelemetryEvent.js +0 -2
  59. package/lib/telemetry/TelemetryEvent.js.map +1 -1
  60. package/lib/tsconfig.tsbuildinfo +203 -76
  61. package/lib/utils/WebUtils.d.ts +3 -1
  62. package/lib/utils/WebUtils.js +8 -2
  63. package/lib/utils/WebUtils.js.map +1 -1
  64. package/lib/utils/libraries.d.ts +1 -3
  65. package/lib/utils/libraries.js +2 -11
  66. package/lib/utils/libraries.js.map +1 -1
  67. package/lib/utils/locale.d.ts +2 -0
  68. package/lib/utils/locale.js +5 -3
  69. package/lib/utils/locale.js.map +1 -1
  70. package/lib/utils/loggers.d.ts +26 -1
  71. package/lib/utils/loggers.js +94 -2
  72. package/lib/utils/loggers.js.map +1 -1
  73. package/package.json +2 -2
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
@@ -40,7 +79,7 @@ Omnichannel offers an live chat widget (LCW) by default. You can use the Chat SD
40
79
  | Screen Sharing | ✔ | 3rd party add-on | Only supported on Web |
41
80
  | Authenticated Chat | ✔ | ✔ |
42
81
  | Pre-chat Survey | ✔ | ✔ |
43
- | Post-chat Survey | ✔ | |
82
+ | Post-chat Survey | ✔ | |
44
83
  | Download Transcript | ✔ | ✔ |
45
84
  | Email Transcript | ✔ | ✔ |
46
85
  | Data Masking | ✔ | ✔ |
@@ -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,228 +145,309 @@ 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 IC3Adapter | **Web only** |
135
- | OmnichannelChatSDK.getVoiceVideoCalling() | Get VoiceVideoCall SDK for Escalation to Voice & Video | **Web only** |
136
-
137
- ## API examples
138
-
139
- ### Import
140
- ```ts
141
- import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
142
- ```
148
+ ## SDK Methods
143
149
 
144
150
  ### Initialization
151
+
152
+ It handles the initialization of ChatSDK internal data.
153
+
145
154
  ```ts
146
- const omnichannelConfig = {
147
- orgUrl: "",
148
- orgId: "",
149
- widgetId: ""
150
- };
155
+ import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
151
156
 
152
- const chatSDKConfig = { // Optional
153
- dataMasking: {
154
- disable: false,
155
- maskingCharacter: '#'
156
- }
157
- };
157
+ const omnichannelConfig = {
158
+ orgUrl: "",
159
+ orgId: "",
160
+ widgetId: ""
161
+ };
158
162
 
159
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
160
- await chatSDK.initialize();
161
- ```
163
+ const chatSDKConfig = { // Optional
164
+ dataMasking: {
165
+ disable: false,
166
+ maskingCharacter: '#'
167
+ }
168
+ };
162
169
 
163
- ### Get Current Live Chat Context
164
- ```ts
165
- const liveChatContext = await chatSDK.getCurrentLiveChatContext();
170
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
171
+
172
+ const optionalParams = {
173
+ getLiveChatConfigOptionalParams: {
174
+ sendCacheHeaders: false // Whether to send Cache-Control HTTP header to GetChatConfig call
175
+ }
176
+ };
177
+
178
+ await chatSDK.initialize(optionalParams);
166
179
  ```
167
180
 
168
- ### Get Current Chat Reconnect Context
181
+ ### Start Chat
182
+
183
+ It starts an Omnichannel conversation.
184
+
169
185
  ```ts
170
- const optionalParams = {
171
- reconnectId: '', // reconnect Id
172
- };
186
+ const customContext = {
187
+ 'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
188
+ 'contextKey2': {'value': 12.34, 'isDisplayable': false},
189
+ 'contextKey3': {'value': true}
190
+ };
191
+
192
+ const optionalParams = {
193
+ preChatResponse: '', // PreChatSurvey response
194
+ liveChatContext: {}, // EXISTING chat context data
195
+ customContext, // Custom Context
196
+ sendDefaultInitContext: true // Send default init context ⚠️ Web only
197
+ };
173
198
 
174
- const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
199
+ await chatSDK.startChat(optionalParams);
175
200
  ```
176
201
 
177
- ### Get Conversation Details
202
+ ### End Chat
203
+
204
+ It ends the current Omnichannel conversation.
205
+
178
206
  ```ts
179
- const conversationDetails = await chatSDK.getConversationDetails();
207
+ await chatSDK.endChat();
180
208
  ```
181
209
 
182
- ### Get Chat Token
210
+ ### Get Pre-Chat Survey
211
+
212
+ It gets the Pre-Chat Survey from Live Chat Config. Pre-Chat Survey is in Adaptive Card format.
213
+
214
+ `Option 1`
183
215
  ```ts
184
- const chatToken = await chatSDK.getChatToken();
216
+ const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
185
217
  ```
186
-
187
- ### Get Calling Token
218
+ `Option 2`
188
219
  ```ts
189
- const callingToken = await chatSDK.getCallingToken();
220
+ const parseToJSON = false;
221
+ const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
190
222
  ```
191
223
 
192
224
  ### Get Live Chat Config
225
+
226
+ It fetches the Live Chat Config.
227
+
193
228
  ```ts
194
- const liveChatConfig = await chatSDK.getLiveChatConfig();
229
+ const liveChatConfig = await chatSDK.getLiveChatConfig();
230
+ ```
231
+
232
+ ### Get Current Live Chat Context
233
+
234
+ It gets the current live chat context information to be used to reconnect to the same conversation.
235
+
236
+ ```ts
237
+ const liveChatContext = await chatSDK.getCurrentLiveChatContext();
195
238
  ```
196
239
 
197
240
  ### Get Data Masking Rules
241
+
242
+ It gets the active data masking rules from Live Chat Config.
243
+
198
244
  ```ts
199
- const dataMaskingRules = await chatSDK.getDataMaskingRules();
245
+ const dataMaskingRules = await chatSDK.getDataMaskingRules();
200
246
  ```
201
247
 
202
- ### Get PreChat Survey
203
- `Option 1`
248
+ ### Get Chat Reconnect Context
249
+
250
+ It gets the current reconnectable chat context information to connect to a previous existing chat session.
251
+
252
+ `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)
253
+
204
254
  ```ts
205
- const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
255
+ const optionalParams = {
256
+ reconnectId: '', // reconnect Id
257
+ };
258
+
259
+ const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
206
260
  ```
207
- `Option 2`
261
+
262
+ ### Get Conversation Details
263
+
264
+ It gets the details of the current conversation such as its state & when the agent joined the conversation.
265
+
208
266
  ```ts
209
- const parseToJSON = false;
210
- const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
267
+ const conversationDetails = await chatSDK.getConversationDetails();
211
268
  ```
212
269
 
213
- ### Start Chat
270
+ ### Get chat Token
271
+
272
+ It gets the chat token used to initiates a chat with Omnichannel messaging client.
273
+
214
274
  ```ts
215
- const customContext = {
216
- 'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
217
- 'contextKey2': {'value': 12.34, 'isDisplayable': false},
218
- 'contextKey3': {'value': true}
219
- };
275
+ const chatToken = await chatSDK.getChatToken();
276
+ ```
220
277
 
221
- const optionalParams = {
222
- preChatResponse: '', // PreChatSurvey response
223
- liveChatContext: {}, // EXISTING chat context data
224
- customContext // Custom Context
225
- };
226
- await chatSDK.startChat(optionalParams);
278
+ ### Get Calling Token
279
+
280
+ It gets the calling token used to initiates a Voice & Video Call.
281
+
282
+ ```ts
283
+ const callingToken = await chatSDK.getCallingToken();
227
284
  ```
228
285
 
229
- ### End Chat
286
+ ### Get Messages
287
+
288
+ It gets all the messages of the current conversation.
289
+
230
290
  ```ts
231
- await chatSDK.endChat();
291
+ const messages = await chatSDK.getMessages();
232
292
  ```
233
293
 
234
- ### On New Message Handler
294
+ ### Send Messages
295
+
296
+ It sends a message to Omnichannel.
297
+
235
298
  ```ts
236
- const optionalParams = {
237
- rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
238
- }
299
+ import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
239
300
 
240
- chatSDK.onNewMessage((message) => {
241
- console.log(`[NewMessage] ${message.content}`); // IC3 protocol message data
242
- console.log(message);
243
- }, optionalParams);
301
+ ...
302
+
303
+ const displayName = "Contoso"
304
+ const message = "Sample message from customer";
305
+ const messageToSend = {
306
+ content: message
307
+ };
308
+
309
+ await chatSDK.sendMessage(messageToSend);
244
310
  ```
245
311
 
246
- ### On Agent End Session
312
+ ### On New Message
313
+
314
+ It subscribes to new incoming messages of the current conversation such as system messages, client messages, agent messages, adaptive cards and attachments.
315
+
247
316
  ```ts
248
- chatSDK.onAgentEndSession(() => {
249
- console.log("Session ended!");
250
- });
251
- ```
317
+ const optionalParams = {
318
+ rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
319
+ }
252
320
 
321
+ chatSDK.onNewMessage((message) => {
322
+ console.log(`[NewMessage] ${message.content}`);
323
+ console.log(message);
324
+ }, optionalParams);
325
+ ```
253
326
  ### On Typing Event
327
+
328
+ It subscribes to agent typing event.
329
+
254
330
  ```ts
255
- chatSDK.onTypingEvent(() => {
256
- console.log("Agent is typing...");
257
- })
331
+ chatSDK.onTypingEvent(() => {
332
+ console.log("Agent is typing...");
333
+ })
258
334
  ```
259
335
 
260
- ### Get Messages
336
+ ### On Agent End Session
337
+
338
+ It subscribes to agent ending the session of the conversation.
339
+
261
340
  ```ts
262
- const messages = await chatSDK.getMessages();
341
+ chatSDK.onAgentEndSession(() => {
342
+ console.log("Session ended!");
343
+ });
263
344
  ```
264
345
 
265
- ### Send Message
346
+ ### Send Typing Event
347
+
348
+ It sends a customer typing event.
349
+
266
350
  ```ts
267
- import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
351
+ await chatSDK.sendTypingEvent();
352
+ ```
268
353
 
269
- ...
354
+ ### Email Live Chat Transcript
270
355
 
271
- const displayName = "Contoso"
272
- const message = "Sample message from customer";
273
- const messageToSend = {
274
- content: message
275
- };
356
+ It sends an email of the live chat transcript.
276
357
 
277
- await chatSDK.sendMessage(messageToSend);
358
+ ```ts
359
+ const body = {
360
+ emailAddress: 'contoso@microsoft.com',
361
+ attachmentMessage: 'Attachment Message'
362
+ };
363
+ await chatSDK.emailLiveChatTranscript(body);
278
364
  ```
279
365
 
280
- ### Send Typing
366
+ ### Get Live Chat Transcript
367
+
368
+ It fetches the current conversation transcript data in JSON.
369
+
281
370
  ```ts
282
- await chatSDK.sendTypingEvent();
371
+ await chatSDK.getLiveChatTranscript();
283
372
  ```
284
373
 
285
- ### Upload Attachment
374
+ ### Upload File Attachment
375
+
376
+ It sends a file attachment to the current conversation.
377
+
286
378
  ```ts
287
- const fileInfo = {
288
- name: '',
289
- type: '',
290
- size: '',
291
- data: ''
292
- };
293
- await chatSDK.uploadFileAttachment(fileInfo);
379
+ const fileInfo = {
380
+ name: '',
381
+ type: '',
382
+ size: '',
383
+ data: ''
384
+ };
385
+ await chatSDK.uploadFileAttachment(fileInfo);
294
386
  ```
295
387
 
296
- ### Download Attachment
388
+ ### Download File Attachment
389
+
390
+ It downloads the file attachment of the incoming message as a Blob response.
391
+
297
392
  ```ts
298
- const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
393
+ const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
299
394
 
300
- ...
395
+ ...
301
396
 
302
- // React Native implementation
303
- const fileReaderInstance = new FileReader();
304
- fileReaderInstance.readAsDataURL(blobResponse);
305
- fileReaderInstance.onload = () => {
306
- const base64data = fileReaderInstance.result;
307
- return <Image source={{uri: base64data}}/>
308
- }
397
+ // React Native implementation
398
+ const fileReaderInstance = new FileReader();
399
+ fileReaderInstance.readAsDataURL(blobResponse);
400
+ fileReaderInstance.onload = () => {
401
+ const base64data = fileReaderInstance.result;
402
+ return <Image source={{uri: base64data}}/>
403
+ }
309
404
  ```
310
405
 
311
- ### Get Live Chat Transcript
406
+ ### Create Chat Adapter
407
+
408
+ > :warning: Currently supported on web only
409
+
410
+ It creates a chat adapter to use with [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat).
312
411
 
313
412
  ```ts
314
- await chatSDK.getLiveChatTranscript();
413
+ const chatAdapter = await chatSDK.createChatAdapter();
315
414
  ```
316
415
 
317
- ### Email Live Chat Transcript
416
+ ### Get Voice & Video Calling
417
+
418
+ > :warning: Currently supported on web only
419
+
420
+ It fetches the SDK for Escalation to Voice & Video.
318
421
 
319
422
  ```ts
320
- const body = {
321
- emailAddress: 'contoso@microsoft.com',
322
- attachmentMessage: 'Attachment Message',
323
- locale: 'en-us'
324
- };
325
- await chatSDK.emailLiveChatTranscript(body);
423
+ try {
424
+ const VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
425
+ console.log("VoiceVideoCalling loaded");
426
+ } catch (e) {
427
+ console.log(`Failed to load VoiceVideoCalling: ${e}`);
428
+
429
+ if (e.message === 'UnsupportedPlatform') {
430
+ // Voice Video Calling feature is not supported on this platform
431
+ }
432
+
433
+ if (e.message === 'FeatureDisabled') {
434
+ // Voice Video Calling feature is disabled on admin side
435
+ }
436
+ }
437
+ ```
438
+ ### Get Post Chat Survey Context
439
+
440
+ It gets post chat survey link, survey locale, and whether an agent has joined the survey.
441
+
442
+ ```ts
443
+ const context = await chatSDK.getPostChatSurveyContext();
326
444
  ```
327
445
 
328
446
  ## Common Scenarios
329
447
 
330
- ### PreChatSurvey
448
+ ### Pre-Chat Survey
449
+
450
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-pre-chat-survey?tabs=customerserviceadmincenter on how to set up pre-conversation surveys
331
451
 
332
452
  ```ts
333
453
  import * as AdaptiveCards, { Action } from "adaptivecards";
@@ -360,233 +480,288 @@ The following steps will be required to run Omnichannel Chat SDK on React Native
360
480
 
361
481
  ```
362
482
 
483
+ ### Post-Chat Survey
484
+
485
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-post-conversation-survey?tabs=customerserviceadmincenter on how to set up post-conversation surveys
486
+
487
+ > ❗ `chatSDK.getPostChatSurveyContext()` needs to be called before `chatSDK.endChat()` is called
488
+
489
+ ```ts
490
+ // 1. Start chat
491
+ await chatSDK.startChat();
492
+
493
+ // 2. Save post chat survey context before ending chat
494
+ try {
495
+ const context = await chatSDK.getPostChatSurveyContext();
496
+ 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.
497
+ // formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
498
+ // If "&lang=" is not set on the url, the locale will be English.
499
+ const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
500
+ // This link is accessible and will redirect to the survey page. Use it as you see fit.
501
+ }
502
+ } catch (ex) {
503
+ // If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
504
+ }
505
+
506
+ // 3. End chat
507
+ await chatSDK.endChat();
508
+
509
+ // 4. Display Post Chat
510
+ ```
511
+
363
512
  ### Reconnect to existing Chat
364
513
 
365
514
  ```ts
366
- await chatSDK.startChat(); // Starts NEW chat
515
+ await chatSDK.startChat(); // Starts NEW chat
367
516
 
368
- const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
517
+ const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
369
518
 
370
- cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
519
+ cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
371
520
 
372
- ...
521
+ ...
373
522
 
374
- // Page/component reloads, ALL previous states are GONE
523
+ // Page/component reloads, ALL previous states are GONE
375
524
 
376
- ...
525
+ ...
377
526
 
378
- const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
527
+ const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
379
528
 
380
- const optionalParams = {};
381
- optionalParams.liveChatContext = liveChatContext;
529
+ const optionalParams = {};
530
+ optionalParams.liveChatContext = liveChatContext;
382
531
 
383
- await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
532
+ await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
384
533
 
385
- ...
534
+ ...
386
535
 
387
- const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
388
- messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
536
+ const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
537
+ messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
389
538
  ```
390
539
 
391
540
  ### Authenticated Chat
392
541
 
393
- ```ts
394
- // add if using against an authenticated chat endpoint
395
- // see https://docs.microsoft.com/en-us/dynamics365/omnichannel/administrator/create-chat-auth-settings on how to set up an authenticated chat widget
542
+ > 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
396
543
 
397
- const chatSDKConfig = {
398
- getAuthToken: async () => {
399
- const response = await fetch("http://contosohelp.com/token");
400
- if (response.ok) {
401
- return await response.text();
402
- }
403
- else {
404
- return null
405
- }
544
+ ```ts
545
+ const chatSDKConfig = {
546
+ getAuthToken: async () => {
547
+ const response = await fetch("http://contosohelp.com/token");
548
+ if (response.ok) {
549
+ return await response.text();
550
+ }
551
+ else {
552
+ return null
406
553
  }
407
554
  }
555
+ }
408
556
 
409
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
410
- await chatSDK.initialize();
557
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
558
+ await chatSDK.initialize();
411
559
 
412
- // from this point, this acts like a regular chat widget
560
+ // from this point, this acts like a regular chat widget
413
561
  ```
414
562
 
415
563
  ### Persistent Chat
416
564
 
565
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/persistent-chat on how to set up persistent chat
566
+
417
567
  ```ts
418
- const chatSDKConfig = {
419
- persistentChat: {
420
- disable: false,
421
- tokenUpdateTime: 21600000
422
- },
423
- getAuthToken: async () => {
424
- const response = await fetch("http://contosohelp.com/token");
425
- if (response.ok) {
426
- return await response.text();
427
- }
428
- else {
429
- return null
430
- }
568
+ const chatSDKConfig = {
569
+ persistentChat: {
570
+ disable: false,
571
+ tokenUpdateTime: 21600000
572
+ },
573
+ getAuthToken: async () => {
574
+ const response = await fetch("http://contosohelp.com/token");
575
+ if (response.ok) {
576
+ return await response.text();
577
+ }
578
+ else {
579
+ return null
431
580
  }
432
581
  }
582
+ }
433
583
 
434
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
435
- await chatSDK.initialize();
584
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
585
+ await chatSDK.initialize();
436
586
 
437
- // from this point, this acts like a persistent chat
587
+ // from this point, this acts like a persistent chat
438
588
  ```
439
589
  ### Chat Reconnect with Authenticated User
440
590
 
591
+ > 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
592
+
441
593
  ```ts
442
- const chatSDKConfig = {
443
- chatReconnect: {
444
- disable: false,
445
- },
446
- getAuthToken: async () => {
447
- const response = await fetch("http://contosohelp.com/token");
448
- if (response.ok) {
449
- return await response.text();
450
- }
451
- else {
452
- return null
453
- }
594
+ const chatSDKConfig = {
595
+ chatReconnect: {
596
+ disable: false,
597
+ },
598
+ getAuthToken: async () => {
599
+ const response = await fetch("http://contosohelp.com/token");
600
+ if (response.ok) {
601
+ return await response.text();
602
+ }
603
+ else {
604
+ return null
454
605
  }
455
606
  }
607
+ }
456
608
 
457
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
458
- await chatSDK.initialize();
609
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
610
+ await chatSDK.initialize();
459
611
 
460
- ...
612
+ ...
461
613
 
462
- const chatReconnectContext = await chatSDK.getChatReconnectContext();
614
+ const chatReconnectContext = await chatSDK.getChatReconnectContext();
463
615
 
464
- if (chatReconnectContext.reconnectId) {
465
- // Add UX with options to reconnect to previous existing chat or start new chat
466
- }
616
+ if (chatReconnectContext.reconnectId) {
617
+ // Add UX with options to reconnect to previous existing chat or start new chat
618
+ }
467
619
 
468
- // Reconnect chat option
469
- const optionalParams = {};
470
- optionalParams.reconnectId = chatReconnectContext.reconnectId;
471
- chatSDK.startChat(optionalParams);
620
+ // Reconnect chat option
621
+ const optionalParams = {};
622
+ optionalParams.reconnectId = chatReconnectContext.reconnectId;
623
+ chatSDK.startChat(optionalParams);
472
624
 
473
- // Start new chat option
474
- chatSDK.startChat();
625
+ // Start new chat option
626
+ chatSDK.startChat();
475
627
  ```
476
628
 
477
629
  ### Chat Reconnect with Unauthenticated User
478
630
 
631
+ > 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
632
+
479
633
  ```ts
480
- const chatSDKConfig = {
481
- chatReconnect: {
482
- disable: false,
483
- },
484
- }
634
+ const chatSDKConfig = {
635
+ chatReconnect: {
636
+ disable: false,
637
+ },
638
+ }
485
639
 
486
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
487
- await chatSDK.initialize();
640
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
641
+ await chatSDK.initialize();
488
642
 
489
- ....
643
+ ....
490
644
 
491
- const optionalParams: any = {};
645
+ const optionalParams: any = {};
492
646
 
493
- // Retrieve reconnect id from the URL
494
- const urlParams = new URLSearchParams(window.location.search);
495
- const reconnectId = urlParams.get('oc.reconnectid');
647
+ // Retrieve reconnect id from the URL
648
+ const urlParams = new URLSearchParams(window.location.search);
649
+ const reconnectId = urlParams.get('oc.reconnectid');
496
650
 
497
- const params = {
498
- reconnectId
499
- };
651
+ const params = {
652
+ reconnectId
653
+ };
500
654
 
501
- // Validate reconnect id
502
- const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
655
+ // Validate reconnect id
656
+ const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
503
657
 
504
- // If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
505
- if (chatReconnectContext.redirectURL) {
506
- window.location.replace(chatReconnectContext.redirectURL);
507
- }
658
+ // If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
659
+ if (chatReconnectContext.redirectURL) {
660
+ window.location.replace(chatReconnectContext.redirectURL);
661
+ }
508
662
 
509
- // Valid reconnect id, reconnect to previous chat
510
- if (chatReconnectContext.reconnectId) {
511
- await chatSDK.startChat({
512
- reconnectId: chatReconnectContext.reconnectId
513
- });
514
- } else { // Reconnect id from URL is not valid, start new chat session
515
- await chatSDK.startChat();
516
- }
663
+ // Valid reconnect id, reconnect to previous chat
664
+ if (chatReconnectContext.reconnectId) {
665
+ await chatSDK.startChat({
666
+ reconnectId: chatReconnectContext.reconnectId
667
+ });
668
+ } else { // Reconnect id from URL is not valid, start new chat session
669
+ await chatSDK.startChat();
670
+ }
517
671
  ```
518
672
 
519
673
  ### Operating Hours
520
674
 
675
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-operating-hours?tabs=customerserviceadmincenter on how to set up operating hours
676
+
521
677
  ```ts
522
- const chatConfig = await chatSDK.getLiveChatConfig();
523
- const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
524
- const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
678
+ const chatConfig = await chatSDK.getLiveChatConfig();
679
+ const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
680
+ const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
525
681
 
526
- if (outOfOperatingHours === "True") {
527
- // Handles UX on Out of Operating Hours
528
- } else {
529
- await chatSDK.startChat();
530
- // Renders Custom Chat Widget
531
- }
682
+ if (outOfOperatingHours === "True") {
683
+ // Handles UX on Out of Operating Hours
684
+ } else {
685
+ await chatSDK.startChat();
686
+ // Renders Custom Chat Widget
687
+ }
532
688
  ```
533
689
 
534
- ### Use [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
690
+ ### Using [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
691
+ > :warning: Currently supported on web only
535
692
 
536
- **NOTE**: Currently supported on web only
537
- ```ts
538
- import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
539
- import ReactWebChat from 'botframework-webchat';
693
+ Minimum Requirement Checklist
694
+ 1. [ ] Initialize ChatSDK
695
+ 1. [ ] Start new conversation
696
+ 1. [ ] Create Chat Adapter
697
+ 1. [ ] Create WebChat store with default middlewares
698
+ 1. [ ] Send Default Channel Message Tags using Store Middleware (See [here](/docs//DEVELOPMENT_GUIDE.md#send-default-channel-message-tags-using-store-middleware)) ❗ Required
699
+ 1. [ ] Render WebChat
540
700
 
541
- ...
701
+ ```ts
702
+ import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
703
+ import ReactWebChat, {createStore} from 'botframework-webchat';
542
704
 
543
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
544
- await chatSDK.initialize();
705
+ // 1. ChatSDK Initialization
706
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig);
707
+ await chatSDK.initialize();
545
708
 
546
- const optionalParams = {
547
- preChatResponse: '' // PreChatSurvey response
548
- };
709
+ // 2. Start new conversation
710
+ await chatSDK.startChat();
549
711
 
550
- await chatSDK.startChat(optionalParams);
551
- const chatAdapter = await chatSDK.createChatAdapter();
712
+ // 3. Create chat adapter
713
+ const chatAdapter = await chatSDK.createChatAdapter();
552
714
 
553
- // Subscribes to incoming message
554
- chatSDK.onNewMessage((message) => {
555
- console.log(`[NewMessage] ${message.content}`); // IC3 protocol message data
556
- console.log(message);
557
- });
715
+ // 4. Create WebChat store with middlewares
716
+ const store = createStore(
717
+ {}, // initial state
718
+ sendDefaultMessagingTagsMiddleware // ❗ Required
719
+ );
558
720
 
559
- ...
560
-
561
- <ReactWebChat
562
- userID="teamsvisitor"
563
- directLine={chatAdapter}
564
- sendTypingIndicator={true}
565
- />
721
+ // 5. Render WebChat
722
+ <ReactWebChat
723
+ store={store}
724
+ userID="teamsvisitor"
725
+ directLine={chatAdapter}
726
+ sendTypingIndicator={true}
727
+ />
566
728
  ```
567
729
 
568
730
  ### Escalation to Voice & Video
569
- **NOTE**: Currently supported on web only
731
+ > :warning: Currently supported on web only
732
+
733
+ > See https://docs.microsoft.com/en-us/dynamics365/customer-service/call-options-visual-engagement on how to set up calling options
734
+
570
735
  ```ts
571
- import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
736
+ import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
572
737
 
573
- ...
738
+ ...
574
739
 
575
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
576
- await chatSDK.initialize();
740
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
741
+ await chatSDK.initialize();
577
742
 
578
- let VoiceVideoCallingSDK;
579
- try {
580
- VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
581
- console.log("VoiceVideoCalling loaded");
582
- } catch (e) {
583
- console.log(`Failed to load VoiceVideoCalling: ${e}`);
743
+ let VoiceVideoCallingSDK;
744
+ try {
745
+ VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
746
+ console.log("VoiceVideoCalling loaded");
747
+ } catch (e) {
748
+ console.log(`Failed to load VoiceVideoCalling: ${e}`);
749
+
750
+ if (e.message === 'UnsupportedPlatform') {
751
+ // Voice Video Calling feature is not supported on this platform
584
752
  }
585
753
 
586
- await chatSDK.startChat();
754
+ if (e.message === 'FeatureDisabled') {
755
+ // Voice Video Calling feature is disabled on admin side
756
+ }
757
+ }
587
758
 
588
- const chatToken: any = await chatSDK.getChatToken();
759
+ await chatSDK.startChat();
589
760
 
761
+ const chatToken: any = await chatSDK.getChatToken();
762
+
763
+ // Initialize only if VoiceVideoCallingSDK is defined
764
+ if (VoiceVideoCallingSDK) {
590
765
  try {
591
766
  await VoiceVideoCallingSDK.initialize({
592
767
  chatToken,
@@ -657,6 +832,7 @@ The following steps will be required to run Omnichannel Chat SDK on React Native
657
832
 
658
833
  // Clean up VoiceVideoCallingSDK (e.g.: Usually called when customer ends chat session)
659
834
  VoiceVideoCallingSDK.close();
835
+ }
660
836
  ```
661
837
 
662
838
  ## Feature Comparisons
@@ -701,20 +877,20 @@ Some of the data being collected are the following:
701
877
  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`.
702
878
 
703
879
  ```ts
704
- const omnichannelConfig = {
705
- orgUrl: "",
706
- orgId: "",
707
- widgetId: ""
708
- };
880
+ const omnichannelConfig = {
881
+ orgUrl: "",
882
+ orgId: "",
883
+ widgetId: ""
884
+ };
709
885
 
710
- const chatSDKConfig = {
711
- telemetry: {
712
- disable: true // Disable telemetry
713
- }
714
- };
886
+ const chatSDKConfig = {
887
+ telemetry: {
888
+ disable: true // Disable telemetry
889
+ }
890
+ };
715
891
 
716
- const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
717
- await chatSDK.initialize();
892
+ const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
893
+ await chatSDK.initialize();
718
894
  ```
719
895
 
720
896
  # Contributing