@sapui5/sap.ushell_abap 1.139.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 +2 -2
  2. package/src/main/js/sap/ushell_abap/.library +1 -1
  3. package/src/main/js/sap/ushell_abap/adapters/abap/AdapterContainer.js +19 -13
  4. package/src/main/js/sap/ushell_abap/adapters/abap/AppStateAdapter.js +11 -11
  5. package/src/main/js/sap/ushell_abap/adapters/abap/ClientSideTargetResolutionAdapter.js +81 -81
  6. package/src/main/js/sap/ushell_abap/adapters/abap/CommonDataModelAdapter.js +1 -1
  7. package/src/main/js/sap/ushell_abap/adapters/abap/ConfigurationDefaultsAdapter.js +1 -2
  8. package/src/main/js/sap/ushell_abap/adapters/abap/ContainerAdapter.js +15 -17
  9. package/src/main/js/sap/ushell_abap/adapters/abap/FlpLaunchPageAdapter.js +230 -167
  10. package/src/main/js/sap/ushell_abap/adapters/abap/LaunchPageAdapter.js +1 -1
  11. package/src/main/js/sap/ushell_abap/adapters/abap/MenuAdapter.js +1 -1
  12. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionAdapter.js +1 -1
  13. package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionInternalAdapter.js +1 -1
  14. package/src/main/js/sap/ushell_abap/adapters/abap/PageBuildingAdapter.js +10 -12
  15. package/src/main/js/sap/ushell_abap/adapters/abap/PagePersistenceAdapter.js +20 -17
  16. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationAdapter.js +5 -5
  17. package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationV2Adapter.js +1 -1
  18. package/src/main/js/sap/ushell_abap/adapters/abap/SearchAdapter.js +1 -1
  19. package/src/main/js/sap/ushell_abap/adapters/abap/SupportTicketAdapter.js +2 -2
  20. package/src/main/js/sap/ushell_abap/adapters/abap/Ui5ComponentLoaderAdapter.js +1 -1
  21. package/src/main/js/sap/ushell_abap/adapters/abap/UserInfoAdapter.js +34 -28
  22. package/src/main/js/sap/ushell_abap/adapters/hana/ContainerAdapter.js +1 -1
  23. package/src/main/js/sap/ushell_abap/bootstrap/evo/SAPCompanionConditionSetter.js +5 -5
  24. package/src/main/js/sap/ushell_abap/bootstrap/evo/XhrLogonEventHandler.js +5 -2
  25. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.bootstrap.utils.js +2 -2
  26. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.ushell.js +1 -1
  27. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.pageset.js +54 -31
  28. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.startup.js +17 -13
  29. package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.theme.handler.js +2 -1
  30. package/src/main/js/sap/ushell_abap/bootstrap/evo/boottask.js +85 -74
  31. package/src/main/js/sap/ushell_abap/components/TCodeNavigation/MessageCode.js +47 -0
  32. package/src/main/js/sap/ushell_abap/components/TCodeNavigation/TCodeNavigationError.js +59 -0
  33. package/src/main/js/sap/ushell_abap/components/TCodeNavigation.js +163 -0
  34. package/src/main/js/sap/ushell_abap/integration/fileshares/AppRuntimeFileShareSupport.js +4 -4
  35. package/src/main/js/sap/ushell_abap/library.js +8 -1
  36. package/src/main/js/sap/ushell_abap/pbServices/ui2/AllCatalogs.js +2 -2
  37. package/src/main/js/sap/ushell_abap/pbServices/ui2/Bag.js +15 -19
  38. package/src/main/js/sap/ushell_abap/pbServices/ui2/Catalog.js +19 -17
  39. package/src/main/js/sap/ushell_abap/pbServices/ui2/Chip.js +14 -23
  40. package/src/main/js/sap/ushell_abap/pbServices/ui2/ChipDefinition.js +4 -5
  41. package/src/main/js/sap/ushell_abap/pbServices/ui2/ChipInstance.js +8 -13
  42. package/src/main/js/sap/ushell_abap/pbServices/ui2/Error.js +2 -2
  43. package/src/main/js/sap/ushell_abap/pbServices/ui2/Factory.js +12 -20
  44. package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataService.js +9 -12
  45. package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataWrapper.js +45 -33
  46. package/src/main/js/sap/ushell_abap/pbServices/ui2/Page.js +3 -5
  47. package/src/main/js/sap/ushell_abap/pbServices/ui2/PageBuildingService.js +19 -22
  48. package/src/main/js/sap/ushell_abap/pbServices/ui2/PageSet.js +9 -10
  49. package/src/main/js/sap/ushell_abap/pbServices/ui2/RemoteCatalogService.js +2 -2
  50. package/src/main/js/sap/ushell_abap/pbServices/ui2/Utils.js +19 -69
  51. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/actions.js +3 -4
  52. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/configuration.js +1 -1
  53. package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/visible.js +2 -2
  54. package/src/main/js/sap/ushell_abap/ui5appruntime/AppInfoAdapter.js +2 -2
  55. package/ui5.yaml +33 -1
