@microsoft/omnichannel-chat-widget 1.2.3-main.000f886 → 1.2.3-main.f8e3363

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 (16) hide show
  1. package/lib/cjs/common/Constants.js +5 -1
  2. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +2 -1
  3. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachmentMiddleware.js +5 -0
  4. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware.js +65 -0
  5. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware.spec.js +342 -0
  6. package/lib/cjs/plugins/createChatTranscript.js +28 -4
  7. package/lib/esm/common/Constants.js +5 -1
  8. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +2 -1
  9. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachmentMiddleware.js +5 -0
  10. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware.js +58 -0
  11. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware.spec.js +338 -0
  12. package/lib/esm/plugins/createChatTranscript.js +28 -4
  13. package/lib/types/common/Constants.d.ts +4 -0
  14. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware.d.ts +5 -0
  15. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware.spec.d.ts +1 -0
  16. package/package.json +2 -2
@@ -58,7 +58,8 @@ _defineProperty(Constants, "prefixTimestampTag", "ServerMessageTimestamp_");
58
58
  _defineProperty(Constants, "acsChannel", "ACS_CHANNEL");
59
59
  _defineProperty(Constants, "publicMessageTag", "public");
60
60
  //attachmentMiddleware
61
- _defineProperty(Constants, "supportedAdaptiveCardContentTypes", ["application/vnd.microsoft.card.adaptive", "application/vnd.microsoft.card.audio", "application/vnd.microsoft.card.hero", "application/vnd.microsoft.card.receipt", "application/vnd.microsoft.card.thumbnail", "application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth"]);
61
+ _defineProperty(Constants, "supportedAdaptiveCardContentTypes", ["application/vnd.microsoft.card.adaptive", "application/vnd.microsoft.card.audio", "application/vnd.microsoft.card.hero", "application/vnd.microsoft.card.receipt", "application/vnd.microsoft.card.thumbnail", "application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth", "application/vnd.microsoft.card.video"]);
62
+ _defineProperty(Constants, "adaptiveCardContentTypePrefix", "application/vnd.microsoft.card");
62
63
  _defineProperty(Constants, "maxUploadFileSize", "500000");
63
64
  _defineProperty(Constants, "imageRegex", /(\.)(jpeg|jpg|jiff|png|gif|bmp|webp)$/i);
64
65
  _defineProperty(Constants, "audioMediaRegex", /(\.)(aac|aiff|alac|amr|flac|mp2|mp3|pcm|wav|wma)$/i);
@@ -116,6 +117,9 @@ _defineProperty(Constants, "LWICheckOnVisibilityTimeout", 3 * 60 * 1000);
116
117
  // Popup mode custom context response event message name
117
118
  _defineProperty(Constants, "InitContextParamsRequest", "initContextParamsRequest");
118
119
  _defineProperty(Constants, "InitContextParamsResponse", "initContextParamsResponse");
