@sapui5/sap.suite.ui.commons 1.140.0 → 1.141.0

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 (55) hide show
  1. package/package.json +1 -1
  2. package/src/sap/suite/ui/commons/.library +1 -1
  3. package/src/sap/suite/ui/commons/AriaProperties.js +1 -1
  4. package/src/sap/suite/ui/commons/CalculationBuilder.js +13 -2
  5. package/src/sap/suite/ui/commons/CalculationBuilderExpression.js +1 -1
  6. package/src/sap/suite/ui/commons/CalculationBuilderFunction.js +1 -1
  7. package/src/sap/suite/ui/commons/CalculationBuilderGroup.js +1 -1
  8. package/src/sap/suite/ui/commons/CalculationBuilderItem.js +1 -1
  9. package/src/sap/suite/ui/commons/CalculationBuilderValidationResult.js +1 -1
  10. package/src/sap/suite/ui/commons/CalculationBuilderVariable.js +1 -1
  11. package/src/sap/suite/ui/commons/CloudFilePicker.js +1 -1
  12. package/src/sap/suite/ui/commons/MicroProcessFlow.js +1 -1
  13. package/src/sap/suite/ui/commons/MicroProcessFlowItem.js +1 -1
  14. package/src/sap/suite/ui/commons/TimelineRenderManager.js +25 -13
  15. package/src/sap/suite/ui/commons/collaboration/BaseHelperService.js +12 -12
  16. package/src/sap/suite/ui/commons/collaboration/CollaborationCardHelper.js +6 -5
  17. package/src/sap/suite/ui/commons/collaboration/CollaborationContactInfoHelper.js +15 -15
  18. package/src/sap/suite/ui/commons/collaboration/CollaborationHelper.js +94 -76
  19. package/src/sap/suite/ui/commons/collaboration/CollaborationManagerService.js +41 -41
  20. package/src/sap/suite/ui/commons/collaboration/ContactHelper.js +288 -286
  21. package/src/sap/suite/ui/commons/collaboration/ServiceContainer.js +33 -33
  22. package/src/sap/suite/ui/commons/collaboration/TeamsHelperService.js +296 -149
  23. package/src/sap/suite/ui/commons/collaboration/flpplugins/msplugin/Component-preload.js +2 -2
  24. package/src/sap/suite/ui/commons/collaboration/flpplugins/msplugin/Component.js +11 -13
  25. package/src/sap/suite/ui/commons/flexibility/changeHandler/PropertyChangeMapper.js +1 -1
  26. package/src/sap/suite/ui/commons/imageeditor/CropCustomShapeHistoryItem.js +1 -1
  27. package/src/sap/suite/ui/commons/imageeditor/CropEllipseHistoryItem.js +1 -1
  28. package/src/sap/suite/ui/commons/imageeditor/CropRectangleHistoryItem.js +1 -1
  29. package/src/sap/suite/ui/commons/imageeditor/CustomSizeItem.js +1 -1
  30. package/src/sap/suite/ui/commons/imageeditor/FilterHistoryItem.js +1 -1
  31. package/src/sap/suite/ui/commons/imageeditor/FlipHistoryItem.js +1 -1
  32. package/src/sap/suite/ui/commons/imageeditor/HistoryItem.js +1 -1
  33. package/src/sap/suite/ui/commons/imageeditor/ImageEditor.js +1 -1
  34. package/src/sap/suite/ui/commons/imageeditor/ImageEditorContainer.js +1 -1
  35. package/src/sap/suite/ui/commons/imageeditor/ImageEditorResponsiveContainer.js +1 -1
  36. package/src/sap/suite/ui/commons/imageeditor/ResizeHistoryItem.js +1 -1
  37. package/src/sap/suite/ui/commons/imageeditor/RotateHistoryItem.js +1 -1
  38. package/src/sap/suite/ui/commons/library.js +1 -1
  39. package/src/sap/suite/ui/commons/statusindicator/Circle.js +1 -1
  40. package/src/sap/suite/ui/commons/statusindicator/CustomShape.js +1 -1
  41. package/src/sap/suite/ui/commons/statusindicator/DiscreteThreshold.js +1 -1
  42. package/src/sap/suite/ui/commons/statusindicator/FillingOption.js +1 -1
  43. package/src/sap/suite/ui/commons/statusindicator/LibraryShape.js +1 -1
  44. package/src/sap/suite/ui/commons/statusindicator/Path.js +1 -1
  45. package/src/sap/suite/ui/commons/statusindicator/PropertyThreshold.js +1 -1
  46. package/src/sap/suite/ui/commons/statusindicator/Rectangle.js +1 -1
  47. package/src/sap/suite/ui/commons/statusindicator/Shape.js +1 -1
  48. package/src/sap/suite/ui/commons/statusindicator/ShapeGroup.js +1 -1
  49. package/src/sap/suite/ui/commons/statusindicator/SimpleShape.js +1 -1
  50. package/src/sap/suite/ui/commons/statusindicator/StatusIndicator.js +1 -1
  51. package/src/sap/suite/ui/commons/taccount/TAccount.js +1 -1
  52. package/src/sap/suite/ui/commons/taccount/TAccountGroup.js +1 -1
  53. package/src/sap/suite/ui/commons/taccount/TAccountItem.js +1 -1
  54. package/src/sap/suite/ui/commons/taccount/TAccountItemProperty.js +1 -1
  55. package/src/sap/suite/ui/commons/taccount/TAccountPanel.js +1 -1