@@ -67,7 +67,9 @@ sap.ui.define([
67
67
  const oStartupResult = JSON.parse(sStartupCallResult);
68
68
  resolve(oStartupResult);
69
69
  },
70
- reject,
70
+ (sErrorMessage) => {
71
+ reject(new Error(sErrorMessage));
72
+ },
71
73
  oXHR
72
74
  );
73
75
  });
@@ -100,19 +102,21 @@ sap.ui.define([
100
102
  * Result of the GET request should be resolved
101
103
  */
102
104
  oStartupHandler.requestFullTM = function (oStartupConfig) {
103
- return requestStartup("so=%2A&action=%2A&systemAliasesFormat=object", ["sap-language", "sap-client", "sap-ui2-cache-disable"], oStartupConfig).then((oResult) => {
104
- if (oResult) {
105
- if (oResult.client) { // double check we get the correct response
106
- // TODO: move this to integration test perhaps
107
- return Promise.reject("A start up response was returned in a target mappings request.");
105
+ return requestStartup("so=%2A&action=%2A&systemAliasesFormat=object", ["sap-language", "sap-client", "sap-ui2-cache-disable"], oStartupConfig)
106
+ .then((oResult) => {
107
+ if (oResult) {
108
+ if (oResult.client) { // double check we get the correct response
109
+ // TODO: move this to integration test perhaps
110
+ throw new Error("A start up response was returned in a target mappings request.");
111
+ }
112
+ return oResult;
108
113
  }
109
- return Promise.resolve(oResult);
110
- }
111
- return Promise.resolve({});
112
- }, (sError) => {
113
- Log.error(`navTargetDataPromise rejected: ${sError}`);
114
- return Promise.reject(sError);
115
- });
114
+ return {};
115
+ })
116
+ .catch((oError) => {
117
+ Log.error("navTargetDataPromise rejected:", oError);
118
+ throw oError;
119
+ });
116
120
  };
117
121
 
118
122
  /**
@@ -16,8 +16,9 @@ sap.ui.define([
16
16
 
17
17
  /**
18
18
  * Checks if ThemeRoot is part of the allowlist
19
+ * @param {string} sOrigin the origin of the theme root to be validated
19
20
  *
20
- * @param {string} sOrigin
21
+ * @returns {boolean} if it is part of the allowlist
21
22
  */
22
23
  function validateThemeOrigin (sOrigin) {
23
24
  const aArrayOfAllowedOrigins = oMetaTagHandler.readMetaTags(
@@ -53,6 +53,10 @@ sap.ui.define([
53
53
  *
54
54
  * The root intent (e.g., #Shell-home) will
55
55
  * not determine a direct start condition.
56
+ *
57
+ * @param {string} sHash the hash
58
+ *
59
+ * @returns {boolean} if it is a direct start
56
60
  * @private
57
61
  */
58
62
  function isDirectStart (sHash) {
@@ -60,9 +64,9 @@ sap.ui.define([
60
64
  * Determine whether sHash is a standalone hash.
61
65
  * In this case, the hash is not set as initial target for the start_up service.
62
66
  *
63
- * @param {string} sName
67
+ * @param {string} sCurrentHash
64
68
  * URL parameter name
65
- * @returns {boolean}
69
+ * @returns {boolean} if it is a standalone hash
66
70
  * @private
67
71
  */
68
72
  function isStandaloneHash (sCurrentHash) {
@@ -109,14 +113,13 @@ sap.ui.define([
109
113
  */
110
114
  // TODO Refactor: Align with URLParsing.getShellHash
111
115
  function getFullShellHash () {
112
- let sHashDecoded;
113
116
  const sHref = oAbapUtils.getLocationHref();
114
117
  const iHashIndex = sHref.indexOf("#");
115
118
  if (iHashIndex < 0) {
116
119
  return "";
117
120
  }
118
121
  // decode hash: identical behavior to ShellNavigationInternal.hrefForExternal
119
- sHashDecoded = decodeURI(sHref.slice(iHashIndex + 1));
122
+ const sHashDecoded = decodeURI(sHref.slice(iHashIndex + 1));
120
123
  return sHashDecoded;
121
124
  }
122
125
 
@@ -181,10 +184,10 @@ sap.ui.define([
181
184
  }
182
185
  try {
183
186
  return JSON.parse(JSON.stringify(oObject));
184
- } catch (e) {
187
+ } catch (oError) {
185
188
  Log.error(
186
189
  "Could not clone object",
187
- null,
190
+ oError,
188
191
  "sap.ushell_abap.bootstrap"
189
192
  );
190
193
  return undefined;
@@ -261,7 +264,7 @@ sap.ui.define([
261
264
 
262
265
  /**
263
266
  * Extracts the theme root from the startup service result or fall back
264
- * @param {object} oStartupServiceResult
267
+ * @param {object} oStartupServiceResult the startup service result
265
268
  * @returns {string} the system theme root
266
269
  *
267
270
  * @private
@@ -288,7 +291,7 @@ sap.ui.define([
288
291
 
289
292
  /**
290
293
  * Extracts the theme from the startup service result
291
- * @param {object} startup service result
294
+ * @param {object} oStartupServiceResult startup service result
292
295
  * @returns {string} the theme or undefined
293
296
  *
294
297
  * @private
@@ -318,8 +321,8 @@ sap.ui.define([
318
321
  * theme root is set to "". The theme is then loaded by the UI5 http handler. This is necessary
319
322
  * as the themeing infrastructure is not mandatory and therefore it cannot be ensured that the
320
323
  * http handler of the theming infrastructure is running.
321
- * @params {string} theme
322
- * @params {string} system theme root
324
+ * @param {string} sTheme theme
325
+ * @param {string} sSystemThemeRoot system theme root
323
326
  * @returns {string} theme root for the given theme
324
327
  *
325
328
  * @private
@@ -337,16 +340,14 @@ sap.ui.define([
337
340
  * Assumption: The theme returned in the startup service does not have a root.
338
341
  * It is only the theme name!
339
342
  * The theme root is amended here in.
340
- * @params {string} startup theme
341
- * @params {string} system theme root
343
+ * @param {string} oStartupServiceResult startup theme
344
+ * @param {string} sSystemThemeRoot system theme root
342
345
  * @returns {object} theme root for the startup theme
343
346
  *
344
347
  * @private
345
348
  */
346
349
  function determineStartupTheme (oStartupServiceResult, sSystemThemeRoot) {
347
- let sTheme;
348
-
349
- sTheme = extractThemeFromStartupServiceResult(oStartupServiceResult);
350
+ const sTheme = extractThemeFromStartupServiceResult(oStartupServiceResult);
350
351
  return {
351
352
  theme: sTheme,
352
353
  root: determineThemeRoot(sTheme, sSystemThemeRoot)
@@ -355,15 +356,18 @@ sap.ui.define([
355
356
 
356
357
  /**
357
358
  * Extracts the theme from the URL and determines the theme root
359
+ *
360
+ * @param {string} sSystemThemeRoot
361
+ * the system theme root, as determined by the startup service
362
+ *
358
363
  * @returns {object} contains the theme and the theme root, undefined if no URL theme supplied
359
364
  *
360
365
  * @private
361
366
  */
362
367
  function determineUrlTheme (sSystemThemeRoot) {
363
- let sThemeUrlParameter;
364
368
  let aThemeParts;
365
369
 
366
- sThemeUrlParameter = oAbapUtils.getUrlParameterValue("sap-theme") || oAbapUtils.getUrlParameterValue("sap-ui-theme");
370
+ const sThemeUrlParameter = oAbapUtils.getUrlParameterValue("sap-theme") || oAbapUtils.getUrlParameterValue("sap-ui-theme");
367
371
  if (sThemeUrlParameter) {
368
372
  if (sThemeUrlParameter.indexOf("@") > 0) {
369
373
  aThemeParts = sThemeUrlParameter.split("@", 2);
@@ -428,6 +432,12 @@ sap.ui.define([
428
432
  /**
429
433
  * Process themes
430
434
  *
435
+ * @param {object} oStartupTheme
436
+ * the theme from the startup service
437
+ * @param {string} sSystemThemeRoot
438
+ * the system theme root, as determined by the startup service
439
+ *
440
+ * @returns {object} oBootTheme
431
441
  * @private
432
442
  */
433
443
  function processTheme (oStartupTheme, sSystemThemeRoot) {
@@ -690,13 +700,12 @@ sap.ui.define([
690
700
  function createWaitForRendererCreatedPromise () {
691
701
  const oPromise = new Promise((resolve, reject) => {
692
702
  let oRenderer;
693
- let fnOnRendererCreated;
694
703
 
695
- fnOnRendererCreated = function () {
704
+ function fnOnRendererCreated () {
696
705
  Log.info("Direct application start: resolving component waitFor promise after shell renderer created event fired.");
697
706
  resolve();
698
707
  getContainer().detachRendererCreatedEvent(fnOnRendererCreated);
699
- };
708
+ }
700
709
 
701
710
  EventHub.once("ShellNavigationInitialized").do(() => {
702
711
  oRenderer = getContainer().getRendererInternal();
@@ -735,7 +744,7 @@ sap.ui.define([
735
744
  fnResolve = resolve;
736
745
  fnReject = reject;
737
746
  });
738
- window["sap-ushell-async-libs-promise-directstart"].catch((sMsg) => { // always provide catch handler
747
+ window["sap-ushell-async-libs-promise-directstart"].catch((oError) => { // always provide catch handler
739
748
  /* silently ignore */
740
749
  });
741
750
  // resolve the shell hash and try to load a UI5 component for it; if successful,
@@ -765,8 +774,8 @@ sap.ui.define([
765
774
  dependenciesLoaded: true
766
775
  });
767
776
  })
768
- .catch((vError) => {
769
- fnReject(vError);
777
+ .catch((oError) => {
778
+ fnReject(oError);
770
779
  });
771
780
  });
772
781
  } else {
@@ -778,8 +787,8 @@ sap.ui.define([
778
787
  }
779
788
  });
780
789
  })
781
- .fail((sMsg) => {
782
- fnReject(sMsg);
790
+ .fail((oError) => {
791
+ fnReject(oError);
783
792
  });
784
793
  });
785
794
  }
@@ -826,8 +835,8 @@ sap.ui.define([
826
835
  const oPagePersistenceService = aResults[1];
827
836
  oPagePersistenceService.getPage(oIds.pageId);
828
837
  })
829
- .catch((sError) => {
830
- Log.error(sError);
838
+ .catch((oError) => {
839
+ Log.error("getPage failed", oError);
831
840
  });
832
841
  });
833
842
  }
@@ -844,53 +853,55 @@ sap.ui.define([
844
853
 
845
854
  // fire start-up request if direct start also indicates suppression of pageset request
846
855
  // must be kept before success handler of requestStartUp
847
- oStartupHandler.requestStartupConfig().then((oStartupResult) => {
848
- const sHash = oBoottask._getShellHash();
849
- (ObjectPath.get("sap-ushell-config.services.Container.adapter") || ObjectPath.create("sap-ushell-config.services.Container.adapter")).config = oStartupResult;
850
- const oLaunchPageAdapterConfig = ObjectPath.get("sap-ushell-config.services.LaunchPage.adapter.config") || ObjectPath.create("sap-ushell-config.services.LaunchPage.adapter.config");
851
- const oClientSideTargetResolutionAdapterConfig = ObjectPath.get("sap-ushell-config.services.ClientSideTargetResolution.adapter.config") ||
852
- ObjectPath.create("sap-ushell-config.services.ClientSideTargetResolution.adapter.config");
853
- if (ObjectPath.get("sap-ushell-config.ushell.spaces.enabled")) {
854
- // VisualizationDataProvider and LaunchPageAdapter should have the same configuration
855
- ObjectPath.set("sap-ushell-config.services.VisualizationDataProvider.adapter.config", oLaunchPageAdapterConfig);
856
- // NavigationDataProvider and ClientSideTargetResolutionAdapter should have the same config
857
- ObjectPath.set("sap-ushell-config.services.NavigationDataProvider.adapter.config", oClientSideTargetResolutionAdapterConfig);
858
- }
859
- processDirectStart(oStartupResult);
860
-
861
- // Startup theme processing: as early as possible for performance reasons
862
- sSystemThemeRoot = extractSystemThemeRoot(oStartupResult);
863
- oStartupTheme = determineStartupTheme(oStartupResult, sSystemThemeRoot);
864
- if (!getSapThemeUrlParameter() && oStartupTheme) {
865
- Log.debug("theme: load theme from startup service via window",
866
- null, "sap.ushell_abap.bootstrap");
867
- }
868
- // Request page set and incomplete target mappings only if the home page is loaded
869
- // (not a direct application start)
870
- if (isHomepageHash(sHash) && !ObjectPath.get("sap-ushell-config.ushell.spaces.enabled")) {
871
- // do not create cache entries for PageSet and compact TMs
872
- // otherwise the FLP will freeze when returning to HOME from the cold started app (???)
873
- oPageSetHandler.requestPageSet(oStartupResult);
874
- }
875
- const oTMPromise = oStartupHandler.requestFullTM(oStartupResult);
876
- oClientSideTargetResolutionAdapterConfig.navTargetDataPromise = oTMPromise;
877
- // Do not issue the separate compact request for the launchpage adapter, as it was done in the earlier FLP versions.
878
- // Reuse the existing full target mappings request that is sent in any case.
879
- oLaunchPageAdapterConfig.compactTMPromise = oTMPromise;
880
- ObjectPath.set("sap-ushell-config.services.FlpLaunchPage.adapter.config.compactTMPromise", oTMPromise);
881
-
882
- // Request the target mappings immediately when startup request is finished; this is always requested,
883
- // because we need it for navigation target resolution
884
- return Promise.resolve(oStartupResult);
885
- }, (sMessage) => {
886
- Log.error(`start_up request failed: ${sMessage}`, null,
887
- "sap.ushell_abap.bootstrap");
888
- return Promise.resolve({});
889
- }).then((oStartupResult) => {
890
- // Note: processStartup creates window["sap-ushell-config"]
891
- processStartup(oStartupResult);
892
- fnCallback();
893
- });
856
+ oStartupHandler.requestStartupConfig()
857
+ .catch((oError) => {
858
+ Log.error("start_up request failed:", oError, "sap.ushell_abap.bootstrap");
859
+ return {};
860
+ })
861
+ .then((oStartupResult) => {
862
+ const sHash = oBoottask._getShellHash();
863
+ (ObjectPath.get("sap-ushell-config.services.Container.adapter") || ObjectPath.create("sap-ushell-config.services.Container.adapter")).config = oStartupResult;
864
+ const oLaunchPageAdapterConfig = ObjectPath.get("sap-ushell-config.services.LaunchPage.adapter.config") || ObjectPath.create("sap-ushell-config.services.LaunchPage.adapter.config");
865
+ const oClientSideTargetResolutionAdapterConfig = ObjectPath.get("sap-ushell-config.services.ClientSideTargetResolution.adapter.config") ||
866
+ ObjectPath.create("sap-ushell-config.services.ClientSideTargetResolution.adapter.config");
867
+ if (ObjectPath.get("sap-ushell-config.ushell.spaces.enabled")) {
868
+ // VisualizationDataProvider and LaunchPageAdapter should have the same configuration
869
+ ObjectPath.set("sap-ushell-config.services.VisualizationDataProvider.adapter.config", oLaunchPageAdapterConfig);
870
+ // NavigationDataProvider and ClientSideTargetResolutionAdapter should have the same config
871
+ ObjectPath.set("sap-ushell-config.services.NavigationDataProvider.adapter.config", oClientSideTargetResolutionAdapterConfig);
872
+ }
873
+ processDirectStart(oStartupResult);
874
+
875
+ // Startup theme processing: as early as possible for performance reasons
876
+ sSystemThemeRoot = extractSystemThemeRoot(oStartupResult);
877
+ oStartupTheme = determineStartupTheme(oStartupResult, sSystemThemeRoot);
878
+ if (!getSapThemeUrlParameter() && oStartupTheme) {
879
+ Log.debug("theme: load theme from startup service via window",
880
+ null, "sap.ushell_abap.bootstrap");
881
+ }
882
+ // Request page set and incomplete target mappings only if the home page is loaded
883
+ // (not a direct application start)
884
+ if (isHomepageHash(sHash) && !ObjectPath.get("sap-ushell-config.ushell.spaces.enabled")) {
885
+ // do not create cache entries for PageSet and compact TMs
886
+ // otherwise the FLP will freeze when returning to HOME from the cold started app (???)
887
+ oPageSetHandler.requestPageSet(oStartupResult);
888
+ }
889
+ const oTMPromise = oStartupHandler.requestFullTM(oStartupResult);
890
+ oClientSideTargetResolutionAdapterConfig.navTargetDataPromise = oTMPromise;
891
+ // Do not issue the separate compact request for the launchpage adapter, as it was done in the earlier FLP versions.
892
+ // Reuse the existing full target mappings request that is sent in any case.
893
+ oLaunchPageAdapterConfig.compactTMPromise = oTMPromise;
894
+ ObjectPath.set("sap-ushell-config.services.FlpLaunchPage.adapter.config.compactTMPromise", oTMPromise);
895
+
896
+ // Request the target mappings immediately when startup request is finished; this is always requested,
897
+ // because we need it for navigation target resolution
898
+ return Promise.resolve(oStartupResult);
899
+ })
900
+ .then((oStartupResult) => {
901
+ // Note: processStartup creates window["sap-ushell-config"]
902
+ processStartup(oStartupResult);
903
+ fnCallback();
904
+ });
894
905
  }
895
906
 
896
907
  oBoottask.start = start;
@@ -0,0 +1,47 @@
1
+ // Copyright (c) 2009-2025 SAP SE, All Rights Reserved
2
+
3
+ sap.ui.define([
4
+ ], (
5
+ ) => {
6
+ "use strict";
7
+
8
+ /**
9
+ * Message codes for navigation results.
10
+ * @alias sap.ushell_abap.components.TCodeNavigation.MessageCode
11
+ * @enum {string}
12
+ *
13
+ * @since 1.140.0
14
+ * @private
15
+ * @ui5-restricted sap.esh.search.ui
16
+ */
17
+ const MessageCode = {
18
+ /**
19
+ * Navigation was successful.
20
+ *
21
+ * @since 1.140.0
22
+ * @private
23
+ * @ui5-restricted sap.esh.search.ui
24
+ */
25
+ NAV_SUCCESS: "NAV_SUCCESS",
26
+
27
+ /**
28
+ * No matching inbound was found for the transaction code or a mandatory parameter is missing.
29
+ *
30
+ * @since 1.140.0
31
+ * @private
32
+ * @ui5-restricted sap.esh.search.ui
33
+ */
34
+ NO_INBOUND_FOUND: "NO_INBOUND_FOUND",
35
+
36
+ /**
37
+ * An unknown error occurred during navigation.
38
+ *
39
+ * @since 1.140.0
40
+ * @private
41
+ * @ui5-restricted sap.esh.search.ui
42
+ */
43
+ UNKNOWN_ERROR: "UNKNOWN_ERROR"
44
+ };
45
+
46
+ return MessageCode;
47
+ });
@@ -0,0 +1,59 @@
1
+ // Copyright (c) 2009-2025 SAP SE, All Rights Reserved
2
+
3
+ /**
4
+ * @fileOverview Custom Error class to transport more details
5
+ */
6
+ sap.ui.define([
7
+ "sap/ushell_abap/components/TCodeNavigation/MessageCode"
8
+ ], (
9
+ MessageCode
10
+ ) => {
11
+ "use strict";
12
+
13
+ /**
14
+ * @alias sap.ushell_abap.components.TCodeNavigation.TCodeNavigationError
15
+ * @class
16
+ * @augments Error
17
+ * @classdesc Custom error class for TCode navigation errors.
18
+ *
19
+ * @since 1.140.0
20
+ * @private
21
+ * @ui5-restricted sap.esh.search.ui
22
+ */
23
+ class TCodeNavigationError extends Error {
24
+ constructor (message, options = {}) {
25
+ super(message);
26
+
27
+ /**
28
+ * Error code representing the specific error type.
29
+ * @type {sap.ushell_abap.components.TCodeNavigation.MessageCode}
30
+ *
31
+ * @since 1.140.0
32
+ * @private
33
+ */
34
+ this.code = options.code || MessageCode.UNKNOWN_ERROR;
35
+
36
+ /**
37
+ * Error code representing the specific error type.
38
+ * @type {sap.ushell_abap.components.TCodeNavigation.MessageCode}
39
+ *
40
+ * @since 1.140.0
41
+ * @private
42
+ * @ui5-restricted sap.esh.search.ui
43
+ */
44
+ this.messagecode = this.code;
45
+
46
+ /**
47
+ * Indicates whether the navigation was successful.
48
+ * @type {boolean}
49
+ *
50
+ * @since 1.140.0
51
+ * @private
52
+ * @ui5-restricted sap.esh.search.ui
53
+ */
54
+ this.successful = options.successful ?? false;
55
+ }
56
+ }
57
+
58
+ return TCodeNavigationError;
59
+ });
@@ -0,0 +1,163 @@
1
+ // Copyright (c) 2009-2025 SAP SE, All Rights Reserved
2
+
3
+ sap.ui.define([
4
+ "sap/ushell/Container",
5
+ "sap/base/Log",
6
+ "sap/ushell/api/performance/Extension",
7
+ "sap/ushell/api/performance/NavigationSource",
8
+ "sap/ushell_abap/components/TCodeNavigation/TCodeNavigationError",
9
+ "sap/ushell_abap/components/TCodeNavigation/MessageCode"
10
+ ], (
11
+ Container,
12
+ Log,
13
+ Extension,
14
+ NavigationSource,
15
+ TCodeNavigationError,
16
+ MessageCode
17
+ ) => {
18
+ "use strict";
19
+
20
+ /**
21
+ * @alias sap.ushell_abap.components.TCodeNavigation.NavigationResult
22
+ * @typedef {object}
23
+ * @property {boolean} successful Indicates whether the navigation was successful. //TODO Remove as not needed due to resolved or rejected promise
24
+ * @property {string} messagecode The message code associated with the navigation result.
25
+ *
26
+ * @since 1.140.0
27
+ * @private
28
+ * @ui5-restricted sap.esh.search.ui
29
+ */
30
+
31
+ /**
32
+ * TCodeNavigation module for navigating by Transaction (TA) Code.
33
+ * @alias sap.ushell_abap.components.TCodeNavigation
34
+ * @namespace
35
+ * @description This module provides functionality to navigate to an application intent based on a transaction code.
36
+ * It checks if the provided transaction code matches any inbound's appInfo parameter `abap.transaction`.
37
+ * If a match is found, it extracts the semantic object, action, and parameters from the inbound
38
+ * and uses the Navigation service to perform the navigation.
39
+ *
40
+ * @hideconstructor
41
+ *
42
+ * @since 1.140.0
43
+ * @private
44
+ * @ui5-restricted sap.esh.search.ui
45
+ */ // TODO add technical name of esearch component / team name
46
+ class TCodeNavigation {
47
+ // Performance extension for tracking navigation sources
48
+ static #oExtension = new Extension("TCodeNavigation");
49
+
50
+ // Expose MessageCode enum
51
+ static MessageCode = MessageCode;
52
+
53
+ /**
54
+ * Navigates to an app intent if the given sTCode matches an inbound's appInfo parameter abap.transaction.
55
+ * If a matching inbound is found, it extracts the semantic object, action, and parameters
56
+ * and uses the Navigation service to perform the navigation.
57
+ * @param {string} sTCode The transaction code to search for, can also be an App ID.
58
+ * @param {boolean} bExplace Indicates whether to open the navigation in a new tab.
59
+ * @returns {Promise<sap.ushell_abap.components.TCodeNavigation.NavigationResult>}
60
+ * Resolves with a NavigationResult object containing a successful flag and a message code. Otherwise, it rejects with an error.
61
+ * @throws {sap.ushell_abap.components.TCodeNavigation.TCodeNavigationError} E.g., if no matching inbound is found or if a mandatory parameter is missing.
62
+ *
63
+ * @since 1.140.0
64
+ * @private
65
+ * @ui5-restricted sap.esh.search.ui
66
+ */
67
+ static async navigateByTCode (sTCode, bExplace) {
68
+ try {
69
+ const NavDataProvider = await Container.getServiceAsync("NavigationDataProvider");
70
+ const oNavigationData = await NavDataProvider.getNavigationData();
71
+
72
+ const oValidInbound = this.#getValidInbound(oNavigationData, sTCode);
73
+
74
+ if (oValidInbound) {
75
+ // Extract semantic object, action, and parameters from the matched inbound for navigation
76
+ const { semanticObject: sSemanticObject, action: sAction } = oValidInbound;
77
+ const oParams = {};
78
+ if (bExplace) {
79
+ oParams["sap-ushell-navmode"] = "explace";
80
+ }
81
+
82
+ // Log the navigation source for performance tracking
83
+ this.#oExtension.addNavigationSource(NavigationSource.SearchDirectLaunch);
84
+
85
+ const oNavService = await Container.getServiceAsync("Navigation");
86
+ await oNavService.navigate({
87
+ target: {
88
+ semanticObject: sSemanticObject,
89
+ action: sAction
90
+ },
91
+ params: oParams
92
+ });
93
+
94
+ return {
95
+ successful: true,
96
+ messagecode: MessageCode.NAV_SUCCESS
97
+ };
98
+ }
99
+ throw new TCodeNavigationError(
100
+ `No matching inbound found for transaction code: ${sTCode}`,
101
+ { code: MessageCode.NO_INBOUND_FOUND }
102
+ );
103
+ } catch (oError) {
104
+ Log.error("Error during TCode navigation", oError);
105
+ const oErrorResult = new TCodeNavigationError(
106
+ "Error during TCode navigation.",
107
+ {
108
+ successful: false,
109
+ code: oError.code
110
+ }
111
+ );
112
+ throw oErrorResult;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Finds the first inbound that matches the given transaction code and doesn't have mandatory parameters.
118
+ * @param {object} oNavigationData The navigation data containing inbounds.
119
+ * @param {string} sTCode The transaction code to match.
120
+ * @returns {object|null} The matched inbound or null if no match is found.
121
+ *
122
+ * @since 1.140.0
123
+ * @private
124
+ */
125
+ static #getValidInbound (oNavigationData, sTCode) {
126
+ if (!oNavigationData?.inbounds) {
127
+ Log.error("No navigation data found");
128
+ return null;
129
+ }
130
+
131
+ // Find all inbounds with matching transaction code
132
+ const aMatchedInbounds = oNavigationData.inbounds.filter((oInbound) =>
133
+ oInbound.resolutionResult?.appInfo?.["abap.transaction"] === sTCode
134
+ );
135
+ if (aMatchedInbounds.length === 0) {
136
+ return null;
137
+ }
138
+
139
+ // Return the first matched inbound where all mandatory parameters have default values
140
+ const oValidInbound = aMatchedInbounds.find((oInbound) => {
141
+ const oParams = oInbound.signature?.parameters;
142
+ if (!oParams) {
143
+ return true; // No parameters, consider valid
144
+ }
145
+ // All required parameters must have a default value
146
+ return Object.values(oParams).every((oValue) =>
147
+ !oValue.required || (oValue.defaultValue && oValue.defaultValue.value)
148
+ );
149
+ });
150
+
151
+ if (!oValidInbound) {
152
+ throw new TCodeNavigationError(
153
+ `Mandatory parameter is missing for transaction ${sTCode}`,
154
+ { code: MessageCode.NO_INBOUND_FOUND }
155
+ );
156
+ }
157
+
158
+ return oValidInbound;
159
+ }
160
+ }
161
+
162
+ return TCodeNavigation;
163
+ });
@@ -37,14 +37,14 @@ sap.ui.define([
37
37
  const ACTION = "manage";
38
38
  const URL = `/sap/bc/ui2/start_up?so=${SEMANTIC_OBJECT}&action=${ACTION}&systemAliasesFormat=object&formFactor=desktop&shellType=FLP&depth=0`;
39
39
 
40
- AppRuntimeFileShareSupport.getDataSource = function () {
40
+ AppRuntimeFileShareSupport.getDataSource = async function () {
41
41
  const sSapClient = AppRuntimeFileShareSupport._getClient();
42
42
  const sUrl = `${URL}&sap-client=${sSapClient}`;
43
43
 
44
44
  // reject if sap-client not found to avoid 401 responses
45
45
  if (!sSapClient) {
46
46
  Log.error("Could not determine sap-client parameter.", null, MODULE_NAME);
47
- return Promise.reject(new Error("Could not determine sap-client parameter."));
47
+ throw new Error("Could not determine sap-client parameter.");
48
48
  }
49
49
 
50
50
  if (!AppRuntimeFileShareSupport._getDataSourcePromise) {
@@ -62,7 +62,7 @@ sap.ui.define([
62
62
  if (oResponse.ok === false) {
63
63
  Log.error("Could not fetch data, request failed",
64
64
  `error: ${oResponse.status}, ${oResponse.statusText},\nurl: ${sUrl}`, MODULE_NAME);
65
- return Promise.reject(oResponse.statusText);
65
+ throw new Error(oResponse.statusText);
66
66
  }
67
67
  return oResponse.json();
68
68
  }).then((oData) => {
@@ -87,7 +87,7 @@ sap.ui.define([
87
87
  }
88
88
  }
89
89
 
90
- const sErrorMessage = ["No manifest URL defined:", JSON.stringify(oData)].join(" ");
90
+ const sErrorMessage = `No manifest URL defined: ${JSON.stringify(oData)}`;
91
91
  Log.error(sErrorMessage, null, MODULE_NAME);
92
92
  throw new Error(sErrorMessage);
93
93
  }).then((oManifest) => {