@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.
- package/package.json +2 -2
- package/src/main/js/sap/ushell_abap/.library +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/AdapterContainer.js +19 -13
- package/src/main/js/sap/ushell_abap/adapters/abap/AppStateAdapter.js +11 -11
- package/src/main/js/sap/ushell_abap/adapters/abap/ClientSideTargetResolutionAdapter.js +81 -81
- package/src/main/js/sap/ushell_abap/adapters/abap/CommonDataModelAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/ConfigurationDefaultsAdapter.js +1 -2
- package/src/main/js/sap/ushell_abap/adapters/abap/ContainerAdapter.js +15 -17
- package/src/main/js/sap/ushell_abap/adapters/abap/FlpLaunchPageAdapter.js +230 -167
- package/src/main/js/sap/ushell_abap/adapters/abap/LaunchPageAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/MenuAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/NavTargetResolutionInternalAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/PageBuildingAdapter.js +10 -12
- package/src/main/js/sap/ushell_abap/adapters/abap/PagePersistenceAdapter.js +20 -17
- package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationAdapter.js +5 -5
- package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationV2Adapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/SearchAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/SupportTicketAdapter.js +2 -2
- package/src/main/js/sap/ushell_abap/adapters/abap/Ui5ComponentLoaderAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/UserInfoAdapter.js +34 -28
- package/src/main/js/sap/ushell_abap/adapters/hana/ContainerAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/bootstrap/evo/SAPCompanionConditionSetter.js +5 -5
- package/src/main/js/sap/ushell_abap/bootstrap/evo/XhrLogonEventHandler.js +5 -2
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.bootstrap.utils.js +2 -2
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.ushell.js +1 -1
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.pageset.js +54 -31
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.startup.js +17 -13
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.theme.handler.js +2 -1
- package/src/main/js/sap/ushell_abap/bootstrap/evo/boottask.js +85 -74
- package/src/main/js/sap/ushell_abap/components/TCodeNavigation/MessageCode.js +47 -0
- package/src/main/js/sap/ushell_abap/components/TCodeNavigation/TCodeNavigationError.js +59 -0
- package/src/main/js/sap/ushell_abap/components/TCodeNavigation.js +163 -0
- package/src/main/js/sap/ushell_abap/integration/fileshares/AppRuntimeFileShareSupport.js +4 -4
- package/src/main/js/sap/ushell_abap/library.js +8 -1
- package/src/main/js/sap/ushell_abap/pbServices/ui2/AllCatalogs.js +2 -2
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Bag.js +15 -19
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Catalog.js +19 -17
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Chip.js +14 -23
- package/src/main/js/sap/ushell_abap/pbServices/ui2/ChipDefinition.js +4 -5
- package/src/main/js/sap/ushell_abap/pbServices/ui2/ChipInstance.js +8 -13
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Error.js +2 -2
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Factory.js +12 -20
- package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataService.js +9 -12
- package/src/main/js/sap/ushell_abap/pbServices/ui2/ODataWrapper.js +45 -33
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Page.js +3 -5
- package/src/main/js/sap/ushell_abap/pbServices/ui2/PageBuildingService.js +19 -22
- package/src/main/js/sap/ushell_abap/pbServices/ui2/PageSet.js +9 -10
- package/src/main/js/sap/ushell_abap/pbServices/ui2/RemoteCatalogService.js +2 -2
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Utils.js +19 -69
- package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/actions.js +3 -4
- package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/configuration.js +1 -1
- package/src/main/js/sap/ushell_abap/pbServices/ui2/contracts/visible.js +2 -2
- package/src/main/js/sap/ushell_abap/ui5appruntime/AppInfoAdapter.js +2 -2
- 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
|
-
|
|
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)
|
|
104
|
-
|
|
105
|
-
if (oResult
|
|
106
|
-
//
|
|
107
|
-
|
|
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
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
* @
|
|
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}
|
|
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 (
|
|
187
|
+
} catch (oError) {
|
|
185
188
|
Log.error(
|
|
186
189
|
"Could not clone object",
|
|
187
|
-
|
|
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
|
-
* @
|
|
322
|
-
* @
|
|
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
|
-
* @
|
|
341
|
-
* @
|
|
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
|
-
|
|
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
|
|
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((
|
|
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((
|
|
769
|
-
fnReject(
|
|
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((
|
|
782
|
-
fnReject(
|
|
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((
|
|
830
|
-
Log.error(
|
|
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()
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
ObjectPath.
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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) => {
|