@@ -28,7 +28,7 @@ sap.ui.define([
28
28
  "sap/base/i18n/Localization",
29
29
  "./CollaborationManagerService",
30
30
  "sap/m/FlexItemData"
31
- ], function (Log, Core, URLListValidator, CollaborationHelper, BaseHelperService, Element, ContactHelper, Device, CollaborationCardHelper, Fragment, MessageBox, Library, Popover, HBox, VBox, MessageStrip, Button, CollaborationContactInfoHelper, sapMLibrary, FlexBox, Localization, CollaborationManagerService, FlexItemData) {
31
+ ], function(Log, Core, URLListValidator, CollaborationHelper, BaseHelperService, Element, ContactHelper, Device, CollaborationCardHelper, Fragment, MessageBox, Library, Popover, HBox, VBox, MessageStrip, Button, CollaborationContactInfoHelper, sapMLibrary, FlexBox, Localization, CollaborationManagerService, FlexItemData) {
32
32
  "use strict";
33
33
 
34
34
  /**
@@ -41,7 +41,7 @@ sap.ui.define([
41
41
  * @experimental Since 1.108
42
42
  */
43
43
  var TeamsHelperService = BaseHelperService.extend("sap.suite.ui.commons.collaboration.TeamsHelperService", {
44
- constructor: function (oProviderConfig) {
44
+ constructor: function(oProviderConfig) {
45
45
  this._providerConfig = oProviderConfig;
46
46
  this._providerConfig.shareAsLinkUrl = "https://teams.microsoft.com/share";
47
47
  this._getShareAsTabUrl().then(function(sShareAsTabUrl) {
@@ -53,18 +53,32 @@ sap.ui.define([
53
53
  /**
54
54
  * sTeamsAppID is hardcoded as of now, will be changed when app is published at org level.
55
55
  */
56
- var COLLABORATION_MSTEAMS_APPID = 'db5b69c6-0430-4ae1-8d6e-a65c2220b50c';
57
- var oLogger = Log.getLogger("sap.suite.ui.commons.collaboration.TeamsHelperService");
58
- var CARD_URL_PREFIX = "https://saps4hana.azure-api.net/bot/redirect?target-url=";
59
-
60
- var oResourceBundle = Library.getResourceBundleFor("sap.suite.ui.commons");
61
- var PARAM_SAP_CARD_INFO = "info";
62
-
63
- var oBusyDailog;
64
- let iTimeoutId;
65
- const AUTO_CLOSE_BUSY_DIALOG_TIME = 60 * 1000; // 1 sec = 1000, here 60 sec
66
- var oTeamsParams = {};
67
- var windowWidthAndHeight = "width=720,height=720";
56
+ const COLLABORATION_MSTEAMS_APPID = 'db5b69c6-0430-4ae1-8d6e-a65c2220b50c';
57
+ const oLogger = Log.getLogger("sap.suite.ui.commons.collaboration.TeamsHelperService");
58
+ const CARD_URL_PREFIX = "https://saps4hana.azure-api.net/bot/redirect?target-url=";
59
+ const oResourceBundle = Library.getResourceBundleFor("sap.suite.ui.commons");
60
+ const PARAM_SAP_CARD_INFO = "info";
61
+
62
+ let oBusyDialog;
63
+ let iBusyDialogTimeoutId;
64
+ const AUTO_CLOSE_BUSY_DIALOG_TIME = 60 * 1000; //60 sec
65
+ let oTeamsParams = {};
66
+ const windowWidthAndHeight = "width=720,height=720";
67
+ const validDomains = [
68
+ "*.s4hana.ondemand.com",
69
+ "*.*.s4hana.ondemand.com",
70
+ "*.*.*.s4hana.ondemand.com",
71
+ "*.cloud.sap",
72
+ "*.*.cloud.sap",
73
+ "*.*.*.cloud.sap",
74
+ "*.sapcloud.cn",
75
+ "*.*.sapcloud.cn",
76
+ "*.*.*.sapcloud.cn",
77
+ "*.saps4hanacloud.cn",
78
+ "*.*.saps4hanacloud.cn",
79
+ "*.*.*.saps4hanacloud.cn",
80
+ "*.sap.com"
81
+ ];
68
82
 
69
83
  /**
70
84
  * Gives list of all Collaboration Options
@@ -77,7 +91,7 @@ sap.ui.define([
77
91
  * @ui5-restricted
78
92
  * @experimental Since 1.108
79
93
  */
80
- TeamsHelperService.prototype.getOptions = function (oParams) {
94
+ TeamsHelperService.prototype.getOptions = function(oParams) {
81
95
  oTeamsParams = {
82
96
  isShareAsLinkEnabled: (oParams && typeof oParams.isShareAsLinkEnabled !== 'undefined') ? oParams.isShareAsLinkEnabled : true,
83
97
  isShareAsTabEnabled: (oParams && typeof oParams.isShareAsTabEnabled !== 'undefined') ? oParams.isShareAsTabEnabled : true,
@@ -195,7 +209,7 @@ sap.ui.define([
195
209
  * @ui5-restricted
196
210
  * @experimental Since 1.108
197
211
  */
198
- TeamsHelperService.prototype.share = function (oOption, oParams) {
212
+ TeamsHelperService.prototype.share = function(oOption, oParams) {
199
213
 
200
214
  if (!oParams.url) {
201
215
  oLogger.error("url is not supplied in object so terminating Click");
@@ -236,7 +250,7 @@ sap.ui.define([
236
250
  * @ui5-restricted
237
251
  * @experimental Since 1.108
238
252
  */
239
- TeamsHelperService.prototype._shareAsChat = function (oParams) {
253
+ TeamsHelperService.prototype._shareAsChat = function(oParams) {
240
254
  var newWindow = window.open(
241
255
  "",
242
256
  "_blank",
@@ -249,13 +263,13 @@ sap.ui.define([
249
263
 
250
264
  newWindow.opener = null;
251
265
  if (oParams.minifyUrlForChat) {
252
- CollaborationHelper.compactHash(oParams.url, []).then(async function (sShortURL) {
266
+ CollaborationHelper.compactHash(oParams.url, []).then(async function(sShortURL) {
253
267
  var sModifiedUrl = await this._modifyUrlForNavigationContext(oParams.url, sShortURL.url);
254
- newWindow.location = this._providerConfig.shareAsLinkUrl + "?msgText=" + encodeURIComponent(sMessage) + "&preview=false" + "&href=" + encodeURIComponent(sModifiedUrl);
255
- }.bind(this));
256
- } else {
257
- newWindow.location = this._providerConfig.shareAsLinkUrl + "?msgText=" + encodeURIComponent(sMessage) + "&preview=false" + "&href=" + encodeURIComponent(oParams.url);
258
- }
268
+ newWindow.location = this._providerConfig.shareAsLinkUrl + "?msgText=" + encodeURIComponent(sMessage) + "&preview=false" + "&href=" + encodeURIComponent(sModifiedUrl);
269
+ }.bind(this));
270
+ } else {
271
+ newWindow.location = this._providerConfig.shareAsLinkUrl + "?msgText=" + encodeURIComponent(sMessage) + "&preview=false" + "&href=" + encodeURIComponent(oParams.url);
272
+ }
259
273
  };
260
274
 
261
275
  /**
@@ -297,7 +311,7 @@ sap.ui.define([
297
311
  * @ui5-restricted
298
312
  * @experimental Since 1.108
299
313
  */
300
- TeamsHelperService.prototype._shareAsTab = async function (oParams) {
314
+ TeamsHelperService.prototype._shareAsTab = async function(oParams) {
301
315
  var sAppUri = await this._modifyUrlForShareAsTab(oParams.url, "MST:T");
302
316
  var oData = {
303
317
  "subEntityId": {
@@ -308,19 +322,19 @@ sap.ui.define([
308
322
  }
309
323
  };
310
324
  if (oParams.minifyUrlForChat) {
311
- CollaborationHelper.compactHash(sAppUri, []).then(async function (sShortURL) {
325
+ CollaborationHelper.compactHash(sAppUri, []).then(async function(sShortURL) {
312
326
  var sModifiedUrl = await this._modifyUrlForNavigationContext(sAppUri, sShortURL.url);
313
- oData.subEntityId.url = await this._addNavmodeInUrl(sModifiedUrl, 'explace');
314
- var sURL = this._providerConfig.shareAsTabUrl + "?&context=" + encodeURIComponent(JSON.stringify(oData));
315
- sap.m.URLHelper.redirect(sURL, true);
316
- }.bind(this));
317
- } else {
318
- var sURL = this._providerConfig.shareAsTabUrl + "?&context=" + encodeURIComponent(JSON.stringify(oData));
319
- sap.m.URLHelper.redirect(sURL, true);
320
- }
327
+ oData.subEntityId.url = await this._addNavmodeInUrl(sModifiedUrl, 'explace');
328
+ var sURL = this._providerConfig.shareAsTabUrl + "?&context=" + encodeURIComponent(JSON.stringify(oData));
329
+ sap.m.URLHelper.redirect(sURL, true);
330
+ }.bind(this));
331
+ } else {
332
+ var sURL = this._providerConfig.shareAsTabUrl + "?&context=" + encodeURIComponent(JSON.stringify(oData));
333
+ sap.m.URLHelper.redirect(sURL, true);
334
+ }
321
335
  };
322
336
 
323
- TeamsHelperService.prototype._addNavmodeInUrl = function (sURL, sNavMode) {
337
+ TeamsHelperService.prototype._addNavmodeInUrl = function(sURL, sNavMode) {
324
338
  const UshellContainer = sap.ui.require("sap/ushell/Container");
325
339
  return UshellContainer && UshellContainer.getServiceAsync("URLParsing").then(function(oURLParsing) {
326
340
  var sAppUri = sURL;
@@ -347,7 +361,7 @@ sap.ui.define([
347
361
  var oHashPartOfUri = oURLParsing.parseShellHash(sAppUri.substring(iIndexOfHash));
348
362
  var iParamsCount = Object.keys(oHashPartOfUri.params).length;
349
363
  var oUrl = new URL(sURL);
350
- if (iParamsCount > 0){
364
+ if (iParamsCount > 0) {
351
365
  if (!oUrl.searchParams.has("sap-collaboration-teams")) {
352
366
  oUrl.searchParams.set("sap-collaboration-teams", "true");
353
367
  } else {
@@ -368,125 +382,256 @@ sap.ui.define([
368
382
  * @ui5-restricted
369
383
  * @experimental Since 1.108
370
384
  */
371
- TeamsHelperService.prototype._shareAsCard = function (oParams) {
372
- if (oParams.cardId && oParams.cardId.length > 0 && oParams.cardManifest && this.isFeatureFlagEnabled()) {
373
- // Card Id and Card Manifest Passed. It will show busy helper and store card into DB.
374
- oParams.cardManifest["rtl"]= Localization.getRTL();
375
- Fragment.load({
376
- name: "sap.suite.ui.commons.collaboration.CollaborationBusyDialog",
377
- controller: this,
378
- type: "XML"
379
- }).then(function (oDialog) {
380
- oBusyDailog = oDialog;
381
- oBusyDailog.open();
382
- iTimeoutId = setTimeout(function() {
383
- oBusyDailog.close();
384
- oBusyDailog.destroy();
385
- }, AUTO_CLOSE_BUSY_DIALOG_TIME);
386
- CollaborationCardHelper.postCard(oParams.cardId, oParams.cardManifest).then(function (response) {
387
- var bSuccessScenario = true;
388
- var oResponseData = {
389
- cardId: response.card_id,
390
- version: response.version
391
- };
392
- if (response.error) {
393
- if (response.error.code === "APS_UI_MSG/001") {
394
- // Card ID with same CardManifest detail is present so it will get version and open Teams Dialog
395
- bSuccessScenario = true;
396
- oResponseData.cardId = oParams.cardId;
397
- if (response.error.message.length > 0){
398
- try {
399
- var sCardVersion = JSON.parse(atob(response.error.message)).version;
400
- oResponseData.version = sCardVersion;
401
- } catch (e) {
402
- bSuccessScenario = false;
403
- }
404
- }
405
- } else {
406
- bSuccessScenario = false;
407
- }
408
- }
409
- if (bSuccessScenario) {
410
- this._updateUrl(oParams, oResponseData);
411
- } else {
412
- MessageBox.error(oResourceBundle.getText("SAVE_CARD_ERROR"));
413
- this._closeBusyDailog();
414
- }
415
- }.bind(this));
416
- }.bind(this));
417
- } else {
385
+ TeamsHelperService.prototype._shareAsCard = async function (oParams) {
386
+ if (!oParams?.cardId || !oParams.cardId.length || !oParams.cardManifest || !this.isFeatureFlagEnabled()) {
418
387
  // Base Card to unfurl
419
388
  this._updateUrl(oParams, {});
389
+ return;
390
+ }
391
+ let oCardData = {};
392
+ try {
393
+ // Card Id and Card Manifest Passed. It will show busy helper and store card into DB.
394
+ try {
395
+ const oDialog = await Fragment.load({
396
+ name: "sap.suite.ui.commons.collaboration.CollaborationBusyDialog",
397
+ controller: this,
398
+ type: "XML"
399
+ });
400
+ oBusyDialog = oDialog;
401
+ oBusyDialog.open();
402
+
403
+ // Automatically close the dialog after a fixed time
404
+ iBusyDialogTimeoutId = setTimeout(() => {
405
+ oBusyDialog.close();
406
+ oBusyDialog.destroy();
407
+ }, AUTO_CLOSE_BUSY_DIALOG_TIME);
408
+ } catch (err) {
409
+ oLogger.error("Fragment load failed: " + err.message);
410
+ }
411
+
412
+ oCardData = await this._buildCardInfo(oParams);
413
+ } catch (err) {
414
+ oLogger.error("buildCardInfo failed: " + err.message);
415
+ } finally {
416
+ if (oCardData && Object.keys(oCardData).length === 0) {
417
+ oLogger.warn("Card info could not be saved.");
418
+ }
419
+
420
+ // Auth/Base card to unfurl
421
+ this._updateUrl(oParams, oCardData);
420
422
  }
421
423
  };
422
424
 
423
- TeamsHelperService.prototype._updateUrl = async function(oParams, oResponseData) {
424
- if (oParams.minifyUrlForChat) {
425
- CollaborationHelper.compactHash(oParams.url, []).then(async function (sShortURL) {
426
- var sModifiedUrl = await this._modifyUrlForNavigationContext(oParams.url, sShortURL.url);
427
- var sUrlForTab = await this._modifyUrlForShareAsTab(oParams.url, "MST:C");
428
- var sShortURLTab = await CollaborationHelper.compactHash(sUrlForTab, []);
429
- var sStageViewHash = sShortURLTab.url.split("sap-url-hash=")[1];
430
- // Scenario in which URL shortening is enabled, but the iAppState is set to Transient.
431
- if (sStageViewHash) {
432
- sModifiedUrl += `,${sStageViewHash}`;
433
- } else {
434
- sUrlForTab = await this._modifyUrlForShareAsTab(sModifiedUrl, "MST:C");
435
- sModifiedUrl = await this._addNavmodeInUrl(sUrlForTab, 'inplace');
425
+ /**
426
+ * Builds card information for a Teams collaboration card.
427
+ * This method calls the postCard API to create or retrieve card info.
428
+ * - On success: returns { cardId, version }.
429
+ * - On business error (e.g., APS_UI_MSG/001 when card already exists):
430
+ * tries to recover the card version from the error message and still returns { cardId, version }.
431
+ * - On other business errors: returns an empty object {}.
432
+ * - On technical errors (network/CSRF/JSON parsing): the promise rejects and should be caught by the caller.
433
+ *
434
+ * @param {Object} oParams - Parameters for building the card
435
+ * @param {string} oParams.cardId - The card ID
436
+ * @param {Object} oParams.cardManifest - The card manifest metadata
437
+ * @returns {Promise<Object>} - Resolves with card information { cardId, version } or {} if not available
438
+ * (may reject on technical errors)
439
+ */
440
+ TeamsHelperService.prototype._buildCardInfo = async function (oParams) {
441
+ // Set right-to-left layout based on localization settings
442
+ oParams.cardManifest.rtl = Localization.getRTL();
443
+ const postCardResponse = await CollaborationCardHelper.postCard(oParams.cardId, oParams.cardManifest);
444
+
445
+ let oCardData = {
446
+ cardId: postCardResponse.card_id,
447
+ version: postCardResponse.version
448
+ };
449
+
450
+ // Handle special error scenario where the card already exists
451
+ if (postCardResponse.error) {
452
+ if (postCardResponse.error.code === "APS_UI_MSG/001") {
453
+ // Card ID with same CardManifest detail is present so it will get version and open Teams Dialog
454
+ oCardData.cardId = oParams.cardId;
455
+ if (postCardResponse.error.message.length > 0){
456
+ try {
457
+ const sCardVersion = JSON.parse(atob(postCardResponse.error.message)).version;
458
+ oCardData.version = sCardVersion;
459
+ } catch (e) {
460
+ oCardData = {};
461
+ }
436
462
  }
437
- this._closeBusyDialogAndOpenTeamsDialog(sModifiedUrl, oParams, oResponseData);
438
- }.bind(this));
439
- } else {
440
- var sModifiedUrl = oParams.url;
441
- if (oTeamsParams.isShareAsTabEnabled && this._providerConfig.isShareAsTabEnabled) {
442
- var sUrlForTab = await this._modifyUrlForShareAsTab(sModifiedUrl, "MST:C");
463
+ } else {
464
+ oCardData = {};
465
+ }
466
+ }
467
+ return oCardData;
468
+ };
469
+
470
+ /**
471
+ * Updates the URL based on parameters, optionally minifying it for chat,
472
+ * and then opens the Teams dialog with the processed URL.
473
+ *
474
+ * @param {Object} oParams - Parameters including original URL and flags.
475
+ * @param {Object} oCardData - The card data containing cardId and version.
476
+ */
477
+ TeamsHelperService.prototype._updateUrl = async function(oParams, oCardData) {
478
+ let sModifiedUrl = oParams?.url || window.location.href;
479
+ try {
480
+ if (oParams.minifyUrlForChat) {
481
+ sModifiedUrl = await this._getModifiedUrlForSharing(oParams);
482
+ } else if (oTeamsParams.isShareAsTabEnabled && this._providerConfig.isShareAsTabEnabled) {
483
+ const sUrlForTab = await this._modifyUrlForShareAsTab(sModifiedUrl, "MST:C");
443
484
  sModifiedUrl = await this._addNavmodeInUrl(sUrlForTab, 'inplace');
444
485
  }
445
- this._closeBusyDialogAndOpenTeamsDialog(sModifiedUrl, oParams, oResponseData);
486
+ } catch (error) {
487
+ oLogger.error("Error while modifying URL for sharing: " + error.message);
488
+ } finally {
489
+ // Close busy dialog and open the Teams dialog with the final URL
490
+ this._closeBusyDialogAndOpenTeamsDialog(sModifiedUrl, oParams, oCardData);
446
491
  }
447
492
  };
448
493
 
449
- TeamsHelperService.prototype._closeBusyDailog = function() {
450
- if (oBusyDailog) {
451
- oBusyDailog.close();
452
- oBusyDailog.destroy();
453
- clearTimeout(iTimeoutId);
494
+ /**
495
+ * Generates a modified URL for sharing in Microsoft Teams.
496
+ * @param {Object} oParams - Parameters containing the original URL and flags.
497
+ * @returns {Promise<string>} - A fully processed URL ready to be used for sharing.
498
+ */
499
+ TeamsHelperService.prototype._getModifiedUrlForSharing = async function(oParams) {
500
+ const sShortURL = await CollaborationHelper.compactHash(oParams.url, []);
501
+ let sModifiedUrl = await this._modifyUrlForNavigationContext(oParams.url, sShortURL.url);
502
+ let sUrlForTab = await this._modifyUrlForShareAsTab(oParams.url, "MST:C");
503
+ const sShortURLTab = await CollaborationHelper.compactHash(sUrlForTab, []);
504
+ const sStageViewHash = sShortURLTab.url.split("sap-url-hash=")[1];
505
+
506
+ if (sStageViewHash) {
507
+ sModifiedUrl += `,${sStageViewHash}`;
508
+ } else {
509
+ sUrlForTab = await this._modifyUrlForShareAsTab(sModifiedUrl, "MST:C");
510
+ sModifiedUrl = await this._addNavmodeInUrl(sUrlForTab, 'inplace');
454
511
  }
512
+
513
+ return sModifiedUrl;
455
514
  };
456
515
 
457
- TeamsHelperService.prototype._closeBusyDialogAndOpenTeamsDialog = function(sUrl, oParams, response) {
458
- this._closeBusyDailog();
459
- var newWindow = window.open(
516
+ /**
517
+ * Closes and destroys the busy dialog, and clears timeout.
518
+ */
519
+ TeamsHelperService.prototype._closeBusyDialog = function() {
520
+ if (oBusyDialog) {
521
+ oBusyDialog.close();
522
+ oBusyDialog.destroy();
523
+ clearTimeout(iBusyDialogTimeoutId);
524
+ }
525
+ };
526
+
527
+ /**
528
+ * Closes the busy dialog and opens a new Teams dialog window with card info in the URL.
529
+ *
530
+ * @param {string} sUrl - URL with card info.
531
+ * @param {Object} oParams - Parameters including original URL and flags.
532
+ * @param {Object} oCardData - The card data containing cardId and version.
533
+ */
534
+ TeamsHelperService.prototype._closeBusyDialogAndOpenTeamsDialog = function(sUrl, oParams, oCardData) {
535
+ this._closeBusyDialog();
536
+ const newWindow = window.open(
460
537
  "",
461
538
  "_blank",
462
539
  windowWidthAndHeight
463
540
  );
464
541
  newWindow.opener = null;
465
- newWindow.location = this._addCardParamsInUrl(sUrl, oParams.appTitle, response);
542
+ newWindow.location = this._generateShareAsCardUrl(sUrl, oParams.appTitle, oCardData);
543
+ };
544
+
545
+ /**
546
+ * Converts a wildcard pattern to a regular expression
547
+ * @param {string} pattern - The wildcard pattern to convert
548
+ * @returns {RegExp} The resulting regular expression
549
+ */
550
+ TeamsHelperService.prototype._wildcardToRegExp = function(pattern) {
551
+ return new RegExp('^' + pattern.split('*').map(function(part) {
552
+ return part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
553
+ }).join('[^.]+') + '$', 'i');
466
554
  };
467
555
 
468
- TeamsHelperService.prototype._addCardParamsInUrl = function(sUrl, sAppTitle, response) {
469
- var aInfoField = [
470
- response.cardId || "",
471
- response.version || "",
472
- encodeURIComponent(sAppTitle)
473
- ].filter(Boolean);
474
- sUrl += `&${PARAM_SAP_CARD_INFO}=${aInfoField.join(",")}`;
475
- const encodeUrl = encodeURIComponent(sUrl);
556
+ /**
557
+ * Checks if a given URL's domain is valid according to the validDomains list
558
+ * @param {string} url - The URL to check
559
+ * @returns {boolean} True if the domain is valid, false otherwise
560
+ */
561
+ TeamsHelperService.prototype._isValidDomain = function(url) {
562
+ try {
563
+ const domain = new URL(url).hostname;
564
+ return validDomains.some((pattern) =>
565
+ this._wildcardToRegExp(pattern).test(domain)
566
+ );
567
+ } catch (e) {
568
+ return false;
569
+ }
570
+ };
571
+
572
+ /**
573
+ * Generates the card info URL based on the provided parameters.
574
+ *
575
+ * @param {string} sUrl - The base URL to be processed.
576
+ * @param {Object} oParams - An object containing additional parameters.
577
+ * @param {string} oParams.appTitle - The title of the application.
578
+ * @param {Object} oCardData - The card data object.
579
+ * @returns {string} The processed URL with card info parameters.
580
+ */
581
+ TeamsHelperService.prototype._getCardInfoUrl = function(sUrl, oParams, oCardData) {
582
+ const isValid = this._isValidDomain(sUrl);
583
+ const sAppTitle = oParams.appTitle;
584
+ if (isValid) {
585
+ return this._generateCardUnfurlingUrl(sUrl, oCardData, { appTitle: sAppTitle });
586
+ } else {
587
+ return this._generateShareAsCardUrl(sUrl, sAppTitle, oCardData);
588
+ }
589
+ };
590
+
591
+ /**
592
+ * Generates the full shareable Teams URL with card info.
593
+ *
594
+ * @param {string} sUrl - The card URL.
595
+ * @param {string} sAppTitle - The application title.
596
+ * @param {Object} oCardData - The card data containing cardId and version.
597
+ * @returns {string} Teams shareable URL.
598
+ */
599
+ TeamsHelperService.prototype._generateShareAsCardUrl = function(sUrl, sAppTitle, oCardData) {
600
+ const sCardInfoUrl = this._generateCardUnfurlingUrl(sUrl, oCardData, { appTitle: sAppTitle });
601
+
476
602
  // add the domain prefix to solve link unfurling issue for systems with different domain patterns
477
- return `${this._providerConfig.shareAsLinkUrl}?href=${encodeURIComponent(CARD_URL_PREFIX + encodeUrl)}`;
603
+ return `${this._providerConfig.shareAsLinkUrl}?href=${encodeURIComponent(CARD_URL_PREFIX + encodeURIComponent(sCardInfoUrl))}`;
604
+ };
605
+
606
+ /**
607
+ * Generates the unfurling URL with card info.
608
+ * Appends the SAP card info parameters (cardId, version, appTitle) to the given URL.
609
+ *
610
+ * @param {string} cardUrl - The base card URL to which the parameter will be appended.
611
+ * @param {Object} oCardData - The card data object containing cardId and version.
612
+ * @param {Object} oParams - The parameter object containing appTitle.
613
+ * @returns {string} The updated URL with the appended sap-card-info query parameter.
614
+ */
615
+ TeamsHelperService.prototype._generateCardUnfurlingUrl = function(cardUrl, oCardData, oParams) {
616
+ const infoFields = [
617
+ oCardData.cardId || "",
618
+ oCardData.version || "",
619
+ encodeURIComponent(oParams.appTitle || "")
620
+ ].filter(Boolean);
621
+
622
+ return `${cardUrl}&${PARAM_SAP_CARD_INFO}=${infoFields.join(",")}`;
478
623
  };
479
624
 
480
- TeamsHelperService.prototype._getShareAsTabUrl = function () {
625
+ TeamsHelperService.prototype._getShareAsTabUrl = function() {
481
626
  return this._getApplicationID().then(function(sTeamsAppID) {
482
627
  return "https://teams.microsoft.com/l/entity/" + sTeamsAppID + "/tab";
483
628
  });
484
629
  };
485
630
 
486
- TeamsHelperService.prototype._getApplicationID = function () {
631
+ TeamsHelperService.prototype._getApplicationID = function() {
487
632
  const UshellContainer = sap.ui.require("sap/ushell/Container");
488
633
  return UshellContainer && UshellContainer.getServiceAsync("URLParsing").then(function(oURLParsing) {
489
- return CollaborationHelper._getCurrentUrl().then(function (sCurrentUrl) {
634
+ return CollaborationHelper._getCurrentUrl().then(function(sCurrentUrl) {
490
635
  var sBeforeHashURL = sCurrentUrl.split("#")[0];
491
636
  if (sBeforeHashURL.indexOf('?') !== -1) {
492
637
  var oParsedUrl = oURLParsing && oURLParsing.parseParameters(sBeforeHashURL.substring(sBeforeHashURL.indexOf('?')));
@@ -509,7 +654,7 @@ sap.ui.define([
509
654
  * @returns {boolean} If set to true, Adaptive Card Generation is enabled
510
655
  * @private
511
656
  */
512
- TeamsHelperService.prototype.isFeatureFlagEnabled = function () {
657
+ TeamsHelperService.prototype.isFeatureFlagEnabled = function() {
513
658
  const bIsShareAsCardEnabled = this._providerConfig.isShareAsCardEnabled;
514
659
  return bIsShareAsCardEnabled === "AUTHENABLE";
515
660
  };
@@ -521,7 +666,7 @@ sap.ui.define([
521
666
  * @private
522
667
  */
523
668
 
524
- TeamsHelperService.prototype.isContactsCollaborationSupported = function () {
669
+ TeamsHelperService.prototype.isContactsCollaborationSupported = function() {
525
670
  return true;
526
671
  };
527
672
 
@@ -534,7 +679,7 @@ sap.ui.define([
534
679
  * @private
535
680
  */
536
681
 
537
- TeamsHelperService.prototype.enableContactsCollaboration = async function (sEmail, oParams) {
682
+ TeamsHelperService.prototype.enableContactsCollaboration = async function(sEmail, oParams) {
538
683
  const isTeamMode = await CollaborationHelper.isTeamsModeActive();
539
684
  const isContactServiceAvailable = await CollaborationContactInfoHelper.fetchServiceStatus();
540
685
  if (sEmail && isContactServiceAvailable.value && isContactServiceAvailable.value && isContactServiceAvailable.value[0].FetchContacts === "Active") {
@@ -563,7 +708,7 @@ sap.ui.define([
563
708
  * @private
564
709
  */
565
710
 
566
- TeamsHelperService.prototype.getTeamsContactCollabOptions = async function () {
711
+ TeamsHelperService.prototype.getTeamsContactCollabOptions = async function() {
567
712
  const isTeamMode = await CollaborationHelper.isTeamsModeActive();
568
713
  if (isTeamMode || this._providerConfig.isDirectCommunicationEnabled !== "ENABLED") {
569
714
  return Promise.reject();
@@ -581,7 +726,7 @@ sap.ui.define([
581
726
  * @private
582
727
  */
583
728
 
584
- TeamsHelperService.prototype.getTeamsContactStatus = async function (sEmail) {
729
+ TeamsHelperService.prototype.getTeamsContactStatus = async function(sEmail) {
585
730
  const isTeamMode = await CollaborationHelper.isTeamsModeActive();
586
731
  if (isTeamMode) {
587
732
  return Promise.reject();
@@ -600,17 +745,18 @@ sap.ui.define([
600
745
  * @param { object } oData Title and data to share
601
746
  * @param { string } oSource The source to which the popover is rendered.
602
747
  * @param { boolean } isLink Indicates the data is a URL or not.
748
+ * @param { object } oCollaborationOptionsConfig Configuration options for collaboration (e.g., shareToTeams, shareToEmail, shareToCM).
603
749
  *
604
750
  */
605
751
  TeamsHelperService.prototype.getCollaborationPopover = function(oParams, oData, oSource, isLink, oCollaborationOptionsConfig) {
606
752
  if (oData.data === undefined || oData.data.trim() === "") {
607
- oLogger.error("Popover cannnot be opened without data");
608
- return;
609
- }
753
+ oLogger.error("Popover cannnot be opened without data");
754
+ return;
755
+ }
610
756
  var oTeamsParams = {
611
757
  isShareAsLinkEnabled: (oParams && typeof oParams.isShareAsLinkEnabled !== 'undefined') ? oParams.isShareAsLinkEnabled : true
612
758
  };
613
- var oCollaborationOptionsConfig = {
759
+ var oCollaborationOptionsCfg = {
614
760
  shareToTeams: oCollaborationOptionsConfig && typeof oCollaborationOptionsConfig.shareToTeams !== "undefined" ? oCollaborationOptionsConfig.shareToTeams : true,
615
761
  shareToEmail: oCollaborationOptionsConfig && typeof oCollaborationOptionsConfig.shareToEmail !== "undefined" ? oCollaborationOptionsConfig.shareToEmail : true,
616
762
  shareToCM: oCollaborationOptionsConfig && typeof oCollaborationOptionsConfig.shareToCM !== "undefined" ? oCollaborationOptionsConfig.shareToCM : false
@@ -618,7 +764,7 @@ sap.ui.define([
618
764
  var aOptions = [];
619
765
  if (Device.system.desktop) {
620
766
  if (oTeamsParams.isShareAsLinkEnabled) {
621
- if (this._providerConfig.isShareAsLinkEnabled === "X" && oCollaborationOptionsConfig.shareToTeams) {
767
+ if (this._providerConfig.isShareAsLinkEnabled === "X" && oCollaborationOptionsCfg.shareToTeams) {
622
768
  aOptions.push({
623
769
  "text": oResourceBundle.getText("COLLABORATION_POPOVER_TEAMS"),
624
770
  "icon": "sap-icon://discussion",
@@ -634,7 +780,7 @@ sap.ui.define([
634
780
  } else {
635
781
  oLogger.info("Share as Chat option is not supported in Phone and Tablet");
636
782
  }
637
- if (oCollaborationOptionsConfig.shareToEmail) {
783
+ if (oCollaborationOptionsCfg.shareToEmail) {
638
784
  aOptions.push({
639
785
  "text": oResourceBundle.getText("COLLABORATION_POPOVER_MAIL"),
640
786
  "icon": "sap-icon://email",
@@ -643,7 +789,7 @@ sap.ui.define([
643
789
  }
644
790
  this.oCollaborationManager = new CollaborationManagerService();
645
791
  var oCMOption = this.oCollaborationManager.getOptions();
646
- if (oCMOption && oCollaborationOptionsConfig.shareToCM) {
792
+ if (oCMOption && oCollaborationOptionsCfg.shareToCM) {
647
793
  aOptions.push({
648
794
  "text": oCMOption.text,
649
795
  "icon": oCMOption.icon,
@@ -663,9 +809,9 @@ sap.ui.define([
663
809
  * @param { object } oData Title and data to share
664
810
  * @param { array } aOptions Array of available options
665
811
  * @param { boolean } isLink Indicates the data is a URL or not.
666
- * @returns Returns the final Popover to the control.
812
+ * @returns {sap.m.Popover} Returns the final Popover to the control.
667
813
  */
668
- TeamsHelperService.prototype._getPopover = function(oData,aOptions,isLink) {
814
+ TeamsHelperService.prototype._getPopover = function(oData, aOptions, isLink) {
669
815
  var oCollaborationPopover = new Popover({
670
816
  showHeader: false,
671
817
  placement: oData.placement ? oData.placement : "Auto",
@@ -681,10 +827,11 @@ sap.ui.define([
681
827
  * @param { object } oData Title and data to share
682
828
  * @param { array } aOptions Array of available options
683
829
  * @param { boolean } isLink Indicates the data is a URL or not.
830
+ * @returns {sap.m.FlexBox} Returns the FlexBox containing the popover content.
684
831
  */
685
832
  TeamsHelperService.prototype._getPopoverContent = function(oData, aOptions, isLink) {
686
833
  var oMainFBox = new FlexBox({
687
- items:[],
834
+ items: [],
688
835
  direction: sapMLibrary.FlexDirection.Column
689
836
  });
690
837
  var oOptionFBox = new FlexBox({
@@ -694,8 +841,8 @@ sap.ui.define([
694
841
  });
695
842
  aOptions.forEach((oOption) => {
696
843
  var button = new Button({
697
- text:oOption.text,
698
- icon:oOption.icon,
844
+ text: oOption.text,
845
+ icon: oOption.icon,
699
846
  width: oData.sFormat === "Horizontal" && aOptions.length === 3 ? "120px" : "180px",
700
847
  press: (oEvent) => {
701
848
  oEvent.getSource().getParent().getParent().getParent().close();
@@ -722,7 +869,7 @@ sap.ui.define([
722
869
  new Button({
723
870
  text: oResourceBundle.getText("COLLABORATION_POPOVER_COPYURL_BUTTON"),
724
871
  width: oData.sFormat === "Vertical" ? "150px" : "",
725
- press: async() => {
872
+ press: async () => {
726
873
  await this._writeToClipBoard(oData.data);
727
874
  }
728
875
  }).addStyleClass("sapUiTinyMarginBeginEnd")
@@ -756,13 +903,13 @@ sap.ui.define([
756
903
  * @param { text } sText Text to copy to the cilpboard
757
904
  * Writes the given URL to the clipboard
758
905
  */
759
- TeamsHelperService.prototype._writeToClipBoard = async function (sText) {
906
+ TeamsHelperService.prototype._writeToClipBoard = async function(sText) {
760
907
  try {
761
- await navigator.clipboard.writeText(sText);
908
+ await window.navigator.clipboard.writeText(sText);
762
909
  } catch (e) {
763
910
  oLogger.info(e);
764
911
  }
765
- }
912
+ };
766
913
 
767
914
  /**
768
915
  *
@@ -773,23 +920,23 @@ sap.ui.define([
773
920
  TeamsHelperService.prototype._shareData = function(oData, oOption, isLink) {
774
921
  if (oOption.key === "COLLABORATION_POPOVER_TEAMS") {
775
922
  if (isLink) {
776
- var oShareData = {
923
+ var oShareDataLink = {
777
924
  url: oData.data,
778
925
  appTitle: oData.title ? oData.title : "",
779
926
  subTitle: "",
780
927
  minifyUrlForChat: true
781
928
  };
782
- this._shareAsChat(oShareData);
929
+ this._shareAsChat(oShareDataLink);
783
930
  } else {
784
- var oShareData = {
931
+ var oShareDataSummary = {
785
932
  appTitle: oData.title ? oData.title : "",
786
933
  message: oData.data,
787
934
  showPreview: typeof oData.showPreview !== "undefined" ? oData.showPreview : true
788
935
  };
789
- this._shareSummary(oShareData);
936
+ this._shareSummary(oShareDataSummary);
790
937
  }
791
938
  } else if (oOption.key === "COLLABORATION_POPOVER_MAIL") {
792
- sap.m.URLHelper.triggerEmail(null, oData.title && oData.title.trim() !== "" ? oData.title: null, oData.data);
939
+ sap.m.URLHelper.triggerEmail(null, oData.title && oData.title.trim() !== "" ? oData.title : null, oData.data);
793
940
  } else if (oOption.key === "COLLABORATION_POPOVER_CM") {
794
941
  this.oCollaborationManager.triggerH2HChat(oData.title, oData.data);
795
942
  }