@sapui5/sap.ushell_abap 1.145.1 → 1.147.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 +4 -4
- package/src/main/js/sap/ushell_abap/.library +8 -7
- package/src/main/js/sap/ushell_abap/adapters/abap/AdapterContainer.js +4 -5
- package/src/main/js/sap/ushell_abap/adapters/abap/AppStateAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/ClientSideTargetResolutionAdapter.js +143 -69
- package/src/main/js/sap/ushell_abap/adapters/abap/CommonDataModelAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/ConfigurationDefaultsAdapter.js +7 -4
- package/src/main/js/sap/ushell_abap/adapters/abap/ContainerAdapter.js +19 -10
- package/src/main/js/sap/ushell_abap/adapters/abap/FlpLaunchPageAdapter.js +148 -109
- package/src/main/js/sap/ushell_abap/adapters/abap/LaunchPageAdapter.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 +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/PagePersistenceAdapter.js +9 -10
- package/src/main/js/sap/ushell_abap/adapters/abap/PersonalizationAdapter.js +1 -1
- 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 +1 -1
- package/src/main/js/sap/ushell_abap/adapters/abap/Ui5ComponentLoaderAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/adapters/hana/ContainerAdapter.js +1 -1
- package/src/main/js/sap/ushell_abap/bootstrap/BootTask/PrepareDirectAppStart.js +20 -0
- package/src/main/js/sap/ushell_abap/bootstrap/BootTask/RequestGroups.js +51 -0
- package/src/main/js/sap/ushell_abap/bootstrap/BootTask/RequestTargetMappings.js +29 -0
- package/src/main/js/sap/ushell_abap/bootstrap/BootTask.js +47 -0
- package/src/main/js/sap/ushell_abap/bootstrap/ConfigurationProvider.js +87 -0
- package/src/main/js/sap/ushell_abap/bootstrap/DirectAppStart.js +231 -0
- package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/CreateRenderer.js +43 -0
- package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/InitXhrLogon.js +148 -0
- package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad/RequestPages.js +86 -0
- package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpad.js +63 -0
- package/src/main/js/sap/ushell_abap/bootstrap/LoadLaunchpadModule.js +11 -0
- package/src/main/js/sap/ushell_abap/bootstrap/PageSetsRequestHandler.js +247 -0
- package/src/main/js/sap/ushell_abap/bootstrap/PlatformConfig.js +385 -0
- package/src/main/js/sap/ushell_abap/bootstrap/{evo/SAPCompanionConditionSetter.js → SAPCompanionConditionSetter.js} +6 -4
- package/src/main/js/sap/ushell_abap/bootstrap/StartupRequestHandler.js +145 -0
- package/src/main/js/sap/ushell_abap/bootstrap/ThemeHandler.js +276 -0
- package/src/main/js/sap/ushell_abap/bootstrap/XhrFactory.js +69 -0
- package/src/main/js/sap/ushell_abap/bootstrap/{evo/XhrLogonEventHandler.js → XhrLogonEventHandler.js} +13 -7
- package/src/main/js/sap/ushell_abap/bootstrap/XhrLogonLibLoader.js +51 -0
- package/src/main/js/sap/ushell_abap/bootstrap/abap-def-dev.js +20 -0
- package/src/main/js/sap/ushell_abap/bootstrap/{evo/abap-def-loader.js → abap-def-loader.js} +2 -2
- package/src/main/js/sap/ushell_abap/bootstrap/abap-def.js +22 -0
- package/src/main/js/sap/ushell_abap/bootstrap/{evo/abap.constants.js → abapConstants.js} +8 -2
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.js +1 -1
- package/src/main/js/sap/ushell_abap/components/TCodeNavigation/MessageCode.js +18 -1
- package/src/main/js/sap/ushell_abap/components/TCodeNavigation.js +27 -16
- package/src/main/js/sap/ushell_abap/library.js +1 -1
- package/src/main/js/sap/ushell_abap/pbServices/ui2/Contracts.js +33 -0
- package/ui5.yaml +7 -6
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap-def-dev.js +0 -42
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap-def.js +0 -45
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.bootstrap.utils.js +0 -172
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.theme.js +0 -28
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.configure.ushell.js +0 -176
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.load.launchpad.js +0 -72
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.pageset.js +0 -219
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.request.startup.js +0 -154
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.theme.handler.js +0 -75
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhrlogon.LibLoader.js +0 -21
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhrlogon.configure.js +0 -62
- package/src/main/js/sap/ushell_abap/bootstrap/evo/abap.xhrlogon.handler.js +0 -82
- package/src/main/js/sap/ushell_abap/bootstrap/evo/boottask.js +0 -948
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
sap.ui.define([
|
|
3
|
+
"sap/base/util/ObjectPath",
|
|
4
|
+
"sap/ushell_abap/bootstrap/StartupRequestHandler",
|
|
5
|
+
"sap/ushell/bootstrap/Config"
|
|
6
|
+
], (
|
|
7
|
+
ObjectPath,
|
|
8
|
+
StartupRequestHandler,
|
|
9
|
+
BootstrapConfig
|
|
10
|
+
) => {
|
|
11
|
+
"use strict";
|
|
12
|
+
|
|
13
|
+
class RequestTargetMappings {
|
|
14
|
+
async run () {
|
|
15
|
+
const oUshellConfig = BootstrapConfig.get();
|
|
16
|
+
|
|
17
|
+
const pResult = StartupRequestHandler.requestFullTM();
|
|
18
|
+
|
|
19
|
+
ObjectPath.set("services.ClientSideTargetResolution.adapter.config.navTargetDataPromise", pResult, oUshellConfig);
|
|
20
|
+
// Do not issue the separate compact request for the launchpage adapter, as it was done in the earlier FLP versions.
|
|
21
|
+
// Reuse the existing full target mappings request that is sent in any case.
|
|
22
|
+
ObjectPath.set("services.LaunchPage.adapter.config.compactTMPromise", pResult, oUshellConfig);
|
|
23
|
+
ObjectPath.set("services.FlpLaunchPage.adapter.config.compactTMPromise", pResult, oUshellConfig);
|
|
24
|
+
ObjectPath.set("services.VisualizationDataProvider.adapter.config.compactTMPromise", pResult, oUshellConfig);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return new RequestTargetMappings();
|
|
29
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
sap.ui.define([
|
|
3
|
+
"sap/base/Log",
|
|
4
|
+
"sap/ui/performance/trace/initTraces",
|
|
5
|
+
"sap/ushell_abap/bootstrap/BootTask/PrepareDirectAppStart",
|
|
6
|
+
"sap/ushell_abap/bootstrap/BootTask/RequestTargetMappings",
|
|
7
|
+
"sap/ushell_abap/bootstrap/BootTask/RequestGroups"
|
|
8
|
+
], (
|
|
9
|
+
Log,
|
|
10
|
+
initTraces,
|
|
11
|
+
PrepareDirectAppStart,
|
|
12
|
+
RequestTargetMappings,
|
|
13
|
+
RequestGroups
|
|
14
|
+
) => {
|
|
15
|
+
"use strict";
|
|
16
|
+
|
|
17
|
+
class BootTask {
|
|
18
|
+
async run (fnCallback, fnErrorCallback) {
|
|
19
|
+
try {
|
|
20
|
+
performance?.mark("FLP - boottask start");
|
|
21
|
+
|
|
22
|
+
// initialize UI5 performance tracing (FESR) before first request is sent, so that this is also instrumented
|
|
23
|
+
initTraces();
|
|
24
|
+
|
|
25
|
+
PrepareDirectAppStart.run().catch((oError) => {
|
|
26
|
+
Log.error("Error during the preparation of direct app start", oError, "sap.ushell_abap.bootstrap.BootTask");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
RequestGroups.run().catch((oError) => {
|
|
30
|
+
Log.error("Error during request of groups", oError, "sap.ushell_abap.bootstrap.BootTask");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
RequestTargetMappings.run().catch((oError) => {
|
|
34
|
+
Log.error("Error during request of target mappings", oError, "sap.ushell_abap.bootstrap.BootTask");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
performance?.mark("FLP - boottask end");
|
|
38
|
+
|
|
39
|
+
fnCallback();
|
|
40
|
+
} catch (oError) {
|
|
41
|
+
fnErrorCallback(oError);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return new BootTask();
|
|
47
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview ABAP bootstrap configuration provider.
|
|
5
|
+
*
|
|
6
|
+
* Coordinates the initialization of BootstrapConfig, PlatformConfig, and
|
|
7
|
+
* the merged UI5 configuration for the ABAP platform. Returns a singleton.
|
|
8
|
+
*/
|
|
9
|
+
sap.ui.define([
|
|
10
|
+
"sap/base/util/deepExtend",
|
|
11
|
+
"sap/ushell_abap/bootstrap/abapConstants",
|
|
12
|
+
"sap/ushell_abap/bootstrap/PlatformConfig",
|
|
13
|
+
"sap/ushell/bootstrap/Config"
|
|
14
|
+
], (
|
|
15
|
+
deepExtend,
|
|
16
|
+
abapConstants,
|
|
17
|
+
PlatformConfig,
|
|
18
|
+
BootstrapConfig
|
|
19
|
+
) => {
|
|
20
|
+
"use strict";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @alias sap.ushell_abap.bootstrap.ConfigurationProvider
|
|
24
|
+
* @namespace
|
|
25
|
+
* @description Configuration provider for the ABAP bootstrap.
|
|
26
|
+
*
|
|
27
|
+
* Initializes the ushell configuration with ABAP defaults, applies
|
|
28
|
+
* platform-specific settings, and merges the resulting UI5 configuration.
|
|
29
|
+
*
|
|
30
|
+
* @since 1.147.0
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
class ConfigurationProvider {
|
|
34
|
+
/** @type {object} The merged UI5 configuration */
|
|
35
|
+
#oUI5Config;
|
|
36
|
+
|
|
37
|
+
constructor () {
|
|
38
|
+
this.#init();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Runs the initialization sequence: initializes BootstrapConfig with ABAP
|
|
43
|
+
* defaults, configures the ushell via PlatformConfig, merges UI5 configs,
|
|
44
|
+
* and applies module paths.
|
|
45
|
+
*
|
|
46
|
+
* @since 1.147.0
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
#init () {
|
|
50
|
+
BootstrapConfig.initialize(abapConstants.defaultUshellConfig);
|
|
51
|
+
|
|
52
|
+
// Extend the default config with platform specific config inplace
|
|
53
|
+
PlatformConfig.configureUshell();
|
|
54
|
+
|
|
55
|
+
this.#oUI5Config = deepExtend({}, BootstrapConfig.getUI5Config(), PlatformConfig.getUI5Config());
|
|
56
|
+
|
|
57
|
+
BootstrapConfig.applyModulePaths();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns the value of a UI5 configuration property.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} sCamelizedKey The camelCase key of the UI5 configuration property (e.g. "sapUiTheme", "sapUiLanguage")
|
|
64
|
+
* @returns {any} The value of the requested key, or <code>undefined</code>
|
|
65
|
+
*
|
|
66
|
+
* @since 1.147.0
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
get (sCamelizedKey) {
|
|
70
|
+
return this.#oUI5Config[sCamelizedKey];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Only for testing purposes!
|
|
75
|
+
* Resets the configuration and re-runs initialization.
|
|
76
|
+
*
|
|
77
|
+
* @since 1.147.0
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
reset () {
|
|
81
|
+
BootstrapConfig.reset();
|
|
82
|
+
this.#init();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return new ConfigurationProvider();
|
|
87
|
+
});
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
sap.ui.define([
|
|
3
|
+
"sap/base/Log",
|
|
4
|
+
"sap/base/util/ObjectPath",
|
|
5
|
+
"sap/ushell_abap/bootstrap/StartupRequestHandler",
|
|
6
|
+
"sap/ushell/bootstrap/Config",
|
|
7
|
+
"sap/ushell/base/promisify",
|
|
8
|
+
"sap/ushell/base/requireAsync",
|
|
9
|
+
"sap/ushell/base/UrlParsing"
|
|
10
|
+
], (
|
|
11
|
+
Log,
|
|
12
|
+
ObjectPath,
|
|
13
|
+
StartupRequestHandler,
|
|
14
|
+
BootstrapConfig,
|
|
15
|
+
promisify,
|
|
16
|
+
requireAsync,
|
|
17
|
+
UrlParsing
|
|
18
|
+
) => {
|
|
19
|
+
"use strict";
|
|
20
|
+
|
|
21
|
+
class DirectAppStart {
|
|
22
|
+
#aInternTargets = [
|
|
23
|
+
"#Shell-home",
|
|
24
|
+
"#Launchpad-openFLPPage",
|
|
25
|
+
"#Shell-appfinder",
|
|
26
|
+
"#Shell-catalog",
|
|
27
|
+
"#shell-catalog",
|
|
28
|
+
"#Action-search"
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
#isRelevant () {
|
|
32
|
+
const sHash = this.#getFullHash();
|
|
33
|
+
|
|
34
|
+
return sHash !== "#" && !this.#aInternTargets.some((sTarget) => sHash.startsWith(sTarget));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async prepare () {
|
|
38
|
+
const oUshellConfig = BootstrapConfig.get();
|
|
39
|
+
|
|
40
|
+
if (!this.#isRelevant()) {
|
|
41
|
+
ObjectPath.set("services.ClientSideTargetResolution.adapter.config.initialSegmentPromise", Promise.resolve(null), oUshellConfig);
|
|
42
|
+
ObjectPath.set("services.AppState.config.initialAppStatesPromise", Promise.resolve({}), oUshellConfig);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const oParsedHash = UrlParsing.parseShellHash(this.#getFullHash(), true);
|
|
47
|
+
const oInitialKeys = {
|
|
48
|
+
"sap-xapp-state": oParsedHash.params?.["sap-xapp-state"]?.[0],
|
|
49
|
+
"sap-intent-param": oParsedHash.params?.["sap-intent-param"]?.[0],
|
|
50
|
+
"sap-system": oParsedHash.params?.["sap-system"]?.[0],
|
|
51
|
+
"sap-iapp-state": oParsedHash.params?.["sap-iapp-state"]?.[0]
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// consider iapp-state also from appSpecificRoute
|
|
55
|
+
if (!oInitialKeys["sap-iapp-state"] && oParsedHash.appSpecificRoute?.includes("sap-iapp-state")) {
|
|
56
|
+
const rRegex = /(\?|&|[/])(sap-iapp-state=[A-Z0-9]+)/;
|
|
57
|
+
const aMatch = oParsedHash.appSpecificRoute.match(rRegex);
|
|
58
|
+
if (aMatch?.[2]) {
|
|
59
|
+
oInitialKeys["sap-iapp-state"] = aMatch[2].split("=")[1];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// remove all undefined values, as they would cause issues in the query
|
|
64
|
+
Object.keys(oInitialKeys).forEach((sKey) => {
|
|
65
|
+
if (oInitialKeys[sKey] === undefined) {
|
|
66
|
+
delete oInitialKeys[sKey];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const oSegment = {
|
|
71
|
+
semanticObject: oParsedHash.semanticObject,
|
|
72
|
+
action: oParsedHash.action
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const pTargetMappings = StartupRequestHandler.requestDirectStart(oSegment, oInitialKeys);
|
|
76
|
+
|
|
77
|
+
const pInitialSegmentPromise = pTargetMappings.then((oResult) => {
|
|
78
|
+
if (!oResult.targetMappings) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return [
|
|
82
|
+
[oSegment],
|
|
83
|
+
oResult.targetMappings,
|
|
84
|
+
oResult.systemAliases,
|
|
85
|
+
oResult.urlTemplates
|
|
86
|
+
];
|
|
87
|
+
});
|
|
88
|
+
ObjectPath.set("services.ClientSideTargetResolution.adapter.config.initialSegmentPromise", pInitialSegmentPromise, oUshellConfig);
|
|
89
|
+
|
|
90
|
+
const pInitialAppStatesPromise = pTargetMappings.then((oResult) => {
|
|
91
|
+
const oInitialAppStates = [
|
|
92
|
+
{ key: "sap-intent-param", startUpKey: "iparState" },
|
|
93
|
+
{ key: "sap-iapp-state", startUpKey: "iappState" },
|
|
94
|
+
{ key: "sap-xapp-state", startUpKey: "xappState" }
|
|
95
|
+
].reduce((oAppStates, { key, startUpKey }) => {
|
|
96
|
+
const sAppStateKey = oInitialKeys[key];
|
|
97
|
+
|
|
98
|
+
if (sAppStateKey && oResult[startUpKey]) {
|
|
99
|
+
oAppStates[sAppStateKey] = oResult[startUpKey];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return oAppStates;
|
|
103
|
+
}, {});
|
|
104
|
+
|
|
105
|
+
ObjectPath.set("services.AppState.config.initialAppStates", oInitialAppStates, oUshellConfig);
|
|
106
|
+
});
|
|
107
|
+
ObjectPath.set("services.AppState.config.initialAppStatesPromise", pInitialAppStatesPromise, oUshellConfig);
|
|
108
|
+
|
|
109
|
+
return Promise.all([
|
|
110
|
+
pTargetMappings,
|
|
111
|
+
pInitialSegmentPromise,
|
|
112
|
+
pInitialAppStatesPromise
|
|
113
|
+
]);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async startApp () {
|
|
117
|
+
if (!this.#isRelevant()) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
window["sap-ushell-async-libs-promise-directstart"] = this.#startApp();
|
|
122
|
+
|
|
123
|
+
await window["sap-ushell-async-libs-promise-directstart"];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async #startApp () {
|
|
127
|
+
let sHash = this.#getFullHash();
|
|
128
|
+
if (sHash.includes("sap-ssb-eval-id")) {
|
|
129
|
+
sHash = await this.#resolveEvalId(sHash);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const [Container] = await requireAsync(["sap/ushell/Container"]);
|
|
133
|
+
const NavTargetResolutionInternal = await Container.getServiceAsync("NavTargetResolutionInternal");
|
|
134
|
+
const oDeferred = NavTargetResolutionInternal.resolveHashFragment(UrlParsing.ensureLeadingHash(sHash));
|
|
135
|
+
|
|
136
|
+
const oResolvedHashFragment = await promisify(oDeferred);
|
|
137
|
+
|
|
138
|
+
const [AppConfiguration] = await requireAsync(["sap/ushell/services/AppConfiguration"]);
|
|
139
|
+
|
|
140
|
+
AppConfiguration.setCurrentApplication(oResolvedHashFragment);
|
|
141
|
+
|
|
142
|
+
if (oResolvedHashFragment?.ui5ComponentName) {
|
|
143
|
+
// create UI5 component early
|
|
144
|
+
const Ui5ComponentLoader = await Container.getServiceAsync("Ui5ComponentLoader");
|
|
145
|
+
|
|
146
|
+
const oResolvedHashFragmentWithComponentHandle = await Ui5ComponentLoader.createComponent(
|
|
147
|
+
oResolvedHashFragment,
|
|
148
|
+
[this.#createWaitForRendererCreatedPromise(Container)],
|
|
149
|
+
"Application"
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
resolvedHashFragment: oResolvedHashFragmentWithComponentHandle,
|
|
154
|
+
dependenciesLoaded: true
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// non-ui5 app
|
|
159
|
+
return {
|
|
160
|
+
resolvedHashFragment: oResolvedHashFragment,
|
|
161
|
+
dependenciesLoaded: false
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* For a Smart Business direct start the parameter sap-ssb-eval-id has to be
|
|
167
|
+
* resolved by Smart Business early so that the resolved parameters are already
|
|
168
|
+
* passed to the app component during the early component creation.
|
|
169
|
+
* @param {string} sHash the current hash
|
|
170
|
+
*/
|
|
171
|
+
async #resolveEvalId (sHash) {
|
|
172
|
+
const [SmartBusiness] = await requireAsync(["sap/ushell/utils/SmartBusiness"]);
|
|
173
|
+
|
|
174
|
+
// At this early point in time the Smart Business library has not been loaded yet.
|
|
175
|
+
// Load it to avoid single file requests.
|
|
176
|
+
// On ABAP, the path where the library is loaded from differs from the
|
|
177
|
+
// common namespace so it has to be mapped.
|
|
178
|
+
await SmartBusiness.loadSmartBusinessLibrary("/sap/bc/ui5_ui5/sap/ssbtileslibs1");
|
|
179
|
+
|
|
180
|
+
let oParsedShellHash = UrlParsing.parseShellHash(sHash);
|
|
181
|
+
oParsedShellHash = await SmartBusiness.resolveEvaluationId(oParsedShellHash, true);
|
|
182
|
+
return UrlParsing.constructShellHash(oParsedShellHash);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Creates an ECMA6 Promise which resolves after the shell renderer has been created. This
|
|
187
|
+
* is necessary to delay the component creation in direct start case, so that the shell renderer
|
|
188
|
+
* had time to initialize (e.g. init shell navigation service).
|
|
189
|
+
*
|
|
190
|
+
* This method must only be called after the shell bootstrap!
|
|
191
|
+
* @param {sap.ushell.Container} Container The shell container instance
|
|
192
|
+
* @returns {Promise} A promise to chain following steps.
|
|
193
|
+
* @private
|
|
194
|
+
*/
|
|
195
|
+
async #createWaitForRendererCreatedPromise (Container) {
|
|
196
|
+
const [EventHub] = await requireAsync(["sap/ushell/EventHub"]);
|
|
197
|
+
const oDeferred = Promise.withResolvers();
|
|
198
|
+
|
|
199
|
+
function fnOnRendererCreated () {
|
|
200
|
+
Log.info("Direct application start: resolving component waitFor promise after shell renderer created event fired.");
|
|
201
|
+
Container.detachRendererCreatedInternal(fnOnRendererCreated);
|
|
202
|
+
oDeferred.resolve();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
EventHub.once("ShellNavigationInitialized").do(() => {
|
|
206
|
+
if (Container.getRendererInternal()) {
|
|
207
|
+
Log.info("Direct application start: resolving component waitFor promise immediately (shell renderer already created).");
|
|
208
|
+
oDeferred.resolve();
|
|
209
|
+
} else {
|
|
210
|
+
// the renderer should be created when the shell navigation is initialized, just to but be robust
|
|
211
|
+
Container.attachRendererCreatedInternal(fnOnRendererCreated);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
return oDeferred.promise;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#getFullHash () {
|
|
219
|
+
const sHash = this.getLocationHash();
|
|
220
|
+
const sSanitizedHash = sHash.startsWith("#") ? sHash : `#${sHash}`;
|
|
221
|
+
// decode hash: identical behavior to ShellNavigationInternal.hrefForExternal
|
|
222
|
+
return decodeURI(sSanitizedHash);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
getLocationHash () {
|
|
226
|
+
return window.location.hash;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return new DirectAppStart();
|
|
231
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
sap.ui.define([
|
|
3
|
+
"sap/ushell/Container",
|
|
4
|
+
"sap/ushell/state/StateManager",
|
|
5
|
+
"sap/ushell/renderer/ShellLayout",
|
|
6
|
+
"sap/ushell/ui/shell/SysInfoBar"
|
|
7
|
+
], (
|
|
8
|
+
Container,
|
|
9
|
+
StateManager,
|
|
10
|
+
ShellLayout,
|
|
11
|
+
SysInfoBar
|
|
12
|
+
) => {
|
|
13
|
+
"use strict";
|
|
14
|
+
|
|
15
|
+
// shortcut for sap.ushell.state.StateManager.ShellMode
|
|
16
|
+
const ShellMode = StateManager.ShellMode;
|
|
17
|
+
|
|
18
|
+
class CreateRenderer {
|
|
19
|
+
async run () {
|
|
20
|
+
const oRenderer = await Container.createRendererInternal("fiori2");
|
|
21
|
+
oRenderer.placeAt("canvas", "only");
|
|
22
|
+
const oSystem = Container.getLogonSystem();
|
|
23
|
+
const sCurrentShellMode = StateManager.getShellMode();
|
|
24
|
+
|
|
25
|
+
if (!oSystem.getSysInfoBar() || sCurrentShellMode === ShellMode.Headerless) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const sSystemInfoHtml = "<div id='systemInfo-shellArea'></div>";
|
|
30
|
+
const oShellHeaderShellArea = document.getElementById(ShellLayout.ShellArea.ShellHeader);
|
|
31
|
+
oShellHeaderShellArea.insertAdjacentHTML("beforebegin", sSystemInfoHtml);
|
|
32
|
+
|
|
33
|
+
new SysInfoBar({
|
|
34
|
+
icon: oSystem.getSysInfoBarIcon(),
|
|
35
|
+
text: oSystem.getSysInfoBarMainText(),
|
|
36
|
+
subText: oSystem.getSysInfoBarSecondaryText(),
|
|
37
|
+
color: oSystem.getSysInfoBarColor()
|
|
38
|
+
}).placeAt("systemInfo-shellArea");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return new CreateRenderer();
|
|
43
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
sap.ui.define([
|
|
3
|
+
"sap/ushell_abap/bootstrap/XhrLogonLibLoader", // triggers loading of the XHR logon lib, once required
|
|
4
|
+
"sap/ushell_abap/bootstrap/XhrLogonEventHandler",
|
|
5
|
+
"sap/ushell/bootstrap/Config",
|
|
6
|
+
"sap/base/Log",
|
|
7
|
+
"sap/ushell/Container"
|
|
8
|
+
], (
|
|
9
|
+
XhrLogonLibLoader,
|
|
10
|
+
XhrLogonEventHandler,
|
|
11
|
+
BootstrapConfig,
|
|
12
|
+
Log,
|
|
13
|
+
Container
|
|
14
|
+
) => {
|
|
15
|
+
"use strict";
|
|
16
|
+
|
|
17
|
+
class InitXhrLogon {
|
|
18
|
+
async run () {
|
|
19
|
+
await Promise.all([
|
|
20
|
+
this.#initXhrLogon(),
|
|
21
|
+
this.#initFrameLogonManager()
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Determines the XHR logon mode based on the bootstrap configuration
|
|
27
|
+
* and the URL parameters sap-ushell-xhrLogon-mode and saml2.
|
|
28
|
+
* @returns {string} the logon mode
|
|
29
|
+
*/
|
|
30
|
+
#getLogonMode () {
|
|
31
|
+
const oUshellConfig = BootstrapConfig.get();
|
|
32
|
+
const sSearch = this.getWindowLocationSearch();
|
|
33
|
+
const oUrlParameters = new URLSearchParams(sSearch);
|
|
34
|
+
|
|
35
|
+
return oUrlParameters.get("sap-ushell-xhrLogon-mode")
|
|
36
|
+
|| (oUrlParameters.get("saml2")?.toLowerCase() === "disabled" ? "logoffAndRedirect" : undefined)
|
|
37
|
+
|| oUshellConfig?.xhrLogon?.mode
|
|
38
|
+
|| "frame";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initializes and starts XHR logon lib based on a given configuration.
|
|
43
|
+
* <p>
|
|
44
|
+
*
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
async #initXhrLogon () {
|
|
48
|
+
const oXhrLogonLib = await XhrLogonLibLoader.getLib();
|
|
49
|
+
|
|
50
|
+
const sLogonMode = this.#getLogonMode();
|
|
51
|
+
const oXhrLogonEventHandler = this.createXhrLogonEventHandler(window, sLogonMode);
|
|
52
|
+
const oLogonManager = oXhrLogonLib.LogonManager.getInstance();
|
|
53
|
+
const oXHRLogonManager = oXhrLogonLib.XHRLogonManager.getInstance();
|
|
54
|
+
const oXhrLibConfig = {
|
|
55
|
+
explicitMatchOnCORS: true // avoids to send XHRLib HTTP headers to thirdparty services
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
oXhrLogonLib.start(oXhrLibConfig);
|
|
59
|
+
|
|
60
|
+
if (sLogonMode === "reload" || sLogonMode === "logoffAndRedirect") {
|
|
61
|
+
oLogonManager.unregisterAllHandlers();
|
|
62
|
+
oLogonManager.registerAuthHandler("*", (oEvent) => {
|
|
63
|
+
oXhrLogonEventHandler.handleEvent(oEvent);
|
|
64
|
+
});
|
|
65
|
+
} else if (sLogonMode !== "frame") {
|
|
66
|
+
Log.warning(`Unknown setting for xhrLogonMode: '${sLogonMode}'. Using default mode 'frame'.`, null, "sap.ushell_abap.bootstrap.XhrLogon");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
oXhrLogonLib.Log.set(this.#createUi5ConnectedXhrLogger());
|
|
70
|
+
this.#initXhrLogonIgnoreList(oXHRLogonManager);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async #initFrameLogonManager () {
|
|
74
|
+
const oXhrLogonLib = await XhrLogonLibLoader.getLib();
|
|
75
|
+
const oFrameLogonManager = oXhrLogonLib.FrameLogonManager.getInstance();
|
|
76
|
+
Container.oFrameLogonManager = oFrameLogonManager;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Creates a logger for XMLHttpRequest(s) that logs errors, warnings, info
|
|
81
|
+
* and debug messages via Log.
|
|
82
|
+
*
|
|
83
|
+
* @returns {object}
|
|
84
|
+
* A logger that can be assigned to XMLHttpRequest.
|
|
85
|
+
*
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
#createUi5ConnectedXhrLogger () {
|
|
89
|
+
return ["error", "warning", "info", "debug"].reduce((oXhrLogger, sLevel) => {
|
|
90
|
+
oXhrLogger[sLevel] = function (sMsg) {
|
|
91
|
+
return Log[sLevel](sMsg);
|
|
92
|
+
};
|
|
93
|
+
return oXhrLogger;
|
|
94
|
+
}, {});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Initializes the ignore list of the XHR logon manager.
|
|
99
|
+
* <p>
|
|
100
|
+
* If the UI5 resources (including the own bootstrap script) are loaded from an absolute URL
|
|
101
|
+
* (in case CDN is activated),
|
|
102
|
+
* this URL is added to the ignore list to prevent CORS preflight requests due to the X headers.
|
|
103
|
+
* We expect that all resources can be loaded without authentication in this case.
|
|
104
|
+
*
|
|
105
|
+
* @param {object} oXHRLogonManager
|
|
106
|
+
* the logon frame manager instance to use
|
|
107
|
+
*
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
#initXhrLogonIgnoreList (oXHRLogonManager) {
|
|
111
|
+
const sOrigin = this.getLocationOrigin();
|
|
112
|
+
const sUi5ResourceRootUrl = sap.ui.require.toUrl("");
|
|
113
|
+
|
|
114
|
+
// add "/" to origin, as otherwise the following use case will match:
|
|
115
|
+
// sUi5ResourceRootUrl: http://sap.com:123
|
|
116
|
+
// sOrigin: http://sap.com
|
|
117
|
+
if (sUi5ResourceRootUrl && sUi5ResourceRootUrl.indexOf(`${sOrigin}/`) === -1) {
|
|
118
|
+
// In case UI5 is loaded from a different domain (CDN / AKAMAI), that URL
|
|
119
|
+
// needs to be ignored for the XHR logon, as we expect that the resources
|
|
120
|
+
// are not protected.
|
|
121
|
+
oXHRLogonManager.ignore.add(sUi5ResourceRootUrl);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* We expose a factory method for the tests and allow to pass a test double for the window object
|
|
127
|
+
*
|
|
128
|
+
* @param {object} oWindow the window object
|
|
129
|
+
* @param {string} sXhrLogonMode logon mode
|
|
130
|
+
* @returns {XhrLogonEventHandler} a new XhrLogonEventHandler
|
|
131
|
+
*
|
|
132
|
+
* @private
|
|
133
|
+
*/
|
|
134
|
+
createXhrLogonEventHandler (oWindow, sXhrLogonMode) {
|
|
135
|
+
return new XhrLogonEventHandler(oWindow, sXhrLogonMode);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
getWindowLocationSearch () {
|
|
139
|
+
return window.location.search;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getLocationOrigin () {
|
|
143
|
+
return window.location.origin;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return new InitXhrLogon();
|
|
148
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Copyright (c) 2009-2026 SAP SE, All Rights Reserved
|
|
2
|
+
sap.ui.define([
|
|
3
|
+
"sap/base/util/ObjectPath",
|
|
4
|
+
"sap/ushell/bootstrap/Config",
|
|
5
|
+
"sap/ushell/Container",
|
|
6
|
+
"sap/ushell/components/pages/controller/PagesAndSpaceId",
|
|
7
|
+
"sap/ushell/resources"
|
|
8
|
+
], (
|
|
9
|
+
ObjectPath,
|
|
10
|
+
BootstrapConfig,
|
|
11
|
+
Container,
|
|
12
|
+
PagesAndSpaceId,
|
|
13
|
+
ushellResources
|
|
14
|
+
) => {
|
|
15
|
+
"use strict";
|
|
16
|
+
|
|
17
|
+
class RequestPages {
|
|
18
|
+
#aInternTargets = [
|
|
19
|
+
"Shell-home",
|
|
20
|
+
"Launchpad-openFLPPage"
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
#isRelevant () {
|
|
24
|
+
const oUshellConfig = BootstrapConfig.get();
|
|
25
|
+
if (!ObjectPath.get("ushell.spaces.enabled", oUshellConfig)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let sHash = this.getLocationHash();
|
|
30
|
+
sHash = sHash.startsWith("#") ? sHash.slice(1) : sHash;
|
|
31
|
+
|
|
32
|
+
return !sHash || this.#aInternTargets.some((sTarget) => sHash.startsWith(sTarget));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async run () {
|
|
36
|
+
if (!this.#isRelevant()) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await Promise.all([
|
|
41
|
+
this.#requestPagesPersonalization(),
|
|
42
|
+
this.#requestPagesContent()
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async #requestPagesPersonalization () {
|
|
47
|
+
const PersonalizationV2 = await Container.getServiceAsync("PersonalizationV2");
|
|
48
|
+
const oPersId = {
|
|
49
|
+
container: "sap.ushell.cdm3-1.personalization",
|
|
50
|
+
item: "data"
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const oScope = {
|
|
54
|
+
validity: "Infinity",
|
|
55
|
+
keyCategory: PersonalizationV2.KeyCategory.GENERATED_KEY,
|
|
56
|
+
writeFrequency: PersonalizationV2.WriteFrequency.HIGH,
|
|
57
|
+
clientStorageAllowed: false
|
|
58
|
+
};
|
|
59
|
+
const oPersonalizer = await PersonalizationV2.getPersonalizer(oPersId, oScope);
|
|
60
|
+
return oPersonalizer.getPersData();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async #requestPagesContent () {
|
|
64
|
+
await ushellResources.awaitResourceBundle();
|
|
65
|
+
|
|
66
|
+
const pId = PagesAndSpaceId.getPageAndSpaceId(this.getLocationHash());
|
|
67
|
+
const pPagePersistenceService = Container.getServiceAsync("PagePersistence");
|
|
68
|
+
|
|
69
|
+
const [
|
|
70
|
+
oIds,
|
|
71
|
+
PagePersistence
|
|
72
|
+
] = await Promise.all([
|
|
73
|
+
pId,
|
|
74
|
+
pPagePersistenceService
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
await PagePersistence.getPage(oIds.pageId);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getLocationHash () {
|
|
81
|
+
return window.location.hash;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return new RequestPages();
|
|
86
|
+
});
|