120
+ _defineProperty(Constants, "OCOriginalMessageId", "OriginalMessageId");
121
+ _defineProperty(Constants, "WebchatSequenceIdAttribute", "webchat:sequence-id");
122
+ _defineProperty(Constants, "MessageSequenceIdOverride", "MessageSequenceIdOverride");
119
123
  const Regex = (_class = class Regex {}, _defineProperty(_class, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _class);
120
124
  exports.Regex = Regex;
121
125
  class HtmlIdNames {}
@@ -35,6 +35,7 @@ var _htmlTextMiddleware = _interopRequireDefault(require("../../webchatcontainer
35
35
  var _preProcessingMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware"));
36
36
  var _sanitizationMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware"));
37
37
  var _dompurify = _interopRequireDefault(require("dompurify"));
38
+ var _messageSequenceIdOverrideMiddleware = _interopRequireDefault(require("../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware"));
38
39
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
39
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
41
  const initWebChatComposer = (props, state, dispatch, chatSDK) => {
@@ -74,7 +75,7 @@ const initWebChatComposer = (props, state, dispatch, chatSDK) => {
74
75
  };
75
76
  webChatStore = (0, _botframeworkWebchat.createStore)({},
76
77
  //initial state
77
- _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), _channelDataMiddleware.default, (0, _conversationEndMiddleware.default)(conversationEndCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.default, _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, _htmlTextMiddleware.default, (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default,
78
+ _preProcessingMiddleware.default, _attachmentProcessingMiddleware.default, (0, _attachmentUploadValidatorMiddleware.default)((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), _channelDataMiddleware.default, (0, _conversationEndMiddleware.default)(conversationEndCallback), (0, _dataMaskingMiddleware.default)((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), _messageTimestampMiddleware.default, _messageSequenceIdOverrideMiddleware.default, _gifUploadMiddleware.default, _htmlPlayerMiddleware.default, _htmlTextMiddleware.default, (0, _maxMessageSizeValidator.default)(localizedTexts), _sanitizationMiddleware.default,
78
79
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
80
  ...(((_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.storeMiddlewares) ?? []));
80
81
  _WebChatStoreLoader.WebChatStoreLoader.store = webChatStore;
@@ -209,12 +209,17 @@ const createAttachmentMiddleware = enableInlinePlaying => {
209
209
  id: attachmentId,
210
210
  style: atttachmentAdaptiveCardStyles
211
211
  }, next(...args));
212
+ } else if (contentType.startsWith(_Constants.Constants.adaptiveCardContentTypePrefix)) {
213
+ console.warn(`${contentType} adaptive card type is currently not supported.`);
212
214
  }
213
215
  if ((_card$activity$channe = card.activity.channelData) !== null && _card$activity$channe !== void 0 && _card$activity$channe.middlewareData) {
214
216
  attachment.contentUrl = card.activity.channelData.middlewareData[attachment.name];
215
217
  } else if (attachment !== null && attachment !== void 0 && attachment.tempContentUrl) {
216
218
  attachment.contentUrl = attachment.tempContentUrl;
217
219
  }
220
+ if (!attachment.name) {
221
+ return next(...args);
222
+ }
218
223
  const fileExtension = attachment.name.substring(attachment.name.lastIndexOf(".") + 1, attachment.name.length) || attachment.name;
219
224
  const imageExtension = _Constants.Constants.imageRegex.test(attachment.name);
220
225
  const audioExtension = _Constants.Constants.audioMediaRegex.test(attachment.name);
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _WebChatActionType = require("../../enums/WebChatActionType");
8
+ var _Constants = require("../../../../../common/Constants");
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
10
+ const createMessageSequenceIdOverrideMiddleware = _ref => {
11
+ let {
12
+ dispatch
13
+ } = _ref;
14
+ return next => action => {
15
+ if (isApplicable(action)) {
16
+ return next(overrideSequenceIdWithOriginalMessageId(action));
17
+ }
18
+ return next(action);
19
+ };
20
+ };
21
+ const isApplicable = action => {
22
+ return action.type === _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY && isValidChannel(action) && isWebSequenceIdPresent(action) && lookupOriginalMessageId(action) !== undefined;
23
+ };
24
+ const isValidChannel = action => {
25
+ var _action$payload, _action$payload$activ;
26
+ return (action === null || action === void 0 ? void 0 : (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : (_action$payload$activ = _action$payload.activity) === null || _action$payload$activ === void 0 ? void 0 : _action$payload$activ.channelId) === _Constants.Constants.acsChannel;
27
+ };
28
+ const isChannelDataPresent = action => {
29
+ var _action$payload2, _action$payload2$acti, _action$payload3, _action$payload3$acti;
30
+ return (action === null || action === void 0 ? void 0 : (_action$payload2 = action.payload) === null || _action$payload2 === void 0 ? void 0 : (_action$payload2$acti = _action$payload2.activity) === null || _action$payload2$acti === void 0 ? void 0 : _action$payload2$acti.channelData) !== undefined && (action === null || action === void 0 ? void 0 : (_action$payload3 = action.payload) === null || _action$payload3 === void 0 ? void 0 : (_action$payload3$acti = _action$payload3.activity) === null || _action$payload3$acti === void 0 ? void 0 : _action$payload3$acti.channelData) !== null;
31
+ };
32
+ const isWebSequenceIdPresent = action => {
33
+ if (!isChannelDataPresent(action)) return false;
34
+ const channelData = action.payload.activity.channelData;
35
+ return Object.keys(channelData).some(key => {
36
+ return key === _Constants.Constants.WebchatSequenceIdAttribute;
37
+ });
38
+ };
39
+ const overrideSequenceIdWithOriginalMessageId = action => {
40
+ const originalMessageId = extractOriginalMessageId(action);
41
+ const channelData = action.payload.activity.channelData;
42
+ if (originalMessageId === undefined) return action;
43
+ Object.keys(channelData).forEach(function (key) {
44
+ if (key === _Constants.Constants.WebchatSequenceIdAttribute && action.payload.activity.channelData[key] !== originalMessageId) {
45
+ action.payload.activity.channelData[key] = originalMessageId;
46
+ }
47
+ });
48
+ return action;
49
+ };
50
+
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
52
+ const extractOriginalMessageId = action => {
53
+ const originalMessageId = lookupOriginalMessageId(action);
54
+ if (typeof originalMessageId !== "string" || originalMessageId === "") {
55
+ return undefined;
56
+ }
57
+ const originalMessageIdResult = parseInt(originalMessageId);
58
+ return isNaN(originalMessageIdResult) ? undefined : originalMessageIdResult;
59
+ };
60
+ const lookupOriginalMessageId = action => {
61
+ var _action$payload4, _action$payload4$acti, _action$payload4$acti2, _action$payload4$acti3;
62
+ return action === null || action === void 0 ? void 0 : (_action$payload4 = action.payload) === null || _action$payload4 === void 0 ? void 0 : (_action$payload4$acti = _action$payload4.activity) === null || _action$payload4$acti === void 0 ? void 0 : (_action$payload4$acti2 = _action$payload4$acti.channelData) === null || _action$payload4$acti2 === void 0 ? void 0 : (_action$payload4$acti3 = _action$payload4$acti2.metadata) === null || _action$payload4$acti3 === void 0 ? void 0 : _action$payload4$acti3.OriginalMessageId;
63
+ };
64
+ var _default = createMessageSequenceIdOverrideMiddleware;
65
+ exports.default = _default;
@@ -0,0 +1,342 @@
1
+ "use strict";
2
+
3
+ var _Constants = require("../../../../../common/Constants");
4
+ var _WebChatActionType = require("../../enums/WebChatActionType");
5
+ var _messageSequenceIdOverrideMiddleware = _interopRequireDefault(require("./messageSequenceIdOverrideMiddleware"));
6
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
7
+ /* eslint-disable @typescript-eslint/no-explicit-any */
8
+
9
+ describe("messageSequenceIdOverrideMiddleware", () => {
10
+ it("sequenceId is overrided", () => {
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ const next = args => args;
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ const dispatch = () => {
15
+ return 1;
16
+ };
17
+ const action = {
18
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
19
+ payload: {
20
+ text: "test-text",
21
+ activity: {
22
+ channelId: "ACS_CHANNEL",
23
+ from: {
24
+ role: "user"
25
+ },
26
+ channelData: {
27
+ metadata: {
28
+ "OriginalMessageId": "1683742135918"
29
+ },
30
+ "webchat:sequence-id": 12345
31
+ }
32
+ }
33
+ }
34
+ };
35
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
36
+ let resultValue;
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
38
+ const channelData = middleware.payload.activity.channelData;
39
+ Object.keys(channelData).forEach(function (key) {
40
+ if (key === _Constants.Constants.WebchatSequenceIdAttribute) {
41
+ resultValue = channelData[key];
42
+ }
43
+ });
44
+ expect(resultValue).toEqual(1683742135918);
45
+ });
46
+ it("sequenceId is not overrided due to empty string for originalID", () => {
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ const next = args => args;
49
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
50
+ const dispatch = () => {
51
+ return 1;
52
+ };
53
+ const action = {
54
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
55
+ payload: {
56
+ text: "test-text",
57
+ activity: {
58
+ channelId: "ACS_CHANNEL",
59
+ from: {
60
+ role: "user"
61
+ },
62
+ channelData: {
63
+ metadata: {
64
+ "OriginalMessageId": ""
65
+ },
66
+ "webchat:sequence-id": 12345
67
+ }
68
+ }
69
+ }
70
+ };
71
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
72
+ let resultValue;
73
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
74
+ const channelData = middleware.payload.activity.channelData;
75
+ Object.keys(channelData).forEach(function (key) {
76
+ if (key === _Constants.Constants.WebchatSequenceIdAttribute) {
77
+ resultValue = channelData[key];
78
+ }
79
+ });
80
+ expect(resultValue).toEqual(12345);
81
+ });
82
+ it("sequenceId is not overrided, due to OriginalMessageId being not a string of numbers ", () => {
83
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
+ const next = args => args;
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
+ const dispatch = () => {
87
+ return 1;
88
+ };
89
+ const action = {
90
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
91
+ payload: {
92
+ text: "test-text",
93
+ activity: {
94
+ channelId: "ACS_CHANNEL",
95
+ from: {
96
+ role: "user"
97
+ },
98
+ channelData: {
99
+ metadata: {
100
+ "OriginalMessageId": "abcdf"
101
+ },
102
+ "webchat:sequence-id": 12345
103
+ }
104
+ }
105
+ }
106
+ };
107
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
108
+ let resultValue;
109
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
110
+ const channelData = middleware.payload.activity.channelData;
111
+ Object.keys(channelData).forEach(function (key) {
112
+ if (key === _Constants.Constants.WebchatSequenceIdAttribute) {
113
+ resultValue = channelData[key];
114
+ }
115
+ });
116
+ expect(resultValue).toEqual(12345);
117
+ });
118
+ it("no changes since webchat id is not present", () => {
119
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
120
+ const next = args => args;
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ const dispatch = () => {
123
+ return 1;
124
+ };
125
+ const payloadExpected = {
126
+ payload: {
127
+ text: "test-text",
128
+ activity: {
129
+ channelId: "ACS_CHANNEL",
130
+ from: {
131
+ role: "user"
132
+ },
133
+ channelData: {
134
+ metadata: {
135
+ "OriginalMessageId": "123456789"
136
+ }
137
+ }
138
+ }
139
+ }
140
+ };
141
+ const action = {
142
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
143
+ payload: {
144
+ text: "test-text",
145
+ activity: {
146
+ channelId: "ACS_CHANNEL",
147
+ from: {
148
+ role: "user"
149
+ },
150
+ channelData: {
151
+ metadata: {
152
+ "OriginalMessageId": "123456789"
153
+ }
154
+ }
155
+ }
156
+ }
157
+ };
158
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
159
+ expect(middleware.payload).toEqual(payloadExpected.payload);
160
+ });
161
+ it("no changes since OriginalMessageId is not present", () => {
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
+ const next = args => args;
164
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
165
+ const dispatch = () => {
166
+ return 1;
167
+ };
168
+ const payloadExpected = {
169
+ payload: {
170
+ text: "test-text",
171
+ activity: {
172
+ channelId: "ACS_CHANNEL",
173
+ from: {
174
+ role: "user"
175
+ },
176
+ channelData: {
177
+ metadata: {},
178
+ "webchat:sequence-id": 12345
179
+ }
180
+ }
181
+ }
182
+ };
183
+ const action = {
184
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
185
+ payload: {
186
+ text: "test-text",
187
+ activity: {
188
+ channelId: "ACS_CHANNEL",
189
+ from: {
190
+ role: "user"
191
+ },
192
+ channelData: {
193
+ metadata: {},
194
+ "webchat:sequence-id": 12345
195
+ }
196
+ }
197
+ }
198
+ };
199
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
200
+ expect(middleware.payload).toEqual(payloadExpected.payload);
201
+ });
202
+ it("no override, since the type of message is not incoming activity", () => {
203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
204
+ const next = args => args;
205
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
+ const dispatch = () => {
207
+ return 1;
208
+ };
209
+ const action = {
210
+ type: "something else",
211
+ payload: {
212
+ text: "test-text",
213
+ activity: {
214
+ channelId: "ACS_CHANNEL",
215
+ from: {
216
+ role: "user"
217
+ },
218
+ channelData: {
219
+ metadata: {
220
+ "OriginalMessageId": "1683742135918"
221
+ },
222
+ "webchat:sequence-id": 12345
223
+ }
224
+ }
225
+ }
226
+ };
227
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
228
+ let resultValue;
229
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
230
+ const channelData = middleware.payload.activity.channelData;
231
+ Object.keys(channelData).forEach(function (key) {
232
+ if (key === _Constants.Constants.WebchatSequenceIdAttribute) {
233
+ resultValue = channelData[key];
234
+ }
235
+ });
236
+ expect(resultValue).toEqual(12345);
237
+ });
238
+ it("no override, since the channel is not ACS", () => {
239
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
240
+ const next = args => args;
241
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
242
+ const dispatch = () => {
243
+ return 1;
244
+ };
245
+ const action = {
246
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
247
+ payload: {
248
+ text: "test-text",
249
+ activity: {
250
+ channelId: "something_else",
251
+ from: {
252
+ role: "user"
253
+ },
254
+ channelData: {
255
+ metadata: {
256
+ "OriginalMessageId": "1683742135918"
257
+ },
258
+ "webchat:sequence-id": 12345
259
+ }
260
+ }
261
+ }
262
+ };
263
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
264
+ let resultValue;
265
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
266
+ const channelData = middleware.payload.activity.channelData;
267
+ Object.keys(channelData).forEach(function (key) {
268
+ if (key === _Constants.Constants.WebchatSequenceIdAttribute) {
269
+ resultValue = channelData[key];
270
+ }
271
+ });
272
+ expect(resultValue).toEqual(12345);
273
+ });
274
+ it("no override, since the channel channelData is not present", () => {
275
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
276
+ const next = args => args;
277
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
278
+ const dispatch = () => {
279
+ return 1;
280
+ };
281
+ const action = {
282
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
283
+ payload: {
284
+ text: "test-text channel data is not present",
285
+ activity: {
286
+ channelId: "ACS_CHANNEL",
287
+ from: {
288
+ role: "user"
289
+ }
290
+ }
291
+ }
292
+ };
293
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
294
+ expect(middleware.payload).toEqual(action.payload);
295
+ });
296
+ it("no override, since channelData is empty object", () => {
297
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
298
+ const next = args => args;
299
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
300
+ const dispatch = () => {
301
+ return 1;
302
+ };
303
+ const action = {
304
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
305
+ payload: {
306
+ text: "test-text channel data empty",
307
+ activity: {
308
+ channelId: "ACS_CHANNEL",
309
+ from: {
310
+ role: "user"
311
+ },
312
+ channelData: {}
313
+ }
314
+ }
315
+ };
316
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
317
+ expect(middleware.payload).toEqual(action.payload);
318
+ });
319
+ it("no override, since channelData null", () => {
320
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
321
+ const next = args => args;
322
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
323
+ const dispatch = () => {
324
+ return 1;
325
+ };
326
+ const action = {
327
+ type: _WebChatActionType.WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
328
+ payload: {
329
+ text: "test-channel Data null",
330
+ activity: {
331
+ channelId: "ACS_CHANNEL",
332
+ from: {
333
+ role: "user"
334
+ },
335
+ channelData: null
336
+ }
337
+ }
338
+ };
339
+ const middleware = (0, _messageSequenceIdOverrideMiddleware.default)(dispatch)(next)(action);
340
+ expect(middleware.payload).toEqual(action.payload);
341
+ });
342
+ });
@@ -124,7 +124,13 @@ class TranscriptHTMLBuilder {
124
124
  <script>
125
125
  class Translator {
126
126
  static convertTranscriptMessageToActivity(message) {
127
- const {created, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
127
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
128
+
129
+ //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
130
+ // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
131
+
132
+ const webchatSequenceId = Translator.convertStringValueToInt(OriginalMessageId) || Translator.convertStringValueToInt(id);
133
+
128
134
  const activity = {
129
135
  from: {
130
136
  role: 'bot'
@@ -179,7 +185,10 @@ class TranscriptHTMLBuilder {
179
185
  return {
180
186
  ...activity,
181
187
  text,
182
- timestamp: created
188
+ timestamp: created,
189
+ channelData: {
190
+ "webchat:sequence-id": webchatSequenceId
191
+ }
183
192
  }
184
193
  }
185
194
 
@@ -192,7 +201,10 @@ class TranscriptHTMLBuilder {
192
201
  return {
193
202
  ...activity,
194
203
  ...partialActivity,
195
- timestamp: created
204
+ timestamp: created,
205
+ channelData: {
206
+ "webchat:sequence-id": webchatSequenceId
207
+ }
196
208
  };
197
209
  } catch {
198
210
 
@@ -203,9 +215,21 @@ class TranscriptHTMLBuilder {
203
215
  return {
204
216
  ...activity,
205
217
  text: content,
206
- timestamp: created
218
+ timestamp: created,
219
+ channelData: {
220
+ "webchat:sequence-id": webchatSequenceId
221
+ }
207
222
  };
208
223
  }
224
+
225
+ static convertStringValueToInt(value) {
226
+ if (typeof value !== "string" || value === "") {
227
+ return undefined;
228
+ }
229
+
230
+ const result = parseInt(value);
231
+ return isNaN(result) ? undefined : result;
232
+ }
209
233
  }
210
234
  <\/script>
211
235
  <script>
@@ -51,7 +51,8 @@ _defineProperty(Constants, "prefixTimestampTag", "ServerMessageTimestamp_");
51
51
  _defineProperty(Constants, "acsChannel", "ACS_CHANNEL");
52
52
  _defineProperty(Constants, "publicMessageTag", "public");
53
53
  //attachmentMiddleware
54
- _defineProperty(Constants, "supportedAdaptiveCardContentTypes", ["application/vnd.microsoft.card.adaptive", "application/vnd.microsoft.card.audio", "application/vnd.microsoft.card.hero", "application/vnd.microsoft.card.receipt", "application/vnd.microsoft.card.thumbnail", "application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth"]);
54
+ _defineProperty(Constants, "supportedAdaptiveCardContentTypes", ["application/vnd.microsoft.card.adaptive", "application/vnd.microsoft.card.audio", "application/vnd.microsoft.card.hero", "application/vnd.microsoft.card.receipt", "application/vnd.microsoft.card.thumbnail", "application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth", "application/vnd.microsoft.card.video"]);
55
+ _defineProperty(Constants, "adaptiveCardContentTypePrefix", "application/vnd.microsoft.card");
55
56
  _defineProperty(Constants, "maxUploadFileSize", "500000");
56
57
  _defineProperty(Constants, "imageRegex", /(\.)(jpeg|jpg|jiff|png|gif|bmp|webp)$/i);
57
58
  _defineProperty(Constants, "audioMediaRegex", /(\.)(aac|aiff|alac|amr|flac|mp2|mp3|pcm|wav|wma)$/i);
@@ -109,6 +110,9 @@ _defineProperty(Constants, "LWICheckOnVisibilityTimeout", 3 * 60 * 1000);
109
110
  // Popup mode custom context response event message name
110
111
  _defineProperty(Constants, "InitContextParamsRequest", "initContextParamsRequest");
111
112
  _defineProperty(Constants, "InitContextParamsResponse", "initContextParamsResponse");
113
+ _defineProperty(Constants, "OCOriginalMessageId", "OriginalMessageId");
114
+ _defineProperty(Constants, "WebchatSequenceIdAttribute", "webchat:sequence-id");
115
+ _defineProperty(Constants, "MessageSequenceIdOverride", "MessageSequenceIdOverride");
112
116
  export const Regex = (_class = class Regex {}, _defineProperty(_class, "EmailRegex", "(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-zA-Z0-9-]*[a-zA-Z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"), _class);
113
117
  export class HtmlIdNames {}
114
118
  _defineProperty(HtmlIdNames, "MSLiveChatWidget", "MSLiveChatWidget");
@@ -29,6 +29,7 @@ import htmlTextMiddleware from "../../webchatcontainerstateful/webchatcontroller
29
29
  import preProcessingMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/preProcessingMiddleware";
30
30
  import sanitizationMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/sanitizationMiddleware";
31
31
  import DOMPurify from "dompurify";
32
+ import createMessageSequenceIdOverrideMiddleware from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/messageSequenceIdOverrideMiddleware";
32
33
 
33
34
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
35
  export const initWebChatComposer = (props, state, dispatch, chatSDK) => {
@@ -68,7 +69,7 @@ export const initWebChatComposer = (props, state, dispatch, chatSDK) => {
68
69
  };
69
70
  webChatStore = createStore({},
70
71
  //initial state
71
- preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), channelDataMiddleware, createConversationEndMiddleware(conversationEndCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware, createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware,
72
+ preProcessingMiddleware, attachmentProcessingMiddleware, createAttachmentUploadValidatorMiddleware((_state$domainStates$l = state.domainStates.liveChatConfig) === null || _state$domainStates$l === void 0 ? void 0 : _state$domainStates$l.allowedFileExtensions, (_state$domainStates$l2 = state.domainStates.liveChatConfig) === null || _state$domainStates$l2 === void 0 ? void 0 : _state$domainStates$l2.maxUploadFileSize, localizedTexts), channelDataMiddleware, createConversationEndMiddleware(conversationEndCallback), createDataMaskingMiddleware((_state$domainStates$l3 = state.domainStates.liveChatConfig) === null || _state$domainStates$l3 === void 0 ? void 0 : _state$domainStates$l3.DataMaskingInfo), createMessageTimeStampMiddleware, createMessageSequenceIdOverrideMiddleware, gifUploadMiddleware, htmlPlayerMiddleware, htmlTextMiddleware, createMaxMessageSizeValidator(localizedTexts), sanitizationMiddleware,
72
73
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
74
  ...(((_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : _props$webChatContain5.storeMiddlewares) ?? []));
74
75
  WebChatStoreLoader.store = webChatStore;
@@ -202,12 +202,17 @@ const createAttachmentMiddleware = enableInlinePlaying => {
202
202
  id: attachmentId,
203
203
  style: atttachmentAdaptiveCardStyles
204
204
  }, next(...args));
205
+ } else if (contentType.startsWith(Constants.adaptiveCardContentTypePrefix)) {
206
+ console.warn(`${contentType} adaptive card type is currently not supported.`);
205
207
  }
206
208
  if ((_card$activity$channe = card.activity.channelData) !== null && _card$activity$channe !== void 0 && _card$activity$channe.middlewareData) {
207
209
  attachment.contentUrl = card.activity.channelData.middlewareData[attachment.name];
208
210
  } else if (attachment !== null && attachment !== void 0 && attachment.tempContentUrl) {
209
211
  attachment.contentUrl = attachment.tempContentUrl;
210
212
  }
213
+ if (!attachment.name) {
214
+ return next(...args);
215
+ }
211
216
  const fileExtension = attachment.name.substring(attachment.name.lastIndexOf(".") + 1, attachment.name.length) || attachment.name;
212
217
  const imageExtension = Constants.imageRegex.test(attachment.name);
213
218
  const audioExtension = Constants.audioMediaRegex.test(attachment.name);
@@ -0,0 +1,58 @@
1
+ import { WebChatActionType } from "../../enums/WebChatActionType";
2
+ import { Constants } from "../../../../../common/Constants";
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
4
+ const createMessageSequenceIdOverrideMiddleware = _ref => {
5
+ let {
6
+ dispatch
7
+ } = _ref;
8
+ return next => action => {
9
+ if (isApplicable(action)) {
10
+ return next(overrideSequenceIdWithOriginalMessageId(action));
11
+ }
12
+ return next(action);
13
+ };
14
+ };
15
+ const isApplicable = action => {
16
+ return action.type === WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY && isValidChannel(action) && isWebSequenceIdPresent(action) && lookupOriginalMessageId(action) !== undefined;
17
+ };
18
+ const isValidChannel = action => {
19
+ var _action$payload, _action$payload$activ;
20
+ return (action === null || action === void 0 ? void 0 : (_action$payload = action.payload) === null || _action$payload === void 0 ? void 0 : (_action$payload$activ = _action$payload.activity) === null || _action$payload$activ === void 0 ? void 0 : _action$payload$activ.channelId) === Constants.acsChannel;
21
+ };
22
+ const isChannelDataPresent = action => {
23
+ var _action$payload2, _action$payload2$acti, _action$payload3, _action$payload3$acti;
24
+ return (action === null || action === void 0 ? void 0 : (_action$payload2 = action.payload) === null || _action$payload2 === void 0 ? void 0 : (_action$payload2$acti = _action$payload2.activity) === null || _action$payload2$acti === void 0 ? void 0 : _action$payload2$acti.channelData) !== undefined && (action === null || action === void 0 ? void 0 : (_action$payload3 = action.payload) === null || _action$payload3 === void 0 ? void 0 : (_action$payload3$acti = _action$payload3.activity) === null || _action$payload3$acti === void 0 ? void 0 : _action$payload3$acti.channelData) !== null;
25
+ };
26
+ const isWebSequenceIdPresent = action => {
27
+ if (!isChannelDataPresent(action)) return false;
28
+ const channelData = action.payload.activity.channelData;
29
+ return Object.keys(channelData).some(key => {
30
+ return key === Constants.WebchatSequenceIdAttribute;
31
+ });
32
+ };
33
+ const overrideSequenceIdWithOriginalMessageId = action => {
34
+ const originalMessageId = extractOriginalMessageId(action);
35
+ const channelData = action.payload.activity.channelData;
36
+ if (originalMessageId === undefined) return action;
37
+ Object.keys(channelData).forEach(function (key) {
38
+ if (key === Constants.WebchatSequenceIdAttribute && action.payload.activity.channelData[key] !== originalMessageId) {
39
+ action.payload.activity.channelData[key] = originalMessageId;
40
+ }
41
+ });
42
+ return action;
43
+ };
44
+
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
46
+ const extractOriginalMessageId = action => {
47
+ const originalMessageId = lookupOriginalMessageId(action);
48
+ if (typeof originalMessageId !== "string" || originalMessageId === "") {
49
+ return undefined;
50
+ }
51
+ const originalMessageIdResult = parseInt(originalMessageId);
52
+ return isNaN(originalMessageIdResult) ? undefined : originalMessageIdResult;
53
+ };
54
+ const lookupOriginalMessageId = action => {
55
+ var _action$payload4, _action$payload4$acti, _action$payload4$acti2, _action$payload4$acti3;
56
+ return action === null || action === void 0 ? void 0 : (_action$payload4 = action.payload) === null || _action$payload4 === void 0 ? void 0 : (_action$payload4$acti = _action$payload4.activity) === null || _action$payload4$acti === void 0 ? void 0 : (_action$payload4$acti2 = _action$payload4$acti.channelData) === null || _action$payload4$acti2 === void 0 ? void 0 : (_action$payload4$acti3 = _action$payload4$acti2.metadata) === null || _action$payload4$acti3 === void 0 ? void 0 : _action$payload4$acti3.OriginalMessageId;
57
+ };
58
+ export default createMessageSequenceIdOverrideMiddleware;
@@ -0,0 +1,338 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Constants } from "../../../../../common/Constants";
3
+ import { WebChatActionType } from "../../enums/WebChatActionType";
4
+ import createMessageSequenceIdOverrideMiddleware from "./messageSequenceIdOverrideMiddleware";
5
+ describe("messageSequenceIdOverrideMiddleware", () => {
6
+ it("sequenceId is overrided", () => {
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ const next = args => args;
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ const dispatch = () => {
11
+ return 1;
12
+ };
13
+ const action = {
14
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
15
+ payload: {
16
+ text: "test-text",
17
+ activity: {
18
+ channelId: "ACS_CHANNEL",
19
+ from: {
20
+ role: "user"
21
+ },
22
+ channelData: {
23
+ metadata: {
24
+ "OriginalMessageId": "1683742135918"
25
+ },
26
+ "webchat:sequence-id": 12345
27
+ }
28
+ }
29
+ }
30
+ };
31
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
32
+ let resultValue;
33
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
34
+ const channelData = middleware.payload.activity.channelData;
35
+ Object.keys(channelData).forEach(function (key) {
36
+ if (key === Constants.WebchatSequenceIdAttribute) {
37
+ resultValue = channelData[key];
38
+ }
39
+ });
40
+ expect(resultValue).toEqual(1683742135918);
41
+ });
42
+ it("sequenceId is not overrided due to empty string for originalID", () => {
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ const next = args => args;
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const dispatch = () => {
47
+ return 1;
48
+ };
49
+ const action = {
50
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
51
+ payload: {
52
+ text: "test-text",
53
+ activity: {
54
+ channelId: "ACS_CHANNEL",
55
+ from: {
56
+ role: "user"
57
+ },
58
+ channelData: {
59
+ metadata: {
60
+ "OriginalMessageId": ""
61
+ },
62
+ "webchat:sequence-id": 12345
63
+ }
64
+ }
65
+ }
66
+ };
67
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
68
+ let resultValue;
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
70
+ const channelData = middleware.payload.activity.channelData;
71
+ Object.keys(channelData).forEach(function (key) {
72
+ if (key === Constants.WebchatSequenceIdAttribute) {
73
+ resultValue = channelData[key];
74
+ }
75
+ });
76
+ expect(resultValue).toEqual(12345);
77
+ });
78
+ it("sequenceId is not overrided, due to OriginalMessageId being not a string of numbers ", () => {
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
+ const next = args => args;
81
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
82
+ const dispatch = () => {
83
+ return 1;
84
+ };
85
+ const action = {
86
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
87
+ payload: {
88
+ text: "test-text",
89
+ activity: {
90
+ channelId: "ACS_CHANNEL",
91
+ from: {
92
+ role: "user"
93
+ },
94
+ channelData: {
95
+ metadata: {
96
+ "OriginalMessageId": "abcdf"
97
+ },
98
+ "webchat:sequence-id": 12345
99
+ }
100
+ }
101
+ }
102
+ };
103
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
104
+ let resultValue;
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
106
+ const channelData = middleware.payload.activity.channelData;
107
+ Object.keys(channelData).forEach(function (key) {
108
+ if (key === Constants.WebchatSequenceIdAttribute) {
109
+ resultValue = channelData[key];
110
+ }
111
+ });
112
+ expect(resultValue).toEqual(12345);
113
+ });
114
+ it("no changes since webchat id is not present", () => {
115
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
116
+ const next = args => args;
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ const dispatch = () => {
119
+ return 1;
120
+ };
121
+ const payloadExpected = {
122
+ payload: {
123
+ text: "test-text",
124
+ activity: {
125
+ channelId: "ACS_CHANNEL",
126
+ from: {
127
+ role: "user"
128
+ },
129
+ channelData: {
130
+ metadata: {
131
+ "OriginalMessageId": "123456789"
132
+ }
133
+ }
134
+ }
135
+ }
136
+ };
137
+ const action = {
138
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
139
+ payload: {
140
+ text: "test-text",
141
+ activity: {
142
+ channelId: "ACS_CHANNEL",
143
+ from: {
144
+ role: "user"
145
+ },
146
+ channelData: {
147
+ metadata: {
148
+ "OriginalMessageId": "123456789"
149
+ }
150
+ }
151
+ }
152
+ }
153
+ };
154
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
155
+ expect(middleware.payload).toEqual(payloadExpected.payload);
156
+ });
157
+ it("no changes since OriginalMessageId is not present", () => {
158
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
+ const next = args => args;
160
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
+ const dispatch = () => {
162
+ return 1;
163
+ };
164
+ const payloadExpected = {
165
+ payload: {
166
+ text: "test-text",
167
+ activity: {
168
+ channelId: "ACS_CHANNEL",
169
+ from: {
170
+ role: "user"
171
+ },
172
+ channelData: {
173
+ metadata: {},
174
+ "webchat:sequence-id": 12345
175
+ }
176
+ }
177
+ }
178
+ };
179
+ const action = {
180
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
181
+ payload: {
182
+ text: "test-text",
183
+ activity: {
184
+ channelId: "ACS_CHANNEL",
185
+ from: {
186
+ role: "user"
187
+ },
188
+ channelData: {
189
+ metadata: {},
190
+ "webchat:sequence-id": 12345
191
+ }
192
+ }
193
+ }
194
+ };
195
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
196
+ expect(middleware.payload).toEqual(payloadExpected.payload);
197
+ });
198
+ it("no override, since the type of message is not incoming activity", () => {
199
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
200
+ const next = args => args;
201
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
202
+ const dispatch = () => {
203
+ return 1;
204
+ };
205
+ const action = {
206
+ type: "something else",
207
+ payload: {
208
+ text: "test-text",
209
+ activity: {
210
+ channelId: "ACS_CHANNEL",
211
+ from: {
212
+ role: "user"
213
+ },
214
+ channelData: {
215
+ metadata: {
216
+ "OriginalMessageId": "1683742135918"
217
+ },
218
+ "webchat:sequence-id": 12345
219
+ }
220
+ }
221
+ }
222
+ };
223
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
224
+ let resultValue;
225
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
226
+ const channelData = middleware.payload.activity.channelData;
227
+ Object.keys(channelData).forEach(function (key) {
228
+ if (key === Constants.WebchatSequenceIdAttribute) {
229
+ resultValue = channelData[key];
230
+ }
231
+ });
232
+ expect(resultValue).toEqual(12345);
233
+ });
234
+ it("no override, since the channel is not ACS", () => {
235
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
236
+ const next = args => args;
237
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
238
+ const dispatch = () => {
239
+ return 1;
240
+ };
241
+ const action = {
242
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
243
+ payload: {
244
+ text: "test-text",
245
+ activity: {
246
+ channelId: "something_else",
247
+ from: {
248
+ role: "user"
249
+ },
250
+ channelData: {
251
+ metadata: {
252
+ "OriginalMessageId": "1683742135918"
253
+ },
254
+ "webchat:sequence-id": 12345
255
+ }
256
+ }
257
+ }
258
+ };
259
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
260
+ let resultValue;
261
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
262
+ const channelData = middleware.payload.activity.channelData;
263
+ Object.keys(channelData).forEach(function (key) {
264
+ if (key === Constants.WebchatSequenceIdAttribute) {
265
+ resultValue = channelData[key];
266
+ }
267
+ });
268
+ expect(resultValue).toEqual(12345);
269
+ });
270
+ it("no override, since the channel channelData is not present", () => {
271
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
272
+ const next = args => args;
273
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
274
+ const dispatch = () => {
275
+ return 1;
276
+ };
277
+ const action = {
278
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
279
+ payload: {
280
+ text: "test-text channel data is not present",
281
+ activity: {
282
+ channelId: "ACS_CHANNEL",
283
+ from: {
284
+ role: "user"
285
+ }
286
+ }
287
+ }
288
+ };
289
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
290
+ expect(middleware.payload).toEqual(action.payload);
291
+ });
292
+ it("no override, since channelData is empty object", () => {
293
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
294
+ const next = args => args;
295
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
296
+ const dispatch = () => {
297
+ return 1;
298
+ };
299
+ const action = {
300
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
301
+ payload: {
302
+ text: "test-text channel data empty",
303
+ activity: {
304
+ channelId: "ACS_CHANNEL",
305
+ from: {
306
+ role: "user"
307
+ },
308
+ channelData: {}
309
+ }
310
+ }
311
+ };
312
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
313
+ expect(middleware.payload).toEqual(action.payload);
314
+ });
315
+ it("no override, since channelData null", () => {
316
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
317
+ const next = args => args;
318
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
319
+ const dispatch = () => {
320
+ return 1;
321
+ };
322
+ const action = {
323
+ type: WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY,
324
+ payload: {
325
+ text: "test-channel Data null",
326
+ activity: {
327
+ channelId: "ACS_CHANNEL",
328
+ from: {
329
+ role: "user"
330
+ },
331
+ channelData: null
332
+ }
333
+ }
334
+ };
335
+ const middleware = createMessageSequenceIdOverrideMiddleware(dispatch)(next)(action);
336
+ expect(middleware.payload).toEqual(action.payload);
337
+ });
338
+ });
@@ -120,7 +120,13 @@ class TranscriptHTMLBuilder {
120
120
  <script>
121
121
  class Translator {
122
122
  static convertTranscriptMessageToActivity(message) {
123
- const {created, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
123
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
124
+
125
+ //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
126
+ // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
127
+
128
+ const webchatSequenceId = Translator.convertStringValueToInt(OriginalMessageId) || Translator.convertStringValueToInt(id);
129
+
124
130
  const activity = {
125
131
  from: {
126
132
  role: 'bot'
@@ -175,7 +181,10 @@ class TranscriptHTMLBuilder {
175
181
  return {
176
182
  ...activity,
177
183
  text,
178
- timestamp: created
184
+ timestamp: created,
185
+ channelData: {
186
+ "webchat:sequence-id": webchatSequenceId
187
+ }
179
188
  }
180
189
  }
181
190
 
@@ -188,7 +197,10 @@ class TranscriptHTMLBuilder {
188
197
  return {
189
198
  ...activity,
190
199
  ...partialActivity,
191
- timestamp: created
200
+ timestamp: created,
201
+ channelData: {
202
+ "webchat:sequence-id": webchatSequenceId
203
+ }
192
204
  };
193
205
  } catch {
194
206
 
@@ -199,9 +211,21 @@ class TranscriptHTMLBuilder {
199
211
  return {
200
212
  ...activity,
201
213
  text: content,
202
- timestamp: created
214
+ timestamp: created,
215
+ channelData: {
216
+ "webchat:sequence-id": webchatSequenceId
217
+ }
203
218
  };
204
219
  }
220
+
221
+ static convertStringValueToInt(value) {
222
+ if (typeof value !== "string" || value === "") {
223
+ return undefined;
224
+ }
225
+
226
+ const result = parseInt(value);
227
+ return isNaN(result) ? undefined : result;
228
+ }
205
229
  }
206
230
  <\/script>
207
231
  <script>
@@ -41,6 +41,7 @@ export declare class Constants {
41
41
  static readonly acsChannel = "ACS_CHANNEL";
42
42
  static readonly publicMessageTag = "public";
43
43
  static readonly supportedAdaptiveCardContentTypes: Array<string>;
44
+ static readonly adaptiveCardContentTypePrefix = "application/vnd.microsoft.card";
44
45
  static readonly maxUploadFileSize = "500000";
45
46
  static readonly imageRegex: RegExp;
46
47
  static readonly audioMediaRegex: RegExp;
@@ -86,6 +87,9 @@ export declare class Constants {
86
87
  static readonly LWICheckOnVisibilityTimeout: number;
87
88
  static readonly InitContextParamsRequest = "initContextParamsRequest";
88
89
  static readonly InitContextParamsResponse = "initContextParamsResponse";
90
+ static readonly OCOriginalMessageId = "OriginalMessageId";
91
+ static readonly WebchatSequenceIdAttribute = "webchat:sequence-id";
92
+ static readonly MessageSequenceIdOverride = "MessageSequenceIdOverride";
89
93
  }
90
94
  export declare const Regex: {
91
95
  new (): {};
@@ -0,0 +1,5 @@
1
+ import { IWebChatAction } from "../../../interfaces/IWebChatAction";
2
+ declare const createMessageSequenceIdOverrideMiddleware: ({ dispatch }: {
3
+ dispatch: any;
4
+ }) => (next: any) => (action: IWebChatAction) => any;
5
+ export default createMessageSequenceIdOverrideMiddleware;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.2.3-main.000f886",
3
+ "version": "1.2.3-main.f8e3363",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -74,7 +74,7 @@
74
74
  "webpack-cli": "^4.9.2"
75
75
  },
76
76
  "dependencies": {
77
- "@microsoft/omnichannel-chat-components": "^1.0.5",
77
+ "@microsoft/omnichannel-chat-components": "^1.0.6",
78
78
  "@microsoft/omnichannel-chat-sdk": "1.4.6",
79
79
  "abort-controller-es5": "^2.0.1",
80
80
  "dompurify": "^2.3.4",