@openmfp/portal-ui-lib 0.0.0 → 0.182.2
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/LICENSE +201 -0
- package/README.md +712 -0
- package/assets/249.js +1 -0
- package/assets/560.js +1 -0
- package/assets/955.js +1 -0
- package/assets/images/favicon.ico +0 -0
- package/assets/images/logo.png +0 -0
- package/assets/moments/sapIllus-Dialog-BeforeSearch-Alt.svg +22 -0
- package/assets/moments/sapIllus-Dialog-BeforeSearch.svg +13 -0
- package/assets/moments/sapIllus-Dialog-NoActivities.svg +18 -0
- package/assets/moments/sapIllus-Dialog-NoData.svg +10 -0
- package/assets/moments/sapIllus-Dialog-NoEntries.svg +16 -0
- package/assets/moments/sapIllus-Dialog-NoMail.svg +11 -0
- package/assets/moments/sapIllus-Dialog-NoNotifications.svg +12 -0
- package/assets/moments/sapIllus-Dialog-NoSavedItems.svg +13 -0
- package/assets/moments/sapIllus-Dialog-NoSearchResults-Alt.svg +14 -0
- package/assets/moments/sapIllus-Dialog-NoSearchResults.svg +15 -0
- package/assets/moments/sapIllus-Dialog-NoTasks.svg +18 -0
- package/assets/moments/sapIllus-Dialog-SuccessBalloon.svg +16 -0
- package/assets/moments/sapIllus-Dialog-SuccessCheckMark-Alt.svg +14 -0
- package/assets/moments/sapIllus-Dialog-SuccessCheckMark.svg +7 -0
- package/assets/moments/sapIllus-Dialog-SuccessHighFive.svg +31 -0
- package/assets/moments/sapIllus-Dialog-UnableToLoad-Alt.svg +12 -0
- package/assets/moments/sapIllus-Dialog-UnableToLoad-Alt2.svg +10 -0
- package/assets/moments/sapIllus-Dialog-UnableToLoad.svg +11 -0
- package/assets/moments/sapIllus-Dialog-UnableToUpload.svg +13 -0
- package/assets/moments/sapIllus-Scene-BeforeSearch.svg +31 -0
- package/assets/moments/sapIllus-Scene-NoActivities-Alt.svg +24 -0
- package/assets/moments/sapIllus-Scene-NoActivities.svg +28 -0
- package/assets/moments/sapIllus-Scene-NoData.svg +21 -0
- package/assets/moments/sapIllus-Scene-NoEntries.svg +30 -0
- package/assets/moments/sapIllus-Scene-NoMail.svg +23 -0
- package/assets/moments/sapIllus-Scene-NoNotifications.svg +36 -0
- package/assets/moments/sapIllus-Scene-NoSavedItems.svg +36 -0
- package/assets/moments/sapIllus-Scene-NoSearchResults-Alt.svg +44 -0
- package/assets/moments/sapIllus-Scene-NoSearchResults.svg +15 -0
- package/assets/moments/sapIllus-Scene-NoTasks.svg +22 -0
- package/assets/moments/sapIllus-Scene-SuccessBalloon.svg +33 -0
- package/assets/moments/sapIllus-Scene-SuccessCheckMark.svg +43 -0
- package/assets/moments/sapIllus-Scene-UnableToLoad.svg +23 -0
- package/assets/moments/sapIllus-Scene-UnableToUpload.svg +13 -0
- package/assets/moments/sapIllus-Spot-BeforeSearch-Alt.svg +10 -0
- package/assets/moments/sapIllus-Spot-BeforeSearch.svg +10 -0
- package/assets/moments/sapIllus-Spot-NoActivities.svg +23 -0
- package/assets/moments/sapIllus-Spot-NoData.svg +9 -0
- package/assets/moments/sapIllus-Spot-NoEntries.svg +12 -0
- package/assets/moments/sapIllus-Spot-NoMail.svg +10 -0
- package/assets/moments/sapIllus-Spot-NoNotifications.svg +10 -0
- package/assets/moments/sapIllus-Spot-NoSavedItems.svg +9 -0
- package/assets/moments/sapIllus-Spot-NoSearchResults-Alt.svg +14 -0
- package/assets/moments/sapIllus-Spot-NoSearchResults.svg +13 -0
- package/assets/moments/sapIllus-Spot-NoTasks.svg +20 -0
- package/assets/moments/sapIllus-Spot-SuccessBalloon.svg +19 -0
- package/assets/moments/sapIllus-Spot-SuccessCheckMark-Alt.svg +13 -0
- package/assets/moments/sapIllus-Spot-SuccessCheckMark.svg +7 -0
- package/assets/moments/sapIllus-Spot-UnableToLoad-Alt.svg +13 -0
- package/assets/moments/sapIllus-Spot-UnableToLoad-Alt2.svg +13 -0
- package/assets/moments/sapIllus-Spot-UnableToLoad.svg +10 -0
- package/assets/moments/sapIllus-Spot-UnableToUpload.svg +10 -0
- package/assets/moments/tnt-Dialog-Components.svg +9 -0
- package/assets/moments/tnt-Dialog-ExternalLink.svg +11 -0
- package/assets/moments/tnt-Dialog-UnsuccessfulAuth.svg +11 -0
- package/assets/moments/tnt-Scene-Components.svg +16 -0
- package/assets/moments/tnt-Scene-ExternalLink.svg +14 -0
- package/assets/moments/tnt-Scene-UnsuccessfulAuth.svg +22 -0
- package/assets/moments/tnt-Spot-UnsuccessfulAuth.svg +10 -0
- package/assets/openmfp-portal-ui-wc.js +179 -0
- package/assets/translation-files/de.json +1 -0
- package/assets/translation-files/en.json +1 -0
- package/fesm2022/openmfp-portal-ui-lib.mjs +2716 -0
- package/fesm2022/openmfp-portal-ui-lib.mjs.map +1 -0
- package/index.d.ts +1071 -0
- package/package.json +50 -2
|
@@ -0,0 +1,2716 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, inject, Optional, Inject, provideAppInitializer, signal, ChangeDetectionStrategy, Component, ViewEncapsulation, provideZoneChangeDetection, makeEnvironmentProviders } from '@angular/core';
|
|
3
|
+
import * as i1$1 from '@angular/common/http';
|
|
4
|
+
import { HttpHeaders, HttpErrorResponse, HttpClient, provideHttpClient } from '@angular/common/http';
|
|
5
|
+
import { firstValueFrom, Subject, lastValueFrom, tap, filter } from 'rxjs';
|
|
6
|
+
import * as i1 from '@angular/router';
|
|
7
|
+
import { NavigationEnd, NavigationStart, RouterOutlet, provideRouter, RouteReuseStrategy } from '@angular/router';
|
|
8
|
+
import { jwtDecode } from 'jwt-decode';
|
|
9
|
+
import { isEqual, isMatch } from 'lodash';
|
|
10
|
+
import oAuth2 from '@luigi-project/plugin-auth-oauth2';
|
|
11
|
+
import { filter as filter$1 } from 'rxjs/operators';
|
|
12
|
+
import { search } from 'jmespath';
|
|
13
|
+
import { $localize } from '@angular/localize/init';
|
|
14
|
+
|
|
15
|
+
const luigi = globalThis.Luigi;
|
|
16
|
+
class LuigiCoreService {
|
|
17
|
+
setConfig(config) {
|
|
18
|
+
return luigi.setConfig(config);
|
|
19
|
+
}
|
|
20
|
+
get config() {
|
|
21
|
+
return luigi.getConfig();
|
|
22
|
+
}
|
|
23
|
+
getConfigValue(key) {
|
|
24
|
+
return luigi.getConfigValue(key);
|
|
25
|
+
}
|
|
26
|
+
unloadConfig() {
|
|
27
|
+
return luigi.unload();
|
|
28
|
+
}
|
|
29
|
+
sendCustomMessage(customMessage) {
|
|
30
|
+
return luigi.sendCustomMessage(customMessage);
|
|
31
|
+
}
|
|
32
|
+
configChanged(scope) {
|
|
33
|
+
luigi.configChanged(scope);
|
|
34
|
+
}
|
|
35
|
+
customMessages() {
|
|
36
|
+
return luigi.customMessages();
|
|
37
|
+
}
|
|
38
|
+
navigation() {
|
|
39
|
+
return luigi.navigation();
|
|
40
|
+
}
|
|
41
|
+
resetLuigi() {
|
|
42
|
+
luigi.reset();
|
|
43
|
+
}
|
|
44
|
+
clearNavigationCache() {
|
|
45
|
+
if (luigi.clearNavigationCache) {
|
|
46
|
+
luigi.clearNavigationCache();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
showAlert(alert) {
|
|
50
|
+
return luigi.showAlert(alert);
|
|
51
|
+
}
|
|
52
|
+
ux() {
|
|
53
|
+
return luigi.ux();
|
|
54
|
+
}
|
|
55
|
+
theming() {
|
|
56
|
+
return luigi.theming();
|
|
57
|
+
}
|
|
58
|
+
i18n() {
|
|
59
|
+
return luigi.i18n();
|
|
60
|
+
}
|
|
61
|
+
globalSearch() {
|
|
62
|
+
return luigi.globalSearch();
|
|
63
|
+
}
|
|
64
|
+
getGlobalContext() {
|
|
65
|
+
return luigi.getGlobalContext();
|
|
66
|
+
}
|
|
67
|
+
getWcExtendedContext() {
|
|
68
|
+
return document
|
|
69
|
+
.querySelector('.wcContainer')
|
|
70
|
+
?.querySelector('[lui_web_component]')?.extendedContext?.context;
|
|
71
|
+
}
|
|
72
|
+
getWcModalExtendedContext() {
|
|
73
|
+
return document
|
|
74
|
+
.querySelector('.iframeModalCtn')
|
|
75
|
+
?.querySelector('[lui_web_component]')?.extendedContext?.context;
|
|
76
|
+
}
|
|
77
|
+
setGlobalContext(globalContext, preventUpdate = false) {
|
|
78
|
+
luigi.setGlobalContext(globalContext, preventUpdate);
|
|
79
|
+
}
|
|
80
|
+
setInGlobalContext(context, preventUpdate = false) {
|
|
81
|
+
luigi.setGlobalContext({ ...this.getGlobalContext(), ...context }, preventUpdate);
|
|
82
|
+
}
|
|
83
|
+
routing() {
|
|
84
|
+
return luigi.routing();
|
|
85
|
+
}
|
|
86
|
+
setFeatureToggle(featureToggleName) {
|
|
87
|
+
luigi.featureToggles().setFeatureToggle(featureToggleName);
|
|
88
|
+
}
|
|
89
|
+
unsetFeatureToggle(featureToggleName) {
|
|
90
|
+
luigi.featureToggles().unsetFeatureToggle(featureToggleName);
|
|
91
|
+
}
|
|
92
|
+
unsetAllFeatureToggles() {
|
|
93
|
+
luigi
|
|
94
|
+
.featureToggles()
|
|
95
|
+
.getActiveFeatureToggleList()
|
|
96
|
+
.forEach((ft) => {
|
|
97
|
+
this.unsetFeatureToggle(ft);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
setFeatureToggles(featureToggles) {
|
|
101
|
+
if (!featureToggles) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
for (const featureToggleName of Object.keys(featureToggles)) {
|
|
105
|
+
if (featureToggles[featureToggleName]) {
|
|
106
|
+
this.setFeatureToggle(featureToggleName);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
isFeatureToggleActive(ft) {
|
|
111
|
+
return luigi.featureToggles().getActiveFeatureToggleList().includes(ft);
|
|
112
|
+
}
|
|
113
|
+
getActiveFeatureToggleList() {
|
|
114
|
+
return luigi.featureToggles().getActiveFeatureToggleList();
|
|
115
|
+
}
|
|
116
|
+
setAuthData(authData) {
|
|
117
|
+
luigi.auth().store.setAuthData(authData);
|
|
118
|
+
luigi.auth().store.setNewlyAuthorized();
|
|
119
|
+
}
|
|
120
|
+
removeAuthData() {
|
|
121
|
+
luigi.auth().store.removeAuthData();
|
|
122
|
+
}
|
|
123
|
+
getAuthData() {
|
|
124
|
+
return luigi.auth().store.getAuthData();
|
|
125
|
+
}
|
|
126
|
+
setCurrentLocale(language) {
|
|
127
|
+
luigi.i18n().setCurrentLocale(language);
|
|
128
|
+
}
|
|
129
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiCoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
130
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiCoreService, providedIn: 'root' }); }
|
|
131
|
+
}
|
|
132
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiCoreService, decorators: [{
|
|
133
|
+
type: Injectable,
|
|
134
|
+
args: [{
|
|
135
|
+
providedIn: 'root',
|
|
136
|
+
}]
|
|
137
|
+
}] });
|
|
138
|
+
|
|
139
|
+
var AuthEvent;
|
|
140
|
+
(function (AuthEvent) {
|
|
141
|
+
AuthEvent["AUTH_SUCCESSFUL"] = "AuthSuccessful";
|
|
142
|
+
AuthEvent["AUTH_ERROR"] = "AuthError";
|
|
143
|
+
AuthEvent["AUTH_EXPIRED"] = "AuthExpired";
|
|
144
|
+
AuthEvent["AUTH_REFRESHED"] = "AuthRefreshed";
|
|
145
|
+
AuthEvent["AUTH_EXPIRE_SOON"] = "AuthExpireSoon";
|
|
146
|
+
AuthEvent["AUTH_CONFIG_ERROR"] = "AuthConfigError";
|
|
147
|
+
AuthEvent["LOGOUT"] = "Logout";
|
|
148
|
+
})(AuthEvent || (AuthEvent = {}));
|
|
149
|
+
|
|
150
|
+
var EntityType;
|
|
151
|
+
(function (EntityType) {
|
|
152
|
+
EntityType["GLOBAL"] = "global";
|
|
153
|
+
EntityType["GLOBAL_TOPNAV"] = "global.topnav";
|
|
154
|
+
EntityType["ENTITY_ERROR"] = "entity.error";
|
|
155
|
+
})(EntityType || (EntityType = {}));
|
|
156
|
+
|
|
157
|
+
var NetworkVisibility;
|
|
158
|
+
(function (NetworkVisibility) {
|
|
159
|
+
NetworkVisibility["INTERNAL"] = "internal";
|
|
160
|
+
NetworkVisibility["INTERNET"] = "internet";
|
|
161
|
+
})(NetworkVisibility || (NetworkVisibility = {}));
|
|
162
|
+
|
|
163
|
+
class RequestHeadersService {
|
|
164
|
+
constructor(luigiCoreService, route) {
|
|
165
|
+
this.luigiCoreService = luigiCoreService;
|
|
166
|
+
this.route = route;
|
|
167
|
+
}
|
|
168
|
+
createOptionsWithAuthHeader() {
|
|
169
|
+
let language = this.luigiCoreService.i18n().getCurrentLocale();
|
|
170
|
+
const authData = this.luigiCoreService.getAuthData();
|
|
171
|
+
this.route.queryParams.subscribe((params) => {
|
|
172
|
+
if (params['language']) {
|
|
173
|
+
language = params['language'];
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
if (!authData?.idToken) {
|
|
177
|
+
throw new Error('Unable to create authorization header, no id token present.');
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
headers: new HttpHeaders({
|
|
181
|
+
authorization: 'Bearer ' + authData.idToken,
|
|
182
|
+
'Accept-Language': language || '',
|
|
183
|
+
}),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RequestHeadersService, deps: [{ token: LuigiCoreService }, { token: i1.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
187
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RequestHeadersService, providedIn: 'root' }); }
|
|
188
|
+
}
|
|
189
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RequestHeadersService, decorators: [{
|
|
190
|
+
type: Injectable,
|
|
191
|
+
args: [{
|
|
192
|
+
providedIn: 'root',
|
|
193
|
+
}]
|
|
194
|
+
}], ctorParameters: () => [{ type: LuigiCoreService }, { type: i1.ActivatedRoute }] });
|
|
195
|
+
|
|
196
|
+
class ConfigService {
|
|
197
|
+
constructor(http, requestHeadersService) {
|
|
198
|
+
this.http = http;
|
|
199
|
+
this.requestHeadersService = requestHeadersService;
|
|
200
|
+
this.entityConfigCache = {};
|
|
201
|
+
}
|
|
202
|
+
async getPortalConfig() {
|
|
203
|
+
if (this.portalConfigCachePromise) {
|
|
204
|
+
return this.portalConfigCachePromise;
|
|
205
|
+
}
|
|
206
|
+
const options = this.requestHeadersService.createOptionsWithAuthHeader();
|
|
207
|
+
this.portalConfigCachePromise = firstValueFrom(this.http.get('/rest/config', options)).catch((e) => {
|
|
208
|
+
if (e instanceof HttpErrorResponse && e.status === 403) {
|
|
209
|
+
window.location.assign('/logout?error=invalidToken');
|
|
210
|
+
}
|
|
211
|
+
throw e;
|
|
212
|
+
});
|
|
213
|
+
return this.portalConfigCachePromise;
|
|
214
|
+
}
|
|
215
|
+
async reloadConfig(entity, context) {
|
|
216
|
+
if (!entity) {
|
|
217
|
+
this.portalConfigCachePromise = undefined;
|
|
218
|
+
await this.getPortalConfig();
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
const entityCacheKey = JSON.stringify(context);
|
|
222
|
+
delete this.entityConfigCache[entity][entityCacheKey];
|
|
223
|
+
await this.getEntityConfig(entity, context);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async getEntityConfig(entity, context) {
|
|
227
|
+
if (!this.entityConfigCache[entity]) {
|
|
228
|
+
this.entityConfigCache[entity] = {};
|
|
229
|
+
}
|
|
230
|
+
const entityCacheKey = JSON.stringify(context);
|
|
231
|
+
if (this.entityConfigCache[entity][entityCacheKey]) {
|
|
232
|
+
return this.entityConfigCache[entity][entityCacheKey];
|
|
233
|
+
}
|
|
234
|
+
const options = this.requestHeadersService.createOptionsWithAuthHeader();
|
|
235
|
+
const entityConfig = firstValueFrom(this.http.get(`/rest/config/${entity}`, {
|
|
236
|
+
...options,
|
|
237
|
+
...{ params: context },
|
|
238
|
+
}));
|
|
239
|
+
this.entityConfigCache[entity][entityCacheKey] = entityConfig;
|
|
240
|
+
return entityConfig;
|
|
241
|
+
}
|
|
242
|
+
clearEntityConfigCache() {
|
|
243
|
+
this.entityConfigCache = {};
|
|
244
|
+
}
|
|
245
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ConfigService, deps: [{ token: i1$1.HttpClient }, { token: RequestHeadersService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
246
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ConfigService, providedIn: 'root' }); }
|
|
247
|
+
}
|
|
248
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ConfigService, decorators: [{
|
|
249
|
+
type: Injectable,
|
|
250
|
+
args: [{
|
|
251
|
+
providedIn: 'root',
|
|
252
|
+
}]
|
|
253
|
+
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: RequestHeadersService }] });
|
|
254
|
+
|
|
255
|
+
class AuthService {
|
|
256
|
+
constructor(http) {
|
|
257
|
+
this.http = http;
|
|
258
|
+
this.authEventSubject = new Subject();
|
|
259
|
+
this.parseJwt = (token) => {
|
|
260
|
+
try {
|
|
261
|
+
return jwtDecode(token);
|
|
262
|
+
}
|
|
263
|
+
catch (Error) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
this.getToken = () => {
|
|
268
|
+
const auth = this.getAuthData();
|
|
269
|
+
if (auth) {
|
|
270
|
+
return auth.idToken;
|
|
271
|
+
}
|
|
272
|
+
return {};
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
get authEvents() {
|
|
276
|
+
return this.authEventSubject.asObservable();
|
|
277
|
+
}
|
|
278
|
+
authEvent(event) {
|
|
279
|
+
this.authEventSubject.next(event);
|
|
280
|
+
}
|
|
281
|
+
async refresh() {
|
|
282
|
+
const response = await lastValueFrom(this.http.post('/rest/auth/refresh', {}));
|
|
283
|
+
this.setAuthData(response);
|
|
284
|
+
return response;
|
|
285
|
+
}
|
|
286
|
+
setAuthData(authTokenData) {
|
|
287
|
+
if (!authTokenData) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
this.authData = {
|
|
291
|
+
accessTokenExpirationDate: this.processExpDate(authTokenData.expires_in),
|
|
292
|
+
idToken: authTokenData.id_token,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
getAuthData() {
|
|
296
|
+
return this.authData;
|
|
297
|
+
}
|
|
298
|
+
getUser() {
|
|
299
|
+
const auth = this.getAuthData();
|
|
300
|
+
if (auth) {
|
|
301
|
+
return this.parseJwt(auth.idToken);
|
|
302
|
+
}
|
|
303
|
+
return {};
|
|
304
|
+
}
|
|
305
|
+
getUserInfo() {
|
|
306
|
+
const user = this.getUser() || {};
|
|
307
|
+
const firstName = user.first_name || user.given_name || '';
|
|
308
|
+
const lastName = user.last_name || user.family_name || '';
|
|
309
|
+
const initialsFirstName = firstName[0] || '';
|
|
310
|
+
const initialsLastName = lastName[0] || '';
|
|
311
|
+
return {
|
|
312
|
+
name: `${firstName} ${lastName}`,
|
|
313
|
+
email: user.mail || user.email || '',
|
|
314
|
+
description: user.mail || user.email || '',
|
|
315
|
+
picture: '',
|
|
316
|
+
icon: false,
|
|
317
|
+
initials: initialsFirstName + initialsLastName,
|
|
318
|
+
userId: user.sub || '',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
processExpDate(expiresInSeconds) {
|
|
322
|
+
const expiresIn = Number(expiresInSeconds);
|
|
323
|
+
return new Date().getTime() + expiresIn * 1000;
|
|
324
|
+
}
|
|
325
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AuthService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
326
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AuthService, providedIn: 'root' }); }
|
|
327
|
+
}
|
|
328
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AuthService, decorators: [{
|
|
329
|
+
type: Injectable,
|
|
330
|
+
args: [{
|
|
331
|
+
providedIn: 'root',
|
|
332
|
+
}]
|
|
333
|
+
}], ctorParameters: () => [{ type: i1$1.HttpClient }] });
|
|
334
|
+
|
|
335
|
+
class EnvConfigService {
|
|
336
|
+
constructor() {
|
|
337
|
+
this.http = inject(HttpClient);
|
|
338
|
+
}
|
|
339
|
+
async getEnvConfig() {
|
|
340
|
+
if (this.envConfigCache) {
|
|
341
|
+
return this.envConfigCache;
|
|
342
|
+
}
|
|
343
|
+
await lastValueFrom(this.http
|
|
344
|
+
.get('/rest/envconfig')
|
|
345
|
+
.pipe(tap((result) => (this.envConfigCache = result))));
|
|
346
|
+
return this.envConfigCache;
|
|
347
|
+
}
|
|
348
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: EnvConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
349
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: EnvConfigService, providedIn: 'root' }); }
|
|
350
|
+
}
|
|
351
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: EnvConfigService, decorators: [{
|
|
352
|
+
type: Injectable,
|
|
353
|
+
args: [{
|
|
354
|
+
providedIn: 'root',
|
|
355
|
+
}]
|
|
356
|
+
}] });
|
|
357
|
+
|
|
358
|
+
class LocalNodesService {
|
|
359
|
+
constructor() {
|
|
360
|
+
this.http = inject(HttpClient);
|
|
361
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
362
|
+
}
|
|
363
|
+
async getLuigiNodesFromConfigurations(contentConfigurations) {
|
|
364
|
+
if (contentConfigurations.length === 0) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
const language = this.luigiCoreService.i18n().getCurrentLocale();
|
|
368
|
+
return await lastValueFrom(this.http.post(`/rest/localnodes`, {
|
|
369
|
+
language,
|
|
370
|
+
contentConfigurations,
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LocalNodesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
374
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LocalNodesService, providedIn: 'root' }); }
|
|
375
|
+
}
|
|
376
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LocalNodesService, decorators: [{
|
|
377
|
+
type: Injectable,
|
|
378
|
+
args: [{
|
|
379
|
+
providedIn: 'root',
|
|
380
|
+
}]
|
|
381
|
+
}] });
|
|
382
|
+
|
|
383
|
+
const ERROR_COMPONENT_CONFIG = 'OPENMFP_ERROR_COMPONENT_CONFIG';
|
|
384
|
+
const THEMING_SERVICE = 'OPENMFP_THEMING_SERVICE';
|
|
385
|
+
const LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_STATIC_SETTINGS_CONFIG_SERVICE';
|
|
386
|
+
const LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN = 'OPENMFP_LUIGI_CUSTOM_MESSAGE_LISTENERS';
|
|
387
|
+
const LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE';
|
|
388
|
+
const LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_APP_SWITCHER_CONFIG_SERVICE';
|
|
389
|
+
const LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_USER_PROFILE_CONFIG_SERVICE';
|
|
390
|
+
const LUIGI_BREADCRUMB_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_BREADCRUMB_CONFIG_SERVICE';
|
|
391
|
+
const LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_NODE_CHANGE_HOOK_CONFIG_SERVICE';
|
|
392
|
+
const LUIGI_EXTENDED_GLOBAL_CONTEXT_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_NODES_EXTENDED_CONTEXT_SERVICE';
|
|
393
|
+
const LOCAL_CONFIGURATION_SERVICE_INJECTION_TOKEN = 'OPENMFP_LOCAL_CONFIGURATION_SERVICE';
|
|
394
|
+
const LUIGI_NODES_CUSTOM_GLOBAL_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_NODES_CUSTOM_GLOBAL_SERVICE';
|
|
395
|
+
const LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_CUSTOM_NODE_PROCESSING_SERVICE';
|
|
396
|
+
const LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE';
|
|
397
|
+
const LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE';
|
|
398
|
+
const HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_HEADER_BAR_CONFIG_SERVICE';
|
|
399
|
+
const LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN = 'OPENMFP_LUIGI_ROUTING_CONFIG_SERVICE';
|
|
400
|
+
|
|
401
|
+
class GlobalContextConfigService {
|
|
402
|
+
constructor() {
|
|
403
|
+
this.authService = inject(AuthService);
|
|
404
|
+
this.configService = inject(ConfigService);
|
|
405
|
+
this.luigiExtendedGlobalContextConfigService = inject(LUIGI_EXTENDED_GLOBAL_CONTEXT_CONFIG_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
406
|
+
}
|
|
407
|
+
async getGlobalContext() {
|
|
408
|
+
const portalConfig = await this.configService.getPortalConfig();
|
|
409
|
+
const userInfo = this.authService.getUserInfo();
|
|
410
|
+
return {
|
|
411
|
+
...(await this.luigiExtendedGlobalContextConfigService?.createLuigiExtendedGlobalContext()),
|
|
412
|
+
portalBaseUrl: window.location.origin,
|
|
413
|
+
portalContext: portalConfig.portalContext,
|
|
414
|
+
userId: userInfo.userId,
|
|
415
|
+
userEmail: userInfo.email,
|
|
416
|
+
token: this.authService.getToken(),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GlobalContextConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
420
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GlobalContextConfigService, providedIn: 'root' }); }
|
|
421
|
+
}
|
|
422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GlobalContextConfigService, decorators: [{
|
|
423
|
+
type: Injectable,
|
|
424
|
+
args: [{ providedIn: 'root' }]
|
|
425
|
+
}] });
|
|
426
|
+
|
|
427
|
+
class SessionRefreshService {
|
|
428
|
+
constructor(authService, luigiCoreService, navigationGlobalContextConfigService) {
|
|
429
|
+
this.authService = authService;
|
|
430
|
+
this.luigiCoreService = luigiCoreService;
|
|
431
|
+
this.navigationGlobalContextConfigService = navigationGlobalContextConfigService;
|
|
432
|
+
}
|
|
433
|
+
async refresh() {
|
|
434
|
+
const isRefreshed = await this.authService.refresh();
|
|
435
|
+
if (!isRefreshed) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
this.authService.authEvent(AuthEvent.AUTH_REFRESHED);
|
|
439
|
+
this.luigiCoreService.setAuthData(this.authService.getAuthData());
|
|
440
|
+
this.luigiCoreService.setGlobalContext(await this.navigationGlobalContextConfigService.getGlobalContext(), true);
|
|
441
|
+
}
|
|
442
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: SessionRefreshService, deps: [{ token: AuthService }, { token: LuigiCoreService }, { token: GlobalContextConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
443
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: SessionRefreshService, providedIn: 'root' }); }
|
|
444
|
+
}
|
|
445
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: SessionRefreshService, decorators: [{
|
|
446
|
+
type: Injectable,
|
|
447
|
+
args: [{ providedIn: 'root' }]
|
|
448
|
+
}], ctorParameters: () => [{ type: AuthService }, { type: LuigiCoreService }, { type: GlobalContextConfigService }] });
|
|
449
|
+
|
|
450
|
+
class I18nService {
|
|
451
|
+
constructor() {
|
|
452
|
+
this.envConfigService = inject(EnvConfigService);
|
|
453
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
454
|
+
this.fallbackLanguage = 'en';
|
|
455
|
+
this.translationTable = {};
|
|
456
|
+
this.currentLanguage = '';
|
|
457
|
+
}
|
|
458
|
+
afterInit() {
|
|
459
|
+
this.currentLanguage = this.luigiCoreService.i18n().getCurrentLocale();
|
|
460
|
+
this.luigiCoreService
|
|
461
|
+
.i18n()
|
|
462
|
+
.addCurrentLocaleChangeListener((locale) => {
|
|
463
|
+
this.currentLanguage = locale;
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* get translation synchronously. If nothing is found for current locale try to get tranlsation for fallback language
|
|
468
|
+
*
|
|
469
|
+
* @param key search key
|
|
470
|
+
* @param interpolations in translation table
|
|
471
|
+
* @param locale
|
|
472
|
+
* @returns returns translated search key or search key, if nothing matched
|
|
473
|
+
*/
|
|
474
|
+
getTranslation(key, interpolations, locale) {
|
|
475
|
+
let result = this.getInternalTranslation(key, interpolations, locale);
|
|
476
|
+
// fallback language
|
|
477
|
+
if (!result) {
|
|
478
|
+
result = this.findTranslation(key, this.translationTable, this.fallbackLanguage, interpolations);
|
|
479
|
+
}
|
|
480
|
+
return result ? result : key;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Get translation asynchronously (especially for logout and theming translation in user settings dialog).
|
|
484
|
+
* If nothing is found for current locale try to get translation for fallback language
|
|
485
|
+
*
|
|
486
|
+
* @param key search key
|
|
487
|
+
* @param interpolations in translation table
|
|
488
|
+
* @param locale
|
|
489
|
+
* @returns returns translated search key or search key, if nothing matched
|
|
490
|
+
*/
|
|
491
|
+
async getTranslationAsync(key, interpolations, locale) {
|
|
492
|
+
return new Promise((res) => {
|
|
493
|
+
let result = this.getInternalTranslation(key, interpolations, locale);
|
|
494
|
+
// fallback language
|
|
495
|
+
if (!result) {
|
|
496
|
+
if (this.translationTable &&
|
|
497
|
+
!this.translationTable[this.fallbackLanguage]) {
|
|
498
|
+
this.fetchTranslationFile(this.fallbackLanguage).then(() => {
|
|
499
|
+
result = this.findTranslation(key, this.translationTable, this.fallbackLanguage, interpolations);
|
|
500
|
+
res(result ? result : key);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
result = this.findTranslation(key, this.translationTable, this.fallbackLanguage, interpolations);
|
|
505
|
+
res(result ? result : key);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
res(result ? result : key);
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Finds the translated value based on given key.
|
|
515
|
+
*
|
|
516
|
+
* @param key key to be translated
|
|
517
|
+
* @param translationTable translation table
|
|
518
|
+
* @param locale current language
|
|
519
|
+
* @param interpolations in translation table
|
|
520
|
+
* @returns translation value
|
|
521
|
+
*/
|
|
522
|
+
findTranslation(key, translationTable, locale, interpolations) {
|
|
523
|
+
if (translationTable[locale]) {
|
|
524
|
+
const translation = typeof translationTable[locale][key] === 'object'
|
|
525
|
+
? translationTable[locale][key].join('<br>')
|
|
526
|
+
: translationTable[locale][key];
|
|
527
|
+
if (interpolations) {
|
|
528
|
+
return this.findInterpolations(translation, interpolations);
|
|
529
|
+
}
|
|
530
|
+
return translation;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Replaces values that are defined in translation strings
|
|
535
|
+
*
|
|
536
|
+
* @param value to be translated
|
|
537
|
+
* @param interpolations in translation table
|
|
538
|
+
* @returns interpolation
|
|
539
|
+
* @example
|
|
540
|
+
* findInterpolations('Environment {num}', {num: 1})
|
|
541
|
+
*/
|
|
542
|
+
findInterpolations(value, interpolations) {
|
|
543
|
+
if (value) {
|
|
544
|
+
Object.keys(interpolations).forEach((item) => {
|
|
545
|
+
value = value.replace(new RegExp('{' + item + '}', 'gi'), interpolations[item]);
|
|
546
|
+
});
|
|
547
|
+
return value;
|
|
548
|
+
}
|
|
549
|
+
return undefined;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* wraps fetched translation table to a specific locale
|
|
553
|
+
*
|
|
554
|
+
* @param locale current language
|
|
555
|
+
* @param data translation json object for specific locale
|
|
556
|
+
*/
|
|
557
|
+
addTranslationFile(locale, data) {
|
|
558
|
+
if (data && locale) {
|
|
559
|
+
this.translationTable[locale] = data;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* fetch generated translation json files
|
|
564
|
+
*
|
|
565
|
+
* @param locale current language
|
|
566
|
+
* @returns translationTable for a specific language
|
|
567
|
+
*/
|
|
568
|
+
async fetchTranslationFile(locale) {
|
|
569
|
+
return new Promise((res) => {
|
|
570
|
+
fetch(`/assets/translation-files/${locale}.json`)
|
|
571
|
+
.then((response) => {
|
|
572
|
+
return response.json();
|
|
573
|
+
})
|
|
574
|
+
.then((data) => {
|
|
575
|
+
this.addTranslationFile(locale, data);
|
|
576
|
+
res(true);
|
|
577
|
+
})
|
|
578
|
+
.catch((error) => {
|
|
579
|
+
console.error('Error:', error);
|
|
580
|
+
this.addTranslationFile(locale, {});
|
|
581
|
+
res(false);
|
|
582
|
+
});
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
*
|
|
587
|
+
* @param key search key
|
|
588
|
+
* @param interpolations in translation table
|
|
589
|
+
* @param locale
|
|
590
|
+
* @returns tranlsated search key or search key, if nothing matched
|
|
591
|
+
*/
|
|
592
|
+
getInternalTranslation(key, interpolations, locale) {
|
|
593
|
+
if (!key)
|
|
594
|
+
return '';
|
|
595
|
+
this.currentLanguage =
|
|
596
|
+
locale ||
|
|
597
|
+
this.currentLanguage ||
|
|
598
|
+
this.luigiCoreService.i18n().getCurrentLocale();
|
|
599
|
+
return this.findTranslation(key, this.translationTable, this.currentLanguage, interpolations);
|
|
600
|
+
}
|
|
601
|
+
async getValidLanguages() {
|
|
602
|
+
const languages = [
|
|
603
|
+
{ value: 'en', label: 'USERSETTINGSDIALOG_LANGUAGE_EN' },
|
|
604
|
+
];
|
|
605
|
+
try {
|
|
606
|
+
const { developmentInstance } = await this.envConfigService.getEnvConfig();
|
|
607
|
+
if (developmentInstance) {
|
|
608
|
+
languages.push({
|
|
609
|
+
value: 'de',
|
|
610
|
+
label: 'USERSETTINGSDIALOG_LANGUAGE_DE',
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
finally {
|
|
615
|
+
return languages;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: I18nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
619
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: I18nService, providedIn: 'root' }); }
|
|
620
|
+
}
|
|
621
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: I18nService, decorators: [{
|
|
622
|
+
type: Injectable,
|
|
623
|
+
args: [{
|
|
624
|
+
providedIn: 'root',
|
|
625
|
+
}]
|
|
626
|
+
}] });
|
|
627
|
+
|
|
628
|
+
var LoginEventType;
|
|
629
|
+
(function (LoginEventType) {
|
|
630
|
+
LoginEventType["LOGIN_TRIGGERED"] = "LoginTriggered";
|
|
631
|
+
LoginEventType["LOGOUT_TRIGGERED"] = "LogoutTriggered";
|
|
632
|
+
})(LoginEventType || (LoginEventType = {}));
|
|
633
|
+
class LoginEventService {
|
|
634
|
+
constructor() {
|
|
635
|
+
this.events = new Subject();
|
|
636
|
+
}
|
|
637
|
+
get loginEvents() {
|
|
638
|
+
return this.events.asObservable();
|
|
639
|
+
}
|
|
640
|
+
loginEvent(event) {
|
|
641
|
+
this.events.next(event);
|
|
642
|
+
}
|
|
643
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LoginEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
644
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LoginEventService, providedIn: 'root' }); }
|
|
645
|
+
}
|
|
646
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LoginEventService, decorators: [{
|
|
647
|
+
type: Injectable,
|
|
648
|
+
args: [{ providedIn: 'root' }]
|
|
649
|
+
}] });
|
|
650
|
+
|
|
651
|
+
var LocalStorageKeys;
|
|
652
|
+
(function (LocalStorageKeys) {
|
|
653
|
+
LocalStorageKeys["LAST_NAVIGATION_URL"] = "openmfp.navigation.lastUrl";
|
|
654
|
+
LocalStorageKeys["USER_SETTINGS"] = "openmfp.settings.userSettings";
|
|
655
|
+
LocalStorageKeys["LOCAL_DEVELOPMENT_SETTINGS"] = "openmfp.settings.localDevelopmentSettings";
|
|
656
|
+
LocalStorageKeys["FEATURE_TOGGLE_SETTINGS"] = "openmfp.settings.featureToggleSettings";
|
|
657
|
+
// deprecated to be removed
|
|
658
|
+
LocalStorageKeys["DEVELOPMENT_MODE_CONFIG"] = "dev-mode-settings";
|
|
659
|
+
})(LocalStorageKeys || (LocalStorageKeys = {}));
|
|
660
|
+
const localDevelopmentSettingsLocalStorage = {
|
|
661
|
+
read: (localStorageKey) => {
|
|
662
|
+
let localDevelopmentSettingsFromLocalStore;
|
|
663
|
+
try {
|
|
664
|
+
localDevelopmentSettingsFromLocalStore = localStorage.getItem(localStorageKey || LocalStorageKeys.LOCAL_DEVELOPMENT_SETTINGS);
|
|
665
|
+
localStorageKey && localStorage.removeItem(localStorageKey);
|
|
666
|
+
}
|
|
667
|
+
catch (e) {
|
|
668
|
+
console.warn('localStorage is not available:', e);
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
try {
|
|
672
|
+
return JSON.parse(localDevelopmentSettingsFromLocalStore);
|
|
673
|
+
}
|
|
674
|
+
catch (e) {
|
|
675
|
+
console.error('Failed to parse the local development settings in your localstorage.', e);
|
|
676
|
+
}
|
|
677
|
+
return null;
|
|
678
|
+
},
|
|
679
|
+
store: (localDevelopmentSetting) => {
|
|
680
|
+
try {
|
|
681
|
+
localStorage.setItem(LocalStorageKeys.LOCAL_DEVELOPMENT_SETTINGS, JSON.stringify(localDevelopmentSetting));
|
|
682
|
+
}
|
|
683
|
+
catch (e) {
|
|
684
|
+
console.error('Failed to stringify the local development settings setting into your localstorage.', e);
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
};
|
|
688
|
+
const userSettingsLocalStorage = {
|
|
689
|
+
read: async (userInfo) => {
|
|
690
|
+
const transientSettings = {
|
|
691
|
+
frame_userAccount: {
|
|
692
|
+
name: userInfo.name || '',
|
|
693
|
+
email: userInfo.email || '',
|
|
694
|
+
},
|
|
695
|
+
};
|
|
696
|
+
return new Promise((resolve, reject) => {
|
|
697
|
+
try {
|
|
698
|
+
const storedSettings = localStorage.getItem(LocalStorageKeys.USER_SETTINGS);
|
|
699
|
+
const settings = storedSettings ? JSON.parse(storedSettings) : {};
|
|
700
|
+
const resultingSettings = { ...settings, ...transientSettings };
|
|
701
|
+
if (settings.frame_userAccount && transientSettings.frame_userAccount) {
|
|
702
|
+
resultingSettings.frame_userAccount = {
|
|
703
|
+
...settings.frame_userAccount,
|
|
704
|
+
...transientSettings.frame_userAccount,
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
if (resultingSettings.frame_userAccount?.language === undefined) {
|
|
708
|
+
resultingSettings.frame_userAccount.language = 'en';
|
|
709
|
+
}
|
|
710
|
+
resolve(resultingSettings);
|
|
711
|
+
}
|
|
712
|
+
catch (e) {
|
|
713
|
+
console.error('Error reading user settings', e);
|
|
714
|
+
reject({
|
|
715
|
+
closeDialog: true,
|
|
716
|
+
message: 'Could not read userSettings from storage...',
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
},
|
|
721
|
+
store: async (settings) => {
|
|
722
|
+
if (settings.frame_userAccount && settings.frame_userAccount.language) {
|
|
723
|
+
delete settings.frame_userAccount.name;
|
|
724
|
+
delete settings.frame_userAccount.email;
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
delete settings.frame_userAccount;
|
|
728
|
+
}
|
|
729
|
+
return new Promise((resolve, reject) => {
|
|
730
|
+
try {
|
|
731
|
+
localStorage.setItem(LocalStorageKeys.USER_SETTINGS, JSON.stringify(settings));
|
|
732
|
+
resolve(settings);
|
|
733
|
+
}
|
|
734
|
+
catch (e) {
|
|
735
|
+
console.error('Error storing user settings', e);
|
|
736
|
+
reject({
|
|
737
|
+
closeDialog: true,
|
|
738
|
+
message: 'Could not write userSettings to storage...',
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
});
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
const featureToggleLocalStorage = {
|
|
745
|
+
read: () => {
|
|
746
|
+
try {
|
|
747
|
+
const storedSettings = localStorage.getItem(LocalStorageKeys.FEATURE_TOGGLE_SETTINGS);
|
|
748
|
+
return storedSettings ? JSON.parse(storedSettings) : {};
|
|
749
|
+
}
|
|
750
|
+
catch (e) {
|
|
751
|
+
console.error('Error reading feature toggle settings', e);
|
|
752
|
+
return {};
|
|
753
|
+
}
|
|
754
|
+
},
|
|
755
|
+
store: (featureToggleSettings) => {
|
|
756
|
+
try {
|
|
757
|
+
localStorage.setItem(LocalStorageKeys.FEATURE_TOGGLE_SETTINGS, JSON.stringify(featureToggleSettings));
|
|
758
|
+
}
|
|
759
|
+
catch (e) {
|
|
760
|
+
console.error('Error storing feature toggle settings', e);
|
|
761
|
+
}
|
|
762
|
+
},
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
class IframeService {
|
|
766
|
+
constructor() {
|
|
767
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
768
|
+
}
|
|
769
|
+
isIFrameFeaturePolicyAllowed(policy, iframeURL) {
|
|
770
|
+
// should be connected to a still to be developed permission management logic
|
|
771
|
+
return true;
|
|
772
|
+
}
|
|
773
|
+
isIFrameSandboxPermissionAllowed(policy, iframeURL) {
|
|
774
|
+
// should be connected to a still to be developed permission management logic
|
|
775
|
+
return true;
|
|
776
|
+
}
|
|
777
|
+
iFrameCreationInterceptor() {
|
|
778
|
+
return (iframe, viewGroup, navigationNode, microFrontendType) => {
|
|
779
|
+
this.applyIframePermissions(iframe, navigationNode, viewGroup);
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
applyIframePermissions(iframe, node, viewGroup) {
|
|
783
|
+
let permissions = node?.requiredIFramePermissions;
|
|
784
|
+
if (!permissions && viewGroup) {
|
|
785
|
+
const viewGroupSettings = this.luigiCoreService.getConfigValue('navigation.viewGroupSettings');
|
|
786
|
+
const viewGroupConfig = (viewGroupSettings && viewGroupSettings[viewGroup]) || {};
|
|
787
|
+
permissions = viewGroupConfig.requiredIFramePermissions;
|
|
788
|
+
}
|
|
789
|
+
if (!permissions) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (permissions.allow) {
|
|
793
|
+
let allow = (iframe.getAttribute('allow') || '').trim();
|
|
794
|
+
if (allow.length > 0 && !allow.endsWith(';')) {
|
|
795
|
+
allow += ';';
|
|
796
|
+
}
|
|
797
|
+
permissions.allow.forEach((policy) => {
|
|
798
|
+
if (this.isIFrameFeaturePolicyAllowed(policy, iframe.getAttribute('src'))) {
|
|
799
|
+
// feature policies are separated by semicolon
|
|
800
|
+
allow += ` ${policy};`;
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
iframe.setAttribute('allow', allow.trim());
|
|
804
|
+
}
|
|
805
|
+
if (permissions.sandbox) {
|
|
806
|
+
let sandbox = (iframe.getAttribute('sandbox') || '').trim();
|
|
807
|
+
permissions.sandbox.forEach((permission) => {
|
|
808
|
+
if (this.isIFrameSandboxPermissionAllowed(permission, iframe.getAttribute('src'))) {
|
|
809
|
+
// sandbox permission are separated by whitespace
|
|
810
|
+
sandbox += ' ' + permission;
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
iframe.setAttribute('sandbox', sandbox.trim());
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IframeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
817
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IframeService, providedIn: 'root' }); }
|
|
818
|
+
}
|
|
819
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IframeService, decorators: [{
|
|
820
|
+
type: Injectable,
|
|
821
|
+
args: [{
|
|
822
|
+
providedIn: 'root',
|
|
823
|
+
}]
|
|
824
|
+
}] });
|
|
825
|
+
|
|
826
|
+
class StaticSettingsConfigServiceImpl {
|
|
827
|
+
constructor() {
|
|
828
|
+
this.customStaticSettingsConfigService = inject(LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN, {
|
|
829
|
+
optional: true,
|
|
830
|
+
});
|
|
831
|
+
this.i18nService = inject(I18nService);
|
|
832
|
+
this.iframeService = inject(IframeService);
|
|
833
|
+
}
|
|
834
|
+
async getStaticSettingsConfig() {
|
|
835
|
+
const logo = 'assets/images/logo.png';
|
|
836
|
+
const favicon = 'assets/images/favicon.ico';
|
|
837
|
+
return {
|
|
838
|
+
header: {
|
|
839
|
+
title: 'OpenMFP Portal',
|
|
840
|
+
logo,
|
|
841
|
+
favicon,
|
|
842
|
+
},
|
|
843
|
+
globalSideNavigation: true,
|
|
844
|
+
experimental: {
|
|
845
|
+
btpToolLayout: true,
|
|
846
|
+
globalNav: true,
|
|
847
|
+
},
|
|
848
|
+
btpToolLayout: true,
|
|
849
|
+
responsiveNavigation: 'Fiori3',
|
|
850
|
+
featureToggles: {
|
|
851
|
+
queryStringParam: 'ft',
|
|
852
|
+
},
|
|
853
|
+
appLoadingIndicator: {
|
|
854
|
+
hideAutomatically: true,
|
|
855
|
+
},
|
|
856
|
+
iframeCreationInterceptor: this.iframeService.iFrameCreationInterceptor(),
|
|
857
|
+
customTranslationImplementation: this.i18nService,
|
|
858
|
+
...(await this.customStaticSettingsConfigService?.getStaticSettingsConfig()),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: StaticSettingsConfigServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
862
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: StaticSettingsConfigServiceImpl, providedIn: 'root' }); }
|
|
863
|
+
}
|
|
864
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: StaticSettingsConfigServiceImpl, decorators: [{
|
|
865
|
+
type: Injectable,
|
|
866
|
+
args: [{
|
|
867
|
+
providedIn: 'root',
|
|
868
|
+
}]
|
|
869
|
+
}] });
|
|
870
|
+
|
|
871
|
+
class ReloadLuigiConfigListener {
|
|
872
|
+
constructor() {
|
|
873
|
+
this.configService = inject(ConfigService);
|
|
874
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
875
|
+
}
|
|
876
|
+
messageId() {
|
|
877
|
+
return 'openmfp.reload-luigi-config';
|
|
878
|
+
}
|
|
879
|
+
async onCustomMessageReceived(customMessage, mfObject, mfNodesObject) {
|
|
880
|
+
console.debug(`Reloading Luigi config from ${customMessage.origin}, action: ${customMessage.action}
|
|
881
|
+
for entity: ${customMessage.entity ?? 'global'}
|
|
882
|
+
with context: ${JSON.stringify(customMessage.context)}`);
|
|
883
|
+
await this.configService.reloadConfig(customMessage.entity, customMessage.context);
|
|
884
|
+
this.luigiCoreService.resetLuigi();
|
|
885
|
+
}
|
|
886
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ReloadLuigiConfigListener, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
887
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ReloadLuigiConfigListener, providedIn: 'root' }); }
|
|
888
|
+
}
|
|
889
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ReloadLuigiConfigListener, decorators: [{
|
|
890
|
+
type: Injectable,
|
|
891
|
+
args: [{
|
|
892
|
+
providedIn: 'root',
|
|
893
|
+
}]
|
|
894
|
+
}] });
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* This class holds the customMessageListeners for custom messages used by the application portal.
|
|
898
|
+
* See also {@link https://docs.luigi-project.io/docs/communication/?section=luigi-core-to-luigi-client}
|
|
899
|
+
* See also {@link https://docs.luigi-project.io/docs/luigi-core-api/?section=custommessages}
|
|
900
|
+
*/
|
|
901
|
+
class CustomMessageListenersService {
|
|
902
|
+
constructor(messageListeners, customMessageListeners) {
|
|
903
|
+
this.messageListeners = messageListeners;
|
|
904
|
+
this.customMessageListeners = customMessageListeners;
|
|
905
|
+
this.listeners = [this.messageListeners, ...(this.customMessageListeners || []).filter((l) => !!l)];
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* An object containing the property 'listeners' in which the message-id and listener assignments are made.
|
|
909
|
+
* See also {@link https://docs.luigi-project.io/docs/communication/?section=luigi-core-to-luigi-client}
|
|
910
|
+
*/
|
|
911
|
+
getMessageListeners() {
|
|
912
|
+
const result = { customMessagesListeners: {} };
|
|
913
|
+
for (const listener of this.listeners) {
|
|
914
|
+
const obj = {
|
|
915
|
+
[listener.messageId()]: (msg, mf, mfNodes) => {
|
|
916
|
+
listener.onCustomMessageReceived(msg, mf, mfNodes);
|
|
917
|
+
},
|
|
918
|
+
};
|
|
919
|
+
Object.assign(result.customMessagesListeners, obj);
|
|
920
|
+
}
|
|
921
|
+
return result;
|
|
922
|
+
}
|
|
923
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CustomMessageListenersService, deps: [{ token: ReloadLuigiConfigListener }, { token: LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
924
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CustomMessageListenersService, providedIn: 'root' }); }
|
|
925
|
+
}
|
|
926
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CustomMessageListenersService, decorators: [{
|
|
927
|
+
type: Injectable,
|
|
928
|
+
args: [{
|
|
929
|
+
providedIn: 'root',
|
|
930
|
+
}]
|
|
931
|
+
}], ctorParameters: () => [{ type: ReloadLuigiConfigListener }, { type: undefined, decorators: [{
|
|
932
|
+
type: Optional
|
|
933
|
+
}, {
|
|
934
|
+
type: Inject,
|
|
935
|
+
args: [LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN]
|
|
936
|
+
}] }] });
|
|
937
|
+
|
|
938
|
+
class DependenciesVersionsService {
|
|
939
|
+
constructor() {
|
|
940
|
+
this.httpClient = inject(HttpClient);
|
|
941
|
+
}
|
|
942
|
+
read() {
|
|
943
|
+
return firstValueFrom(this.httpClient.get('/assets/dependencies-versions.json'));
|
|
944
|
+
}
|
|
945
|
+
transformVersionsConfig(versionsConfig) {
|
|
946
|
+
return Object.entries(versionsConfig).reduce((acc, [key, value]) => {
|
|
947
|
+
const label = key
|
|
948
|
+
.replace(/([A-Z])/g, ' $1')
|
|
949
|
+
.replace(/^./, (char) => char.toUpperCase());
|
|
950
|
+
acc[key] = {
|
|
951
|
+
type: 'string',
|
|
952
|
+
label,
|
|
953
|
+
value,
|
|
954
|
+
isEditable: false,
|
|
955
|
+
};
|
|
956
|
+
return acc;
|
|
957
|
+
}, {});
|
|
958
|
+
}
|
|
959
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: DependenciesVersionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
960
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: DependenciesVersionsService, providedIn: 'root' }); }
|
|
961
|
+
}
|
|
962
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: DependenciesVersionsService, decorators: [{
|
|
963
|
+
type: Injectable,
|
|
964
|
+
args: [{ providedIn: 'root' }]
|
|
965
|
+
}] });
|
|
966
|
+
|
|
967
|
+
class UserSettingsConfigService {
|
|
968
|
+
constructor() {
|
|
969
|
+
this.luigiThemingService = inject(THEMING_SERVICE, {
|
|
970
|
+
optional: true,
|
|
971
|
+
});
|
|
972
|
+
this.authService = inject(AuthService);
|
|
973
|
+
this.i18nService = inject(I18nService);
|
|
974
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
975
|
+
this.dependenciesVersionsService = inject(DependenciesVersionsService);
|
|
976
|
+
this.envConfigService = inject(EnvConfigService);
|
|
977
|
+
this.versionsConfig = {};
|
|
978
|
+
}
|
|
979
|
+
async getUserSettings(childrenByEntity) {
|
|
980
|
+
const userSettingsConfig = this.extractUserSettings(childrenByEntity);
|
|
981
|
+
const groupsFromNodes = this.getGroupsFromUserSettings(userSettingsConfig);
|
|
982
|
+
this.versionsConfig = await this.readDependenciesVersions();
|
|
983
|
+
const envConfig = await this.envConfigService.getEnvConfig();
|
|
984
|
+
let coreGroups = await this.getCoreUserSettingsGroups();
|
|
985
|
+
const userSettings = {
|
|
986
|
+
userSettingsProfileMenuEntry: {
|
|
987
|
+
label: 'USERSETTINGSPROFILEMENUENTRY_SETTINGS',
|
|
988
|
+
},
|
|
989
|
+
userSettingsDialog: {
|
|
990
|
+
dismissBtn: 'USERSETTINGSDIALOG_CANCEL',
|
|
991
|
+
saveBtn: 'USERSETTINGSDIALOG_SAVE',
|
|
992
|
+
dialogHeader: 'USERSETTINGSDIALOG_HEADER',
|
|
993
|
+
},
|
|
994
|
+
userSettingGroups: { ...coreGroups, ...groupsFromNodes },
|
|
995
|
+
readUserSettings: async () => {
|
|
996
|
+
const setting = (await userSettingsLocalStorage.read(this.authService.getUserInfo())) || {};
|
|
997
|
+
setting.frame_versions = this.versionsConfig;
|
|
998
|
+
return setting;
|
|
999
|
+
},
|
|
1000
|
+
storeUserSettings: async (settings, previous) => {
|
|
1001
|
+
userSettingsLocalStorage.store(settings);
|
|
1002
|
+
this.applyNewTheme(settings, previous);
|
|
1003
|
+
this.changeToSelectedLanguage(settings, previous);
|
|
1004
|
+
this.saveLocalDevelopmentSettings(settings, previous);
|
|
1005
|
+
if (envConfig.uiOptions.includes('enableFeatureToggleSetting')) {
|
|
1006
|
+
this.saveFeatureToggleSettings(settings);
|
|
1007
|
+
}
|
|
1008
|
+
},
|
|
1009
|
+
};
|
|
1010
|
+
return userSettings;
|
|
1011
|
+
}
|
|
1012
|
+
async getCoreUserSettingsGroups() {
|
|
1013
|
+
const envConfig = await this.envConfigService.getEnvConfig();
|
|
1014
|
+
const settings = {};
|
|
1015
|
+
await this.addUserSettings(settings);
|
|
1016
|
+
await this.addThemingSettings(settings);
|
|
1017
|
+
this.addLocalDevelopmentSettings(settings);
|
|
1018
|
+
if (envConfig.uiOptions.includes('enableFeatureToggleSetting')) {
|
|
1019
|
+
this.addFeatureToggleSettings(settings);
|
|
1020
|
+
}
|
|
1021
|
+
this.addInfoSettings(settings);
|
|
1022
|
+
return settings;
|
|
1023
|
+
}
|
|
1024
|
+
saveFeatureToggleSettings(settings) {
|
|
1025
|
+
const currentFeatureToggleSettings = settings?.frame_featureToggle?.featureToggleSettings;
|
|
1026
|
+
featureToggleLocalStorage.store(currentFeatureToggleSettings);
|
|
1027
|
+
this.luigiCoreService.unsetAllFeatureToggles();
|
|
1028
|
+
this.luigiCoreService.setFeatureToggles(currentFeatureToggleSettings);
|
|
1029
|
+
globalThis.location.reload();
|
|
1030
|
+
}
|
|
1031
|
+
saveLocalDevelopmentSettings(settings, previous) {
|
|
1032
|
+
const currentLocalDevelopmentSettings = settings?.frame_development?.localDevelopmentSettings;
|
|
1033
|
+
const previousLocalDevelopmentSettings = previous?.frame_development?.localDevelopmentSettings;
|
|
1034
|
+
if (currentLocalDevelopmentSettings &&
|
|
1035
|
+
(!localDevelopmentSettingsLocalStorage.read() ||
|
|
1036
|
+
!isEqual(currentLocalDevelopmentSettings, previousLocalDevelopmentSettings))) {
|
|
1037
|
+
localDevelopmentSettingsLocalStorage.store(currentLocalDevelopmentSettings);
|
|
1038
|
+
globalThis.location.reload();
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
extractUserSettings(childrenByEntity) {
|
|
1042
|
+
const userSettings = Object.values(childrenByEntity)
|
|
1043
|
+
.reduce((accumulator, value) => accumulator.concat(value), [])
|
|
1044
|
+
.reduce((accu, n) => {
|
|
1045
|
+
if (n._userSettingsConfig) {
|
|
1046
|
+
accu.push(n._userSettingsConfig);
|
|
1047
|
+
}
|
|
1048
|
+
return accu;
|
|
1049
|
+
}, []);
|
|
1050
|
+
return userSettings;
|
|
1051
|
+
}
|
|
1052
|
+
changeToSelectedLanguage(settings, previous) {
|
|
1053
|
+
if (settings?.frame_userAccount?.language &&
|
|
1054
|
+
previous?.frame_userAccount?.language !==
|
|
1055
|
+
settings?.frame_userAccount?.language) {
|
|
1056
|
+
globalThis.location.reload();
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
applyNewTheme(settings, previous) {
|
|
1060
|
+
if (settings?.frame_appearance?.selectedTheme &&
|
|
1061
|
+
previous?.frame_appearance?.selectedTheme !==
|
|
1062
|
+
settings?.frame_appearance?.selectedTheme) {
|
|
1063
|
+
this.luigiThemingService?.applyTheme(settings.frame_appearance.selectedTheme);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
getGroupsFromUserSettings(luigiUserSettings) {
|
|
1067
|
+
const settingsGroups = {};
|
|
1068
|
+
luigiUserSettings.forEach((userConfig) => {
|
|
1069
|
+
if (userConfig?.groups) {
|
|
1070
|
+
Object.keys(userConfig.groups).forEach((groupId) => {
|
|
1071
|
+
const groupConfig = userConfig.groups[groupId];
|
|
1072
|
+
settingsGroups[groupId] = groupConfig;
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
return settingsGroups;
|
|
1077
|
+
}
|
|
1078
|
+
async getSelectedThemeDisplayName() {
|
|
1079
|
+
const user = this.authService.getUserInfo();
|
|
1080
|
+
const userSettings = await userSettingsLocalStorage.read(user);
|
|
1081
|
+
const selectedTheme = userSettings?.frame_appearance?.selectedTheme ||
|
|
1082
|
+
this.luigiThemingService.getDefaultThemeId();
|
|
1083
|
+
return this.luigiThemingService
|
|
1084
|
+
.getAvailableThemes()
|
|
1085
|
+
.find((t) => t.id === selectedTheme)?.name;
|
|
1086
|
+
}
|
|
1087
|
+
async addThemingSettings(settings) {
|
|
1088
|
+
if (this.luigiThemingService) {
|
|
1089
|
+
settings.frame_appearance = {
|
|
1090
|
+
label: 'USERSETTINGSDIALOG__APPEARANCE',
|
|
1091
|
+
sublabel: await this.getSelectedThemeDisplayName(),
|
|
1092
|
+
icon: 'palette',
|
|
1093
|
+
title: 'USERSETTINGSDIALOG__APPEARANCE',
|
|
1094
|
+
viewUrl: '/settings-theming#disable_loading_indicator',
|
|
1095
|
+
settings: {},
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
addLocalDevelopmentSettings(settings) {
|
|
1100
|
+
settings.frame_development = {
|
|
1101
|
+
label: 'LOCAL_DEVELOPMENT_SETTINGS_DIALOG_LABEL',
|
|
1102
|
+
sublabel: 'LOCAL_DEVELOPMENT_SETTINGS_DIALOG_SUBLABEL',
|
|
1103
|
+
icon: 'developer-settings',
|
|
1104
|
+
iconClassAttribute: localDevelopmentSettingsLocalStorage.read()?.isActive
|
|
1105
|
+
? 'settings-icon-active'
|
|
1106
|
+
: '',
|
|
1107
|
+
title: 'LOCAL_DEVELOPMENT_SETTINGS_DIALOG_TITLE',
|
|
1108
|
+
viewUrl: '/assets/openmfp-portal-ui-wc.js#development-settings',
|
|
1109
|
+
webcomponent: {
|
|
1110
|
+
selfRegistered: true,
|
|
1111
|
+
},
|
|
1112
|
+
context: {
|
|
1113
|
+
translationTable: this.i18nService.translationTable,
|
|
1114
|
+
},
|
|
1115
|
+
};
|
|
1116
|
+
}
|
|
1117
|
+
async addUserSettings(settings) {
|
|
1118
|
+
const userInfo = this.authService.getUserInfo();
|
|
1119
|
+
settings.frame_userAccount = {
|
|
1120
|
+
label: 'USERSETTINGSDIALOG_USER_ACCOUNT',
|
|
1121
|
+
sublabel: userInfo.name,
|
|
1122
|
+
icon: `https://avatars.wdf.sap.corp/avatar/${userInfo.userId}`,
|
|
1123
|
+
title: userInfo.name,
|
|
1124
|
+
initials: userInfo.initials,
|
|
1125
|
+
iconClassAttribute: 'fd-avatar fd-avatar--s fd-avatar--circle fd-avatar--thumbnail lui-avatar-space',
|
|
1126
|
+
settings: {
|
|
1127
|
+
name: {
|
|
1128
|
+
type: 'string',
|
|
1129
|
+
label: 'USERSETTINGSDIALOG_NAME',
|
|
1130
|
+
isEditable: false,
|
|
1131
|
+
},
|
|
1132
|
+
email: {
|
|
1133
|
+
type: 'string',
|
|
1134
|
+
label: 'USERSETTINGSDIALOG_EMAIL',
|
|
1135
|
+
isEditable: false,
|
|
1136
|
+
},
|
|
1137
|
+
},
|
|
1138
|
+
};
|
|
1139
|
+
const validLanguages = await this.i18nService.getValidLanguages();
|
|
1140
|
+
if (validLanguages.length > 1) {
|
|
1141
|
+
settings.frame_userAccount.settings['language'] = {
|
|
1142
|
+
type: 'enum',
|
|
1143
|
+
label: 'USERSETTINGSDIALOG_LANGUAGE',
|
|
1144
|
+
options: validLanguages,
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
addInfoSettings(settings) {
|
|
1149
|
+
const settingsTransformed = this.dependenciesVersionsService.transformVersionsConfig(this.versionsConfig);
|
|
1150
|
+
settings.frame_versions = {
|
|
1151
|
+
label: 'INFO_SETTINGS_DIALOG_LABEL',
|
|
1152
|
+
sublabel: 'INFO_SETTINGS_DIALOG_SUBLABEL',
|
|
1153
|
+
title: 'INFO_SETTINGS_DIALOG_TITLE',
|
|
1154
|
+
icon: 'message-information',
|
|
1155
|
+
settings: settingsTransformed,
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
addFeatureToggleSettings(settings) {
|
|
1159
|
+
const isActive = this.luigiCoreService.getActiveFeatureToggleList().length > 0;
|
|
1160
|
+
settings.frame_featureToggle = {
|
|
1161
|
+
label: 'FEATURE_TOGGLE_SETTINGS_DIALOG_LABEL',
|
|
1162
|
+
sublabel: 'FEATURE_TOGGLE_SETTINGS_DIALOG_SUBLABEL',
|
|
1163
|
+
title: 'FEATURE_TOGGLE_SETTINGS_DIALOG_TITLE',
|
|
1164
|
+
icon: 'activate',
|
|
1165
|
+
iconClassAttribute: isActive ? 'settings-icon-active' : '',
|
|
1166
|
+
viewUrl: '/assets/openmfp-portal-ui-wc.js#feature-toggle',
|
|
1167
|
+
webcomponent: {
|
|
1168
|
+
selfRegistered: true,
|
|
1169
|
+
},
|
|
1170
|
+
context: {
|
|
1171
|
+
translationTable: this.i18nService.translationTable,
|
|
1172
|
+
},
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
async readDependenciesVersions() {
|
|
1176
|
+
const versions = { browser: navigator.userAgent };
|
|
1177
|
+
try {
|
|
1178
|
+
return {
|
|
1179
|
+
...(await this.dependenciesVersionsService.read()),
|
|
1180
|
+
...versions,
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
catch (error) { }
|
|
1184
|
+
return versions;
|
|
1185
|
+
}
|
|
1186
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: UserSettingsConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1187
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: UserSettingsConfigService, providedIn: 'root' }); }
|
|
1188
|
+
}
|
|
1189
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: UserSettingsConfigService, decorators: [{
|
|
1190
|
+
type: Injectable,
|
|
1191
|
+
args: [{ providedIn: 'root' }]
|
|
1192
|
+
}] });
|
|
1193
|
+
|
|
1194
|
+
class NodeUtilsService {
|
|
1195
|
+
constructor(luigiCoreService) {
|
|
1196
|
+
this.luigiCoreService = luigiCoreService;
|
|
1197
|
+
}
|
|
1198
|
+
retrieveGlobalHelpContext() {
|
|
1199
|
+
return (node) => {
|
|
1200
|
+
const ctx = this.luigiCoreService.getGlobalContext();
|
|
1201
|
+
node.context.helpContext = ctx.helpContext;
|
|
1202
|
+
return true;
|
|
1203
|
+
};
|
|
1204
|
+
}
|
|
1205
|
+
isVisible(node) {
|
|
1206
|
+
if (!node.visibleForFeatureToggles) {
|
|
1207
|
+
return true;
|
|
1208
|
+
}
|
|
1209
|
+
return node.visibleForFeatureToggles.every((ft) => {
|
|
1210
|
+
if (ft.startsWith('!')) {
|
|
1211
|
+
return !this.luigiCoreService.isFeatureToggleActive(ft.slice(1));
|
|
1212
|
+
}
|
|
1213
|
+
return this.luigiCoreService.isFeatureToggleActive(ft);
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodeUtilsService, deps: [{ token: LuigiCoreService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1217
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodeUtilsService, providedIn: 'root' }); }
|
|
1218
|
+
}
|
|
1219
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodeUtilsService, decorators: [{
|
|
1220
|
+
type: Injectable,
|
|
1221
|
+
args: [{ providedIn: 'root' }]
|
|
1222
|
+
}], ctorParameters: () => [{ type: LuigiCoreService }] });
|
|
1223
|
+
|
|
1224
|
+
class AppSwitcherConfigServiceImpl {
|
|
1225
|
+
constructor() {
|
|
1226
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
1227
|
+
this.nodeUtilsService = inject(NodeUtilsService);
|
|
1228
|
+
}
|
|
1229
|
+
getAppSwitcher(luigiNodes) {
|
|
1230
|
+
return {
|
|
1231
|
+
keepMainTitle: true,
|
|
1232
|
+
showSubTitle: false,
|
|
1233
|
+
itemRenderer: (item, slot, appSwitcherApiObj) => {
|
|
1234
|
+
const a = document.createElement('a');
|
|
1235
|
+
a.setAttribute('class', 'fd-menu__link');
|
|
1236
|
+
a.addEventListener('click', (e) => {
|
|
1237
|
+
this.luigiCoreService.navigation().navigate(item.link);
|
|
1238
|
+
appSwitcherApiObj.closeDropDown();
|
|
1239
|
+
e.stopPropagation();
|
|
1240
|
+
});
|
|
1241
|
+
const span = document.createElement('span');
|
|
1242
|
+
span.setAttribute('class', 'fd-menu__addon-before');
|
|
1243
|
+
const i = document.createElement('i');
|
|
1244
|
+
i.setAttribute('class', 'sap-icon--' + item.icon);
|
|
1245
|
+
span.appendChild(i);
|
|
1246
|
+
const spanText = document.createElement('span');
|
|
1247
|
+
spanText.setAttribute('class', 'fd-menu__title');
|
|
1248
|
+
spanText.innerText = item.title;
|
|
1249
|
+
a.appendChild(span);
|
|
1250
|
+
a.appendChild(spanText);
|
|
1251
|
+
slot.innerHTML = '';
|
|
1252
|
+
slot.appendChild(a);
|
|
1253
|
+
},
|
|
1254
|
+
items: this.getNodeItems(luigiNodes),
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
getNodeItems(luigiNodes) {
|
|
1258
|
+
const items = (luigiNodes || [])
|
|
1259
|
+
.filter((node) => {
|
|
1260
|
+
return (!node.hideFromNav &&
|
|
1261
|
+
node.entityType === EntityType.GLOBAL &&
|
|
1262
|
+
this.nodeUtilsService.isVisible(node));
|
|
1263
|
+
})
|
|
1264
|
+
.map((node) => {
|
|
1265
|
+
const nodeConfig = {
|
|
1266
|
+
title: node.label,
|
|
1267
|
+
icon: node.icon,
|
|
1268
|
+
link: '/' + node.pathSegment,
|
|
1269
|
+
};
|
|
1270
|
+
return nodeConfig;
|
|
1271
|
+
});
|
|
1272
|
+
return items?.length === 1 ? [] : items;
|
|
1273
|
+
}
|
|
1274
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AppSwitcherConfigServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1275
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AppSwitcherConfigServiceImpl, providedIn: 'root' }); }
|
|
1276
|
+
}
|
|
1277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AppSwitcherConfigServiceImpl, decorators: [{
|
|
1278
|
+
type: Injectable,
|
|
1279
|
+
args: [{ providedIn: 'root' }]
|
|
1280
|
+
}] });
|
|
1281
|
+
|
|
1282
|
+
class HeaderBarService {
|
|
1283
|
+
constructor(headerBarConfig) {
|
|
1284
|
+
this.headerBarConfig = headerBarConfig;
|
|
1285
|
+
}
|
|
1286
|
+
async getConfig() {
|
|
1287
|
+
if (!this.headerBarConfig) {
|
|
1288
|
+
return undefined;
|
|
1289
|
+
}
|
|
1290
|
+
const { leftRenderers, rightRenderers, ...rest } = await this.headerBarConfig.getConfig();
|
|
1291
|
+
return {
|
|
1292
|
+
...rest,
|
|
1293
|
+
renderer: (containerElement, nodeItems, clickHandler) => {
|
|
1294
|
+
containerElement.style.display = 'flex';
|
|
1295
|
+
containerElement.style.position = 'static';
|
|
1296
|
+
containerElement.style.height = 'min-content';
|
|
1297
|
+
const parrent = containerElement.parentElement;
|
|
1298
|
+
if (parrent) {
|
|
1299
|
+
this.setParrentStyles(parrent);
|
|
1300
|
+
}
|
|
1301
|
+
const { rightContainer, leftContainer } = this.createRendererContainers();
|
|
1302
|
+
containerElement.appendChild(leftContainer);
|
|
1303
|
+
containerElement.appendChild(rightContainer);
|
|
1304
|
+
this.executeRenderes(leftContainer, leftRenderers, [nodeItems, clickHandler]);
|
|
1305
|
+
this.executeRenderes(rightContainer, rightRenderers, [nodeItems, clickHandler]);
|
|
1306
|
+
return containerElement;
|
|
1307
|
+
},
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
;
|
|
1311
|
+
setParrentStyles(parrent) {
|
|
1312
|
+
parrent.style.display = 'flex';
|
|
1313
|
+
parrent.style.flexDirection = 'column';
|
|
1314
|
+
parrent.style.height = '100%';
|
|
1315
|
+
parrent.style.marginTop = '0';
|
|
1316
|
+
}
|
|
1317
|
+
executeRenderes(rootContainer, renderers, params) {
|
|
1318
|
+
renderers.forEach((renderer) => {
|
|
1319
|
+
const rendererContainer = document.createElement('div');
|
|
1320
|
+
rootContainer.appendChild(rendererContainer);
|
|
1321
|
+
renderer(rendererContainer, ...params);
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
createRendererContainers() {
|
|
1325
|
+
const rightContainer = document.createElement('div');
|
|
1326
|
+
const leftContainer = document.createElement('div');
|
|
1327
|
+
rightContainer.style.display = 'flex';
|
|
1328
|
+
rightContainer.style.justifyContent = 'flex-end';
|
|
1329
|
+
rightContainer.style.gap = '1em';
|
|
1330
|
+
leftContainer.style.display = 'flex';
|
|
1331
|
+
leftContainer.style.justifyContent = 'flex-start';
|
|
1332
|
+
leftContainer.style.gap = '1em';
|
|
1333
|
+
leftContainer.style.flexGrow = '1';
|
|
1334
|
+
return { rightContainer, leftContainer };
|
|
1335
|
+
}
|
|
1336
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: HeaderBarService, deps: [{ token: HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1337
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: HeaderBarService, providedIn: 'root' }); }
|
|
1338
|
+
}
|
|
1339
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: HeaderBarService, decorators: [{
|
|
1340
|
+
type: Injectable,
|
|
1341
|
+
args: [{ providedIn: 'root' }]
|
|
1342
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
1343
|
+
type: Optional
|
|
1344
|
+
}, {
|
|
1345
|
+
type: Inject,
|
|
1346
|
+
args: [HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN]
|
|
1347
|
+
}] }] });
|
|
1348
|
+
|
|
1349
|
+
class AuthConfigService {
|
|
1350
|
+
constructor() {
|
|
1351
|
+
this.authService = inject(AuthService);
|
|
1352
|
+
this.envConfigService = inject(EnvConfigService);
|
|
1353
|
+
this.luigiAuthEventsCallbacksService = inject(LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
1354
|
+
}
|
|
1355
|
+
async getAuthConfig() {
|
|
1356
|
+
const { oauthServerUrl, clientId } = await this.envConfigService.getEnvConfig();
|
|
1357
|
+
return {
|
|
1358
|
+
use: 'oAuth2AuthCode',
|
|
1359
|
+
storage: 'none',
|
|
1360
|
+
oAuth2AuthCode: {
|
|
1361
|
+
idpProvider: oAuth2,
|
|
1362
|
+
authorizeUrl: oauthServerUrl,
|
|
1363
|
+
logoutUrl: '/rest/logout',
|
|
1364
|
+
post_logout_redirect_uri: '/logout',
|
|
1365
|
+
oAuthData: {
|
|
1366
|
+
client_id: clientId,
|
|
1367
|
+
scope: 'openid',
|
|
1368
|
+
redirect_uri: '/callback',
|
|
1369
|
+
response_type: 'code',
|
|
1370
|
+
},
|
|
1371
|
+
accessTokenExpiringNotificationTime: 60,
|
|
1372
|
+
expirationCheckInterval: 5,
|
|
1373
|
+
userInfoFn: () => {
|
|
1374
|
+
const userInfo = this.authService.getUserInfo();
|
|
1375
|
+
return new Promise((resolve) => {
|
|
1376
|
+
fetch(userInfo.picture, {
|
|
1377
|
+
method: 'HEAD',
|
|
1378
|
+
mode: 'no-cors',
|
|
1379
|
+
})
|
|
1380
|
+
.then(() => {
|
|
1381
|
+
resolve(userInfo);
|
|
1382
|
+
})
|
|
1383
|
+
.catch(() => {
|
|
1384
|
+
userInfo.picture = '';
|
|
1385
|
+
resolve(userInfo);
|
|
1386
|
+
});
|
|
1387
|
+
});
|
|
1388
|
+
},
|
|
1389
|
+
},
|
|
1390
|
+
disableAutoLogin: false,
|
|
1391
|
+
events: {
|
|
1392
|
+
onAuthSuccessful: (settings, authData) => {
|
|
1393
|
+
this.authService.authEvent(AuthEvent.AUTH_SUCCESSFUL);
|
|
1394
|
+
this.luigiAuthEventsCallbacksService?.onAuthSuccessful(settings, authData);
|
|
1395
|
+
},
|
|
1396
|
+
onAuthError: (settings, err) => {
|
|
1397
|
+
this.authService.authEvent(AuthEvent.AUTH_ERROR);
|
|
1398
|
+
this.luigiAuthEventsCallbacksService?.onAuthError(settings, err);
|
|
1399
|
+
},
|
|
1400
|
+
onAuthExpired: (settings) => {
|
|
1401
|
+
this.authService.authEvent(AuthEvent.AUTH_EXPIRED);
|
|
1402
|
+
this.luigiAuthEventsCallbacksService?.onAuthExpired(settings);
|
|
1403
|
+
},
|
|
1404
|
+
onLogout: (settings) => {
|
|
1405
|
+
this.authService.authEvent(AuthEvent.LOGOUT);
|
|
1406
|
+
this.luigiAuthEventsCallbacksService?.onLogout(settings);
|
|
1407
|
+
},
|
|
1408
|
+
onAuthExpireSoon: (settings) => {
|
|
1409
|
+
this.authService.authEvent(AuthEvent.AUTH_EXPIRE_SOON);
|
|
1410
|
+
this.luigiAuthEventsCallbacksService?.onAuthExpireSoon(settings);
|
|
1411
|
+
},
|
|
1412
|
+
onAuthConfigError: (settings, err) => {
|
|
1413
|
+
this.authService.authEvent(AuthEvent.AUTH_CONFIG_ERROR);
|
|
1414
|
+
this.luigiAuthEventsCallbacksService?.onAuthConfigError(settings, err);
|
|
1415
|
+
},
|
|
1416
|
+
},
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AuthConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1420
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AuthConfigService, providedIn: 'root' }); }
|
|
1421
|
+
}
|
|
1422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: AuthConfigService, decorators: [{
|
|
1423
|
+
type: Injectable,
|
|
1424
|
+
args: [{
|
|
1425
|
+
providedIn: 'root',
|
|
1426
|
+
}]
|
|
1427
|
+
}] });
|
|
1428
|
+
|
|
1429
|
+
class LocalConfigurationServiceImpl {
|
|
1430
|
+
constructor() {
|
|
1431
|
+
this.http = inject(HttpClient);
|
|
1432
|
+
this.luigiConfigService = inject(LocalNodesService);
|
|
1433
|
+
this.i18nService = inject(I18nService);
|
|
1434
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
1435
|
+
this.customLocalConfigurationService = inject(LOCAL_CONFIGURATION_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
1436
|
+
}
|
|
1437
|
+
async getLocalNodes() {
|
|
1438
|
+
const localDevelopmentSettings = localDevelopmentSettingsLocalStorage.read();
|
|
1439
|
+
if (!localDevelopmentSettings?.isActive) {
|
|
1440
|
+
return ((await this.customLocalConfigurationService?.getLocalNodes()) || []);
|
|
1441
|
+
}
|
|
1442
|
+
this.addLocalDevelopmentModeOnIndicator();
|
|
1443
|
+
if (this.cachedLocalNodes?.length) {
|
|
1444
|
+
return this.cachedLocalNodes;
|
|
1445
|
+
}
|
|
1446
|
+
try {
|
|
1447
|
+
const configurations = await this.getLocalConfigurations(localDevelopmentSettings);
|
|
1448
|
+
const result = (await this.luigiConfigService.getLuigiNodesFromConfigurations(configurations)) || {};
|
|
1449
|
+
if (result.errors) {
|
|
1450
|
+
this.alertErrors(result.errors);
|
|
1451
|
+
}
|
|
1452
|
+
(result.nodes || []).forEach((node) => {
|
|
1453
|
+
node.context = {
|
|
1454
|
+
...node.context,
|
|
1455
|
+
serviceProviderConfig: {
|
|
1456
|
+
...node.context?.serviceProviderConfig,
|
|
1457
|
+
...localDevelopmentSettings.serviceProviderConfig,
|
|
1458
|
+
},
|
|
1459
|
+
};
|
|
1460
|
+
});
|
|
1461
|
+
return (this.cachedLocalNodes = result.nodes || []);
|
|
1462
|
+
}
|
|
1463
|
+
catch (e) {
|
|
1464
|
+
console.warn(`Failed to retrieve local luigi config.`, e);
|
|
1465
|
+
return [];
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
addLocalDevelopmentModeOnIndicator() {
|
|
1469
|
+
const popoverControl = document.querySelector('#profilePopover');
|
|
1470
|
+
if (popoverControl && popoverControl.parentNode) {
|
|
1471
|
+
const newSpan = document.createElement('span');
|
|
1472
|
+
newSpan.classList.add('sap-icon--developer-settings', 'local-development-settings-indication');
|
|
1473
|
+
newSpan.title = this.i18nService.getTranslation('LOCAL_DEVELOPMENT_SETTINGS_ACTIVE_INDICATOR');
|
|
1474
|
+
popoverControl.parentNode.appendChild(newSpan);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
alertErrors(errors) {
|
|
1478
|
+
const message = errors
|
|
1479
|
+
.map((e) => {
|
|
1480
|
+
return `For configuration with url:
|
|
1481
|
+
${e.url} <br/><br/>
|
|
1482
|
+
${(e.validationErrors || [])
|
|
1483
|
+
.map((v) => v.message)
|
|
1484
|
+
.filter((v) => !v.includes('The document is not valid'))
|
|
1485
|
+
.join('<br/>')}`;
|
|
1486
|
+
})
|
|
1487
|
+
.join('<br/><br/><br/>');
|
|
1488
|
+
this.luigiCoreService.showAlert({
|
|
1489
|
+
text: `
|
|
1490
|
+
Your local development configuration contains error(s).
|
|
1491
|
+
You will not be able to see your local changes and local development results unless you correct the data and reload the page.
|
|
1492
|
+
Please see below the detailed information: <br/><br/>
|
|
1493
|
+
|
|
1494
|
+
${message}
|
|
1495
|
+
`,
|
|
1496
|
+
type: 'error',
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
async replaceServerNodesWithLocalOnes(serverLuigiNodes, currentEntities) {
|
|
1500
|
+
const localNodes = await this.getLocalNodes();
|
|
1501
|
+
console.debug(`Processing local nodes for currentEntities: ${currentEntities}`);
|
|
1502
|
+
if (!localNodes || localNodes.length == 0) {
|
|
1503
|
+
console.debug('No local nodes found');
|
|
1504
|
+
return serverLuigiNodes;
|
|
1505
|
+
}
|
|
1506
|
+
this.logNodesState(serverLuigiNodes, localNodes);
|
|
1507
|
+
const localReplacingNodes = [];
|
|
1508
|
+
const filteredServerNodes = serverLuigiNodes.filter((serverNode) => {
|
|
1509
|
+
const index = localNodes.findIndex((localNode) => {
|
|
1510
|
+
return this.localNodeMatchesServerNode(localNode, serverNode);
|
|
1511
|
+
});
|
|
1512
|
+
if (index !== -1) {
|
|
1513
|
+
const [localFoundNode] = localNodes.splice(index, 1);
|
|
1514
|
+
localReplacingNodes.push(localFoundNode);
|
|
1515
|
+
localFoundNode.context = {
|
|
1516
|
+
...serverNode.context,
|
|
1517
|
+
...localFoundNode.context,
|
|
1518
|
+
};
|
|
1519
|
+
}
|
|
1520
|
+
return index === -1;
|
|
1521
|
+
});
|
|
1522
|
+
const localNewNodes = localNodes.filter((n) => {
|
|
1523
|
+
const entity = n.entityType?.includes('::compound')
|
|
1524
|
+
? 'global'
|
|
1525
|
+
: n.entityType || 'home';
|
|
1526
|
+
return currentEntities.includes(entity);
|
|
1527
|
+
});
|
|
1528
|
+
console.debug(`${filteredServerNodes.length} server nodes have no matching local nodes.
|
|
1529
|
+
Found ${localReplacingNodes.length} matching local nodes.
|
|
1530
|
+
Adding ${localNewNodes.length} new local nodes.`);
|
|
1531
|
+
return filteredServerNodes
|
|
1532
|
+
.concat(localReplacingNodes)
|
|
1533
|
+
.concat(localNewNodes);
|
|
1534
|
+
}
|
|
1535
|
+
logNodesState(serverLuigiNodes, localNodes) {
|
|
1536
|
+
const serverEntityTypes = [
|
|
1537
|
+
...new Set(serverLuigiNodes.map((n) => n.entityType)),
|
|
1538
|
+
]
|
|
1539
|
+
.filter(Boolean)
|
|
1540
|
+
.join(',');
|
|
1541
|
+
const localEntityTypes = [...new Set(localNodes.map((n) => n.entityType))]
|
|
1542
|
+
.filter(Boolean)
|
|
1543
|
+
.join(',');
|
|
1544
|
+
console.debug(`Found '${serverLuigiNodes.length}' server nodes.
|
|
1545
|
+
Found '${localNodes.length}' local luigi nodes.
|
|
1546
|
+
The entities of the server node are: [${serverEntityTypes}]
|
|
1547
|
+
The entities of local nodes are: [${localEntityTypes}]`);
|
|
1548
|
+
}
|
|
1549
|
+
localNodeMatchesServerNode(localNode, node) {
|
|
1550
|
+
return (localNode.pathSegment === node.pathSegment &&
|
|
1551
|
+
localNode.entityType === node.entityType);
|
|
1552
|
+
}
|
|
1553
|
+
async getLocalConfigurations(localDevelopmentSettings) {
|
|
1554
|
+
const initialConfigurations = localDevelopmentSettings.configs
|
|
1555
|
+
.filter((config) => config.data)
|
|
1556
|
+
.map((config) => config.data);
|
|
1557
|
+
const configurations = (await Promise.allSettled(localDevelopmentSettings.configs
|
|
1558
|
+
.filter((config) => config.url)
|
|
1559
|
+
.map((config) => lastValueFrom(this.http.get(config.url)).then((contentConfiguration) => ({
|
|
1560
|
+
...contentConfiguration,
|
|
1561
|
+
url: config.url,
|
|
1562
|
+
})))))
|
|
1563
|
+
.filter((result) => result.status === 'fulfilled')
|
|
1564
|
+
.map((result) => result.value)
|
|
1565
|
+
.concat(initialConfigurations);
|
|
1566
|
+
return configurations;
|
|
1567
|
+
}
|
|
1568
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LocalConfigurationServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1569
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LocalConfigurationServiceImpl, providedIn: 'root' }); }
|
|
1570
|
+
}
|
|
1571
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LocalConfigurationServiceImpl, decorators: [{
|
|
1572
|
+
type: Injectable,
|
|
1573
|
+
args: [{
|
|
1574
|
+
providedIn: 'root',
|
|
1575
|
+
}]
|
|
1576
|
+
}] });
|
|
1577
|
+
|
|
1578
|
+
class LuigiNodesService {
|
|
1579
|
+
constructor() {
|
|
1580
|
+
this.i18nService = inject(I18nService);
|
|
1581
|
+
this.configService = inject(ConfigService);
|
|
1582
|
+
this.localConfigurationService = inject(LocalConfigurationServiceImpl);
|
|
1583
|
+
this.errorComponentConfig = inject(ERROR_COMPONENT_CONFIG, {
|
|
1584
|
+
optional: true,
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
getChildrenByEntity(allChildren) {
|
|
1588
|
+
const childrenByEntity = {
|
|
1589
|
+
home: [],
|
|
1590
|
+
};
|
|
1591
|
+
for (const child of allChildren) {
|
|
1592
|
+
// default to home to stay backward compatible
|
|
1593
|
+
const entityType = child.entityType || 'home';
|
|
1594
|
+
if (!childrenByEntity[entityType]) {
|
|
1595
|
+
childrenByEntity[entityType] = [];
|
|
1596
|
+
}
|
|
1597
|
+
childrenByEntity[entityType].push(child);
|
|
1598
|
+
}
|
|
1599
|
+
return childrenByEntity;
|
|
1600
|
+
}
|
|
1601
|
+
async retrieveChildrenByEntity() {
|
|
1602
|
+
try {
|
|
1603
|
+
const portalConfig = await this.configService.getPortalConfig();
|
|
1604
|
+
const serverLuigiNodes = portalConfig.providers.flatMap((p) => p.nodes);
|
|
1605
|
+
const luigiNodes = await this.localConfigurationService.replaceServerNodesWithLocalOnes(serverLuigiNodes, ['global', 'main', 'home']);
|
|
1606
|
+
return this.getChildrenByEntity(luigiNodes);
|
|
1607
|
+
}
|
|
1608
|
+
catch (e) {
|
|
1609
|
+
console.warn('Could not retrieve nodes, error: ', e);
|
|
1610
|
+
throw e;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
async retrieveEntityChildren(entityDefinition, additionalContext) {
|
|
1614
|
+
let errorCode = 0;
|
|
1615
|
+
let configsForEntity;
|
|
1616
|
+
const entityType = entityDefinition.dynamicFetchId;
|
|
1617
|
+
try {
|
|
1618
|
+
configsForEntity = await this.configService.getEntityConfig(entityType, additionalContext);
|
|
1619
|
+
}
|
|
1620
|
+
catch (e) {
|
|
1621
|
+
errorCode = e.status || 500;
|
|
1622
|
+
console.warn(`Could not retrieve nodes for entity: ${entityType}, error: `, e);
|
|
1623
|
+
}
|
|
1624
|
+
if (errorCode) {
|
|
1625
|
+
return this.createErrorNodes(entityDefinition, additionalContext, errorCode);
|
|
1626
|
+
}
|
|
1627
|
+
return configsForEntity.providers.flatMap((p) => p.nodes);
|
|
1628
|
+
}
|
|
1629
|
+
createErrorNodes(entityDefinition, additionalContext, errorCode) {
|
|
1630
|
+
return [
|
|
1631
|
+
{
|
|
1632
|
+
pathSegment: 'error',
|
|
1633
|
+
entityType: EntityType.ENTITY_ERROR,
|
|
1634
|
+
hideFromNav: true,
|
|
1635
|
+
hideSideNav: true,
|
|
1636
|
+
viewUrl: '/assets/openmfp-portal-ui-wc.js#error-component',
|
|
1637
|
+
context: {
|
|
1638
|
+
error: {
|
|
1639
|
+
code: errorCode,
|
|
1640
|
+
errorComponentConfig: this.errorComponentConfig,
|
|
1641
|
+
entityDefinition,
|
|
1642
|
+
additionalContext,
|
|
1643
|
+
},
|
|
1644
|
+
translationTable: this.i18nService.translationTable,
|
|
1645
|
+
},
|
|
1646
|
+
isolateView: true,
|
|
1647
|
+
showBreadcrumbs: false,
|
|
1648
|
+
webcomponent: {
|
|
1649
|
+
selfRegistered: true,
|
|
1650
|
+
},
|
|
1651
|
+
},
|
|
1652
|
+
];
|
|
1653
|
+
}
|
|
1654
|
+
nodePolicyResolver(nodeToCheckPermissionFor) {
|
|
1655
|
+
const mockPermissions = ['projectMember'];
|
|
1656
|
+
const permissions = nodeToCheckPermissionFor.requiredPolicies;
|
|
1657
|
+
return (!permissions ||
|
|
1658
|
+
permissions.every((item) => mockPermissions.includes(item)));
|
|
1659
|
+
}
|
|
1660
|
+
clearNodeCache() {
|
|
1661
|
+
this.configService.clearEntityConfigCache();
|
|
1662
|
+
}
|
|
1663
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiNodesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1664
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiNodesService, providedIn: 'root' }); }
|
|
1665
|
+
}
|
|
1666
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiNodesService, decorators: [{
|
|
1667
|
+
type: Injectable,
|
|
1668
|
+
args: [{
|
|
1669
|
+
providedIn: 'root',
|
|
1670
|
+
}]
|
|
1671
|
+
}] });
|
|
1672
|
+
|
|
1673
|
+
class RoutingConfigServiceImpl {
|
|
1674
|
+
constructor() {
|
|
1675
|
+
this.customRoutingConfigService = inject(LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
1676
|
+
}
|
|
1677
|
+
getInitialRoutingConfig() {
|
|
1678
|
+
return {
|
|
1679
|
+
useHashRouting: false,
|
|
1680
|
+
showModalPathInUrl: false,
|
|
1681
|
+
modalPathParam: 'modalPathParamDisabled',
|
|
1682
|
+
skipRoutingForUrlPatterns: [/.*/],
|
|
1683
|
+
pageNotFoundHandler: () => { },
|
|
1684
|
+
...(this.customRoutingConfigService?.getInitialRoutingConfig?.() || {}),
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
getRoutingConfig() {
|
|
1688
|
+
return {
|
|
1689
|
+
useHashRouting: false,
|
|
1690
|
+
showModalPathInUrl: true,
|
|
1691
|
+
modalPathParam: 'modal',
|
|
1692
|
+
pageNotFoundHandler: (notFoundPath, isAnyPathMatched) => {
|
|
1693
|
+
return {
|
|
1694
|
+
redirectTo: 'error/404',
|
|
1695
|
+
keepURL: true,
|
|
1696
|
+
};
|
|
1697
|
+
},
|
|
1698
|
+
...(this.customRoutingConfigService?.getRoutingConfig?.() || {}),
|
|
1699
|
+
};
|
|
1700
|
+
}
|
|
1701
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RoutingConfigServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1702
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RoutingConfigServiceImpl, providedIn: 'root' }); }
|
|
1703
|
+
}
|
|
1704
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RoutingConfigServiceImpl, decorators: [{
|
|
1705
|
+
type: Injectable,
|
|
1706
|
+
args: [{ providedIn: 'root' }]
|
|
1707
|
+
}] });
|
|
1708
|
+
|
|
1709
|
+
async function bootstrap(authService) {
|
|
1710
|
+
try {
|
|
1711
|
+
await authService.refresh();
|
|
1712
|
+
}
|
|
1713
|
+
catch (error) {
|
|
1714
|
+
console.error('Error bootstrapping the app:', error);
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
const provideBootstrap = () => provideAppInitializer(() => bootstrap(inject(AuthService)));
|
|
1718
|
+
|
|
1719
|
+
async function initializeAutomaticSessionRefresh(sessionRefreshService, authService, luigiCoreService) {
|
|
1720
|
+
authService.authEvents
|
|
1721
|
+
.pipe(filter((event) => event === AuthEvent.AUTH_EXPIRE_SOON), filter(() => luigiCoreService.isFeatureToggleActive('enableSessionAutoRefresh')))
|
|
1722
|
+
.subscribe({
|
|
1723
|
+
next: async () => {
|
|
1724
|
+
try {
|
|
1725
|
+
await sessionRefreshService.refresh();
|
|
1726
|
+
}
|
|
1727
|
+
catch (error) {
|
|
1728
|
+
console.error('Error executing session refresh: ', error);
|
|
1729
|
+
}
|
|
1730
|
+
},
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
const provideSessionRefresh = () => provideAppInitializer(() => initializeAutomaticSessionRefresh(inject(SessionRefreshService), inject(AuthService), inject(LuigiCoreService)));
|
|
1734
|
+
|
|
1735
|
+
class NavigationService {
|
|
1736
|
+
constructor(router, authService, loginEventService) {
|
|
1737
|
+
this.router = router;
|
|
1738
|
+
this.authService = authService;
|
|
1739
|
+
this.loginEventService = loginEventService;
|
|
1740
|
+
}
|
|
1741
|
+
track() {
|
|
1742
|
+
this.router.events
|
|
1743
|
+
.pipe(filter$1((event) => event instanceof NavigationEnd))
|
|
1744
|
+
.subscribe((event) => {
|
|
1745
|
+
this.currentUrl = event.url;
|
|
1746
|
+
});
|
|
1747
|
+
this.router.events
|
|
1748
|
+
.pipe(filter$1((event) => event instanceof NavigationStart))
|
|
1749
|
+
.subscribe((event) => {
|
|
1750
|
+
this.previousUrl = event.url;
|
|
1751
|
+
});
|
|
1752
|
+
this.authService.authEvents
|
|
1753
|
+
.pipe(filter$1((event) => event === AuthEvent.AUTH_EXPIRED))
|
|
1754
|
+
.subscribe({ next: () => this.saveCurrentUrl() });
|
|
1755
|
+
this.authService.authEvents
|
|
1756
|
+
.pipe(filter$1((event) => event === AuthEvent.LOGOUT))
|
|
1757
|
+
.subscribe({
|
|
1758
|
+
next: () => {
|
|
1759
|
+
this.saveLastNavigationUrl();
|
|
1760
|
+
},
|
|
1761
|
+
});
|
|
1762
|
+
this.loginEventService.loginEvents
|
|
1763
|
+
.pipe(filter$1((event) => event.type === LoginEventType.LOGIN_TRIGGERED))
|
|
1764
|
+
.subscribe({
|
|
1765
|
+
next: (event) => {
|
|
1766
|
+
this.router.navigate([this.getRedirectUrl()], {
|
|
1767
|
+
queryParams: event.queryParams,
|
|
1768
|
+
});
|
|
1769
|
+
this.clearCurrentUrl();
|
|
1770
|
+
},
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
clearCurrentUrl() {
|
|
1774
|
+
localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, '');
|
|
1775
|
+
}
|
|
1776
|
+
saveCurrentUrl() {
|
|
1777
|
+
localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, this.currentUrl);
|
|
1778
|
+
}
|
|
1779
|
+
saveLastNavigationUrl() {
|
|
1780
|
+
localStorage.setItem(LocalStorageKeys.LAST_NAVIGATION_URL, this.previousUrl);
|
|
1781
|
+
}
|
|
1782
|
+
getRedirectUrl() {
|
|
1783
|
+
return localStorage.getItem(LocalStorageKeys.LAST_NAVIGATION_URL) || '/';
|
|
1784
|
+
}
|
|
1785
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NavigationService, deps: [{ token: i1.Router }, { token: AuthService }, { token: LoginEventService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1786
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NavigationService, providedIn: 'root' }); }
|
|
1787
|
+
}
|
|
1788
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NavigationService, decorators: [{
|
|
1789
|
+
type: Injectable,
|
|
1790
|
+
args: [{
|
|
1791
|
+
providedIn: 'root',
|
|
1792
|
+
}]
|
|
1793
|
+
}], ctorParameters: () => [{ type: i1.Router }, { type: AuthService }, { type: LoginEventService }] });
|
|
1794
|
+
|
|
1795
|
+
async function track(navigationService) {
|
|
1796
|
+
navigationService.track();
|
|
1797
|
+
}
|
|
1798
|
+
const provideNavigationTracker = () => provideAppInitializer(() => {
|
|
1799
|
+
track(inject(NavigationService));
|
|
1800
|
+
});
|
|
1801
|
+
|
|
1802
|
+
async function initLanguage(i18nService, authService, luigiCoreService) {
|
|
1803
|
+
const userSettings = await userSettingsLocalStorage.read(authService.getUserInfo());
|
|
1804
|
+
const storedLanguage = userSettings?.frame_userAccount?.language;
|
|
1805
|
+
const validLanguages = (await i18nService.getValidLanguages()).map((l) => l.value);
|
|
1806
|
+
let language = i18nService.fallbackLanguage;
|
|
1807
|
+
if (storedLanguage && validLanguages.includes(storedLanguage)) {
|
|
1808
|
+
language = storedLanguage;
|
|
1809
|
+
}
|
|
1810
|
+
luigiCoreService.setCurrentLocale(language);
|
|
1811
|
+
await i18nService.fetchTranslationFile(language);
|
|
1812
|
+
}
|
|
1813
|
+
const provideLanguageServices = () => provideAppInitializer(() => initLanguage(inject(I18nService), inject(AuthService), inject(LuigiCoreService)));
|
|
1814
|
+
|
|
1815
|
+
class LogoutComponent {
|
|
1816
|
+
constructor(route, luigiCoreService, i18nService, loginEventService) {
|
|
1817
|
+
this.route = route;
|
|
1818
|
+
this.luigiCoreService = luigiCoreService;
|
|
1819
|
+
this.i18nService = i18nService;
|
|
1820
|
+
this.loginEventService = loginEventService;
|
|
1821
|
+
this.headline = signal('', ...(ngDevMode ? [{ debugName: "headline" }] : []));
|
|
1822
|
+
this.hint = signal('', ...(ngDevMode ? [{ debugName: "hint" }] : []));
|
|
1823
|
+
this.btnText = signal('', ...(ngDevMode ? [{ debugName: "btnText" }] : []));
|
|
1824
|
+
}
|
|
1825
|
+
async ngOnInit() {
|
|
1826
|
+
this.luigiCoreService.ux().hideAppLoadingIndicator();
|
|
1827
|
+
const error = this.route.snapshot.queryParams['error'];
|
|
1828
|
+
const translations = await this.getTranslations();
|
|
1829
|
+
this.headline.set(translations.headlineSuccessfullyLoggedOut);
|
|
1830
|
+
this.hint.set(translations.hintSignIn);
|
|
1831
|
+
this.btnText.set(translations.btnTextLoginAgain);
|
|
1832
|
+
switch (error) {
|
|
1833
|
+
case 'tokenExpired':
|
|
1834
|
+
this.headline.set(translations.headlineSessionExpired);
|
|
1835
|
+
break;
|
|
1836
|
+
case 'loginError':
|
|
1837
|
+
this.headline.set(translations.headlineSigInError);
|
|
1838
|
+
this.hint.set(translations.hintSignInError);
|
|
1839
|
+
break;
|
|
1840
|
+
case 'invalidToken':
|
|
1841
|
+
this.luigiCoreService.removeAuthData();
|
|
1842
|
+
this.headline.set(translations.headlineInvalidTokenError);
|
|
1843
|
+
this.hint.set(translations.hintInvalidTokenError);
|
|
1844
|
+
break;
|
|
1845
|
+
default:
|
|
1846
|
+
break;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
login() {
|
|
1850
|
+
this.loginEventService.loginEvent({ type: LoginEventType.LOGIN_TRIGGERED });
|
|
1851
|
+
}
|
|
1852
|
+
async getTranslations() {
|
|
1853
|
+
return {
|
|
1854
|
+
headlineSuccessfullyLoggedOut: await this.i18nService.getTranslationAsync('SUCCESSFULLY_LOGGED_OUT'),
|
|
1855
|
+
hintSignIn: await this.i18nService.getTranslationAsync('SIGN_IN_HINT'),
|
|
1856
|
+
btnTextLoginAgain: await this.i18nService.getTranslationAsync('LOGIN_AGAIN'),
|
|
1857
|
+
headlineSessionExpired: await this.i18nService.getTranslationAsync('SESSION_EXPIRED'),
|
|
1858
|
+
headlineSigInError: await this.i18nService.getTranslationAsync('SIGN_IN_ERROR'),
|
|
1859
|
+
hintSignInError: await this.i18nService.getTranslationAsync('SIGN_IN_ERROR_HINT'),
|
|
1860
|
+
headlineInvalidTokenError: await this.i18nService.getTranslationAsync('INVALID_TOKEN_ERROR'),
|
|
1861
|
+
hintInvalidTokenError: await this.i18nService.getTranslationAsync('INVALID_TOKEN_ERROR_HINT'),
|
|
1862
|
+
};
|
|
1863
|
+
}
|
|
1864
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LogoutComponent, deps: [{ token: i1.ActivatedRoute }, { token: LuigiCoreService }, { token: I18nService }, { token: LoginEventService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1865
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: LogoutComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<div class=\"fd-page\">\n <link rel=\"stylesheet\" href=\"/fundamental-styles/fundamental-styles.css\" />\n <div class=\"fd-page__content\">\n <div class=\"fd-container fd-container--centered\">\n <div class=\"content\">\n <span class=\"sap-icon--log\"></span>\n\n <div class=\"info\" data-e2e=\"logout-headline\">{{ headline() }}</div>\n <div class=\"hint\" data-e2e=\"logout-message\">{{ hint() }}</div>\n\n <p class=\"fd-has-text-align-center\">\n <button\n class=\"fd-button fd-button--action-bar fd-button--l\"\n (click)=\"login()\"\n >\n {{ btnText() }}\n </button>\n </p>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Light-full.woff) format(\"woff\");font-weight:300;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Light-full.woff2) format(\"woff2\");font-weight:300;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Bold-full.woff) format(\"woff\");font-weight:700;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Bold-full.woff2) format(\"woff2\");font-weight:700;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Regular-full.woff) format(\"woff\");font-weight:400;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Regular-full.woff2) format(\"woff2\");font-weight:400;font-style:normal}@font-face{font-family:SAP-icons;src:url(/fundamental-styles/SAP-icons.woff) format(\"woff\");font-weight:400;font-style:normal}@font-face{font-family:SAP-icons;src:url(/fundamental-styles/SAP-icons.woff2) format(\"woff2\");font-weight:400;font-style:normal}body{margin:0}.sap-icon--log:before{font-size:150px;color:#a0a0a0}.fd-container--centered{text-align:center}a.fd-button{color:#fff}.fd-page{margin-top:32px;height:100vh;overflow-y:auto;overflow-x:hidden}.content{width:100%}.fd-has-text-align-center{text-align:center}.info,.hint{text-align:center;margin:0}.info{padding-top:30px;font-size:36px}.hint{font-size:18px;color:#6f7275;padding-bottom:30px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1866
|
+
}
|
|
1867
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LogoutComponent, decorators: [{
|
|
1868
|
+
type: Component,
|
|
1869
|
+
args: [{ standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fd-page\">\n <link rel=\"stylesheet\" href=\"/fundamental-styles/fundamental-styles.css\" />\n <div class=\"fd-page__content\">\n <div class=\"fd-container fd-container--centered\">\n <div class=\"content\">\n <span class=\"sap-icon--log\"></span>\n\n <div class=\"info\" data-e2e=\"logout-headline\">{{ headline() }}</div>\n <div class=\"hint\" data-e2e=\"logout-message\">{{ hint() }}</div>\n\n <p class=\"fd-has-text-align-center\">\n <button\n class=\"fd-button fd-button--action-bar fd-button--l\"\n (click)=\"login()\"\n >\n {{ btnText() }}\n </button>\n </p>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Light-full.woff) format(\"woff\");font-weight:300;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Light-full.woff2) format(\"woff2\");font-weight:300;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Bold-full.woff) format(\"woff\");font-weight:700;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Bold-full.woff2) format(\"woff2\");font-weight:700;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Regular-full.woff) format(\"woff\");font-weight:400;font-style:normal}@font-face{font-family:\"72\";src:url(/fundamental-styles/72-Regular-full.woff2) format(\"woff2\");font-weight:400;font-style:normal}@font-face{font-family:SAP-icons;src:url(/fundamental-styles/SAP-icons.woff) format(\"woff\");font-weight:400;font-style:normal}@font-face{font-family:SAP-icons;src:url(/fundamental-styles/SAP-icons.woff2) format(\"woff2\");font-weight:400;font-style:normal}body{margin:0}.sap-icon--log:before{font-size:150px;color:#a0a0a0}.fd-container--centered{text-align:center}a.fd-button{color:#fff}.fd-page{margin-top:32px;height:100vh;overflow-y:auto;overflow-x:hidden}.content{width:100%}.fd-has-text-align-center{text-align:center}.info,.hint{text-align:center;margin:0}.info{padding-top:30px;font-size:36px}.hint{font-size:18px;color:#6f7275;padding-bottom:30px}\n"] }]
|
|
1870
|
+
}], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: LuigiCoreService }, { type: I18nService }, { type: LoginEventService }] });
|
|
1871
|
+
|
|
1872
|
+
class IntentNavigationService {
|
|
1873
|
+
constructor() { }
|
|
1874
|
+
/**
|
|
1875
|
+
* This function builds the Luigi based intent mapping configuration from the pre-built intent target knowledge
|
|
1876
|
+
* It iterates existing intentMappings and constructs pathSegment from the relative path of the defined entity and the target
|
|
1877
|
+
* that uses the entity as a reference
|
|
1878
|
+
*
|
|
1879
|
+
* @param nodes the nodes to fetch intentMapping initial configuration from
|
|
1880
|
+
* @returns a list of luigi intent objects
|
|
1881
|
+
*/
|
|
1882
|
+
buildIntentMappings(nodes) {
|
|
1883
|
+
let intentMappings = [];
|
|
1884
|
+
let entityRelativePaths = {};
|
|
1885
|
+
// find mapping on config from node[0] --> not 0 anymore need to traverse fully
|
|
1886
|
+
for (const item of nodes) {
|
|
1887
|
+
if (item._intentMappings) {
|
|
1888
|
+
intentMappings = [...intentMappings, ...item._intentMappings];
|
|
1889
|
+
}
|
|
1890
|
+
if (item._entityRelativePaths) {
|
|
1891
|
+
entityRelativePaths = {
|
|
1892
|
+
...entityRelativePaths,
|
|
1893
|
+
...item._entityRelativePaths,
|
|
1894
|
+
};
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
for (const intentElement of intentMappings) {
|
|
1898
|
+
if (entityRelativePaths && intentElement.baseEntityId) {
|
|
1899
|
+
let entityPath = '';
|
|
1900
|
+
intentElement.baseEntityId.split('.').forEach((entity) => {
|
|
1901
|
+
if (entityRelativePaths[entity] &&
|
|
1902
|
+
entityRelativePaths[entity].pathSegment) {
|
|
1903
|
+
entityPath += '/' + entityRelativePaths[entity].pathSegment;
|
|
1904
|
+
}
|
|
1905
|
+
});
|
|
1906
|
+
intentElement.pathSegment = this.removeDuplicateSlash(entityPath + '/' + intentElement.relativePath);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
return intentMappings;
|
|
1910
|
+
}
|
|
1911
|
+
/**
|
|
1912
|
+
* Removes duplicate slashes if exist
|
|
1913
|
+
*
|
|
1914
|
+
* @param url the url string to modify
|
|
1915
|
+
* @returns
|
|
1916
|
+
*/
|
|
1917
|
+
removeDuplicateSlash(url) {
|
|
1918
|
+
return url.replace(/\/+/g, '/');
|
|
1919
|
+
}
|
|
1920
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IntentNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1921
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IntentNavigationService, providedIn: 'root' }); }
|
|
1922
|
+
}
|
|
1923
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IntentNavigationService, decorators: [{
|
|
1924
|
+
type: Injectable,
|
|
1925
|
+
args: [{
|
|
1926
|
+
providedIn: 'root',
|
|
1927
|
+
}]
|
|
1928
|
+
}], ctorParameters: () => [] });
|
|
1929
|
+
|
|
1930
|
+
/**
|
|
1931
|
+
* Evaluates the JMESPath expression on the context and returns true if the result is true, otherwise false
|
|
1932
|
+
* @param context The context to evaluate
|
|
1933
|
+
* @param jmesPathExpression The JMESPath expression to evaluate
|
|
1934
|
+
* @returns true if the result of the JMESPath expression is true, otherwise (or if there was an exception while matching with JMESPath) false
|
|
1935
|
+
* */
|
|
1936
|
+
function matchesJMESPath(context, jmesPathExpression) {
|
|
1937
|
+
if (!jmesPathExpression) {
|
|
1938
|
+
return true;
|
|
1939
|
+
}
|
|
1940
|
+
try {
|
|
1941
|
+
return search(context, jmesPathExpression) === true;
|
|
1942
|
+
}
|
|
1943
|
+
catch (e) {
|
|
1944
|
+
logJMESException(context, jmesPathExpression, e);
|
|
1945
|
+
return false;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
function logJMESException(context, jmesPathExpression, error) {
|
|
1949
|
+
console.warn('Error while evaluating JMESPath expression.', 'Please check your visibleForContext or configurationMissing key in your Configuration.', '\n', '\n', 'Context:', '\n', context, '\n', '\n', 'JMESPath expression:', '\n', jmesPathExpression, '\n', '\n', 'Exception: ', '\n', error);
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
const visibleForContext = (ctx, node) => {
|
|
1953
|
+
// visibleForEntityContext is deprecated
|
|
1954
|
+
if (!isMatch(ctx.entityContext, node.visibleForEntityContext)) {
|
|
1955
|
+
return false;
|
|
1956
|
+
}
|
|
1957
|
+
return matchesJMESPath(ctx, node.visibleForContext);
|
|
1958
|
+
};
|
|
1959
|
+
const computeDynamicFetchContext = (entityNode, ctx) => {
|
|
1960
|
+
const contextForEntityConfig = new Map();
|
|
1961
|
+
function addToAll(key, value) {
|
|
1962
|
+
contextForEntityConfig.forEach((record) => {
|
|
1963
|
+
record[key] = value;
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
let node = entityNode;
|
|
1967
|
+
while (node) {
|
|
1968
|
+
if (node.defineEntity?.contextKey && node.defineEntity?.dynamicFetchId) {
|
|
1969
|
+
contextForEntityConfig.set(node.defineEntity.dynamicFetchId, {});
|
|
1970
|
+
addToAll(node.defineEntity.dynamicFetchId, ctx[node.defineEntity.contextKey]);
|
|
1971
|
+
}
|
|
1972
|
+
node = node.parent;
|
|
1973
|
+
}
|
|
1974
|
+
addToAll('user', ctx.userId || ctx.userid);
|
|
1975
|
+
return contextForEntityConfig;
|
|
1976
|
+
};
|
|
1977
|
+
|
|
1978
|
+
class NodeSortingService {
|
|
1979
|
+
constructor() { }
|
|
1980
|
+
markEntityRootChildren(nodes) {
|
|
1981
|
+
nodes.forEach((child) => {
|
|
1982
|
+
child._entityRootChild = true;
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
nodeComparison(a, b) {
|
|
1986
|
+
// set default order to the end if not defined
|
|
1987
|
+
a.order = a.dxpOrder || a.order || '999';
|
|
1988
|
+
b.order = b.dxpOrder || b.order || '999';
|
|
1989
|
+
const orderA = isNaN(parseFloat(a?.order)) ? 999 : parseFloat(a.order);
|
|
1990
|
+
const orderB = isNaN(parseFloat(b?.order)) ? 999 : parseFloat(b.order);
|
|
1991
|
+
if (orderA < orderB) {
|
|
1992
|
+
return -1;
|
|
1993
|
+
}
|
|
1994
|
+
else if (orderA > orderB) {
|
|
1995
|
+
return 1;
|
|
1996
|
+
}
|
|
1997
|
+
// if orders are equal -> sort alphabetically by label
|
|
1998
|
+
if (!a.label && !b.label) {
|
|
1999
|
+
return 0; // both undefined, keep original order
|
|
2000
|
+
}
|
|
2001
|
+
else if (!a.label) {
|
|
2002
|
+
return 1; // a has no label, goes after b
|
|
2003
|
+
}
|
|
2004
|
+
else if (!b.label) {
|
|
2005
|
+
return -1; // b has no label, a goes before b
|
|
2006
|
+
}
|
|
2007
|
+
return a.label.localeCompare(b.label);
|
|
2008
|
+
}
|
|
2009
|
+
appendChildrenToSlot(nodes, slotNode, children) {
|
|
2010
|
+
const slotIndex = nodes.indexOf(slotNode);
|
|
2011
|
+
if (slotNode.category) {
|
|
2012
|
+
const cat = slotNode.category.id ||
|
|
2013
|
+
slotNode.category.label ||
|
|
2014
|
+
(slotNode.category.length > 0
|
|
2015
|
+
? slotNode.category
|
|
2016
|
+
: undefined);
|
|
2017
|
+
if (cat) {
|
|
2018
|
+
children.forEach((node) => {
|
|
2019
|
+
node.category = cat;
|
|
2020
|
+
});
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
nodes.splice(slotIndex + 1, 0, ...children);
|
|
2024
|
+
}
|
|
2025
|
+
sortNodes(nodes) {
|
|
2026
|
+
const entityRootNodes = [];
|
|
2027
|
+
const slottedChildrenMap = {};
|
|
2028
|
+
const otherChildren = [];
|
|
2029
|
+
const slotNodes = [];
|
|
2030
|
+
let defaultSlot;
|
|
2031
|
+
nodes.forEach((node) => {
|
|
2032
|
+
if (node._entityRootChild) {
|
|
2033
|
+
entityRootNodes.push(node);
|
|
2034
|
+
if (node.defineSlot) {
|
|
2035
|
+
slotNodes.push(node);
|
|
2036
|
+
}
|
|
2037
|
+
else if (node.defineSlot === '') {
|
|
2038
|
+
defaultSlot = node;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
else if (node.navSlot) {
|
|
2042
|
+
if (!slottedChildrenMap[node.navSlot]) {
|
|
2043
|
+
slottedChildrenMap[node.navSlot] = [];
|
|
2044
|
+
}
|
|
2045
|
+
slottedChildrenMap[node.navSlot].push(node);
|
|
2046
|
+
}
|
|
2047
|
+
else {
|
|
2048
|
+
otherChildren.push(node);
|
|
2049
|
+
}
|
|
2050
|
+
});
|
|
2051
|
+
const sortedNodes = [...entityRootNodes];
|
|
2052
|
+
const sortedOther = otherChildren.sort(this.nodeComparison);
|
|
2053
|
+
if (slotNodes.length > 0) {
|
|
2054
|
+
slotNodes.forEach((slotNode) => {
|
|
2055
|
+
if (slottedChildrenMap[slotNode.defineSlot]) {
|
|
2056
|
+
this.appendChildrenToSlot(sortedNodes, slotNode, slottedChildrenMap[slotNode.defineSlot].sort(this.nodeComparison));
|
|
2057
|
+
delete slottedChildrenMap[slotNode.defineSlot];
|
|
2058
|
+
}
|
|
2059
|
+
});
|
|
2060
|
+
}
|
|
2061
|
+
// collect unassigned slotted nodes and add to default slot
|
|
2062
|
+
for (const slotId in slottedChildrenMap) {
|
|
2063
|
+
if (Object.prototype.hasOwnProperty.call(slottedChildrenMap, slotId)) {
|
|
2064
|
+
const unassignedSlotChildren = slottedChildrenMap[slotId];
|
|
2065
|
+
sortedOther.push(...unassignedSlotChildren.sort(this.nodeComparison));
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
if (defaultSlot) {
|
|
2069
|
+
this.appendChildrenToSlot(sortedNodes, defaultSlot, sortedOther);
|
|
2070
|
+
}
|
|
2071
|
+
else {
|
|
2072
|
+
sortedNodes.push(...sortedOther);
|
|
2073
|
+
}
|
|
2074
|
+
// move nodes without categories to top
|
|
2075
|
+
const singleNodes = [];
|
|
2076
|
+
const catNodes = [];
|
|
2077
|
+
sortedNodes.forEach((node) => {
|
|
2078
|
+
(node.category ? catNodes : singleNodes).push(node);
|
|
2079
|
+
});
|
|
2080
|
+
return [...singleNodes, ...catNodes];
|
|
2081
|
+
}
|
|
2082
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodeSortingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2083
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodeSortingService, providedIn: 'root' }); }
|
|
2084
|
+
}
|
|
2085
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodeSortingService, decorators: [{
|
|
2086
|
+
type: Injectable,
|
|
2087
|
+
args: [{
|
|
2088
|
+
providedIn: 'root',
|
|
2089
|
+
}]
|
|
2090
|
+
}], ctorParameters: () => [] });
|
|
2091
|
+
|
|
2092
|
+
class ChildrenNodesService {
|
|
2093
|
+
constructor() {
|
|
2094
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
2095
|
+
this.configService = inject(ConfigService);
|
|
2096
|
+
this.nodeUtilsService = inject(NodeUtilsService);
|
|
2097
|
+
this.nodeSortingService = inject(NodeSortingService);
|
|
2098
|
+
this.customNodeProcessingService = inject(LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
2099
|
+
}
|
|
2100
|
+
async processChildrenForEntity(entityNode, childrenNodes, ctx) {
|
|
2101
|
+
if (entityNode.defineEntity?.useBack &&
|
|
2102
|
+
this.luigiCoreService.isFeatureToggleActive('navheader-up') &&
|
|
2103
|
+
entityNode.navHeader) {
|
|
2104
|
+
entityNode.navHeader.showUpLink = true;
|
|
2105
|
+
}
|
|
2106
|
+
this.addNavigationHeader(entityNode);
|
|
2107
|
+
if (!childrenNodes) {
|
|
2108
|
+
return [];
|
|
2109
|
+
}
|
|
2110
|
+
const entityContext = {};
|
|
2111
|
+
const fetchContext = computeDynamicFetchContext(entityNode, ctx);
|
|
2112
|
+
await Promise.all(Array.from(fetchContext.entries()).map(async ([dynamicFetchId, context]) => {
|
|
2113
|
+
try {
|
|
2114
|
+
entityContext[dynamicFetchId] = (await this.configService.getEntityConfig(dynamicFetchId, context)).entityContext;
|
|
2115
|
+
}
|
|
2116
|
+
catch (error) {
|
|
2117
|
+
console.error(entityNode.defineEntity.id, 'does not exist', context);
|
|
2118
|
+
}
|
|
2119
|
+
}));
|
|
2120
|
+
childrenNodes.forEach((child) => {
|
|
2121
|
+
child.context = { ...child.context, entityContext };
|
|
2122
|
+
child.onNodeActivation =
|
|
2123
|
+
this.nodeUtilsService.retrieveGlobalHelpContext();
|
|
2124
|
+
});
|
|
2125
|
+
const nodes = await Promise.all(childrenNodes
|
|
2126
|
+
.filter((child) => visibleForContext(child.context, child))
|
|
2127
|
+
.map((child) => this.customNodeProcessingService?.processNode(child.context, child) || child));
|
|
2128
|
+
return this.nodeSortingService.sortNodes(nodes);
|
|
2129
|
+
}
|
|
2130
|
+
addNavigationHeader(entityNode) {
|
|
2131
|
+
if (entityNode.defineEntity) {
|
|
2132
|
+
if (!entityNode.navHeader) {
|
|
2133
|
+
entityNode.navHeader = {};
|
|
2134
|
+
}
|
|
2135
|
+
entityNode.navHeader.renderer = (containerElement, nodeItem, clickHandler, navHeader) => {
|
|
2136
|
+
if (!containerElement || !navHeader?.label) {
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2139
|
+
const label = this.sanitizeString(navHeader.label);
|
|
2140
|
+
const type = this.getSideNavigationHeaderType(navHeader.context, nodeItem);
|
|
2141
|
+
containerElement.classList.add('entity-nav-header');
|
|
2142
|
+
containerElement.innerHTML = `
|
|
2143
|
+
<ui5-text class="entity-nav-header-type">${type}</ui5-text>
|
|
2144
|
+
<ui5-title class="entity-nav-header-label" level="H6" size="H6">${label}</ui5-title>
|
|
2145
|
+
`;
|
|
2146
|
+
};
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
getSideNavigationHeaderType(nodeContext = {}, nodeItem) {
|
|
2150
|
+
const dynamicFetchId = nodeItem.defineEntity?.dynamicFetchId || '';
|
|
2151
|
+
let type = (nodeContext.entityContext?.[dynamicFetchId] || {}).type;
|
|
2152
|
+
if (!type || typeof type !== 'string') {
|
|
2153
|
+
type = nodeItem.defineEntity?.label || dynamicFetchId || 'Extension';
|
|
2154
|
+
}
|
|
2155
|
+
type = type.replace(/Id/i, '');
|
|
2156
|
+
return type.at(0).toUpperCase() + type.slice(1);
|
|
2157
|
+
}
|
|
2158
|
+
sanitizeString(inputString) {
|
|
2159
|
+
// Prevent XSS attacks by removing any tags
|
|
2160
|
+
const tempSpan = document.createElement('span');
|
|
2161
|
+
tempSpan.textContent = inputString;
|
|
2162
|
+
return tempSpan.innerHTML;
|
|
2163
|
+
}
|
|
2164
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ChildrenNodesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2165
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ChildrenNodesService, providedIn: 'root' }); }
|
|
2166
|
+
}
|
|
2167
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ChildrenNodesService, decorators: [{
|
|
2168
|
+
type: Injectable,
|
|
2169
|
+
args: [{ providedIn: 'root' }]
|
|
2170
|
+
}] });
|
|
2171
|
+
|
|
2172
|
+
class CommonGlobalLuigiNodesService {
|
|
2173
|
+
constructor() {
|
|
2174
|
+
this.i18nService = inject(I18nService);
|
|
2175
|
+
this.errorComponentConfig = inject(ERROR_COMPONENT_CONFIG, {
|
|
2176
|
+
optional: true,
|
|
2177
|
+
});
|
|
2178
|
+
}
|
|
2179
|
+
getContentNotFoundGlobalNode() {
|
|
2180
|
+
return [
|
|
2181
|
+
{
|
|
2182
|
+
pathSegment: 'error',
|
|
2183
|
+
label: 'Content not found',
|
|
2184
|
+
order: '1000',
|
|
2185
|
+
hideFromNav: true,
|
|
2186
|
+
children: [
|
|
2187
|
+
{
|
|
2188
|
+
pathSegment: ':id',
|
|
2189
|
+
entityType: EntityType.ENTITY_ERROR,
|
|
2190
|
+
hideFromNav: true,
|
|
2191
|
+
hideSideNav: true,
|
|
2192
|
+
viewUrl: '/assets/openmfp-portal-ui-wc.js#error-component',
|
|
2193
|
+
context: {
|
|
2194
|
+
error: {
|
|
2195
|
+
code: 404,
|
|
2196
|
+
errorComponentConfig: this.errorComponentConfig,
|
|
2197
|
+
},
|
|
2198
|
+
translationTable: this.i18nService.translationTable,
|
|
2199
|
+
},
|
|
2200
|
+
webcomponent: {
|
|
2201
|
+
selfRegistered: true,
|
|
2202
|
+
},
|
|
2203
|
+
},
|
|
2204
|
+
],
|
|
2205
|
+
},
|
|
2206
|
+
];
|
|
2207
|
+
}
|
|
2208
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CommonGlobalLuigiNodesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2209
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CommonGlobalLuigiNodesService, providedIn: 'root' }); }
|
|
2210
|
+
}
|
|
2211
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CommonGlobalLuigiNodesService, decorators: [{
|
|
2212
|
+
type: Injectable,
|
|
2213
|
+
args: [{ providedIn: 'root' }]
|
|
2214
|
+
}] });
|
|
2215
|
+
|
|
2216
|
+
class NodesProcessingService {
|
|
2217
|
+
constructor() {
|
|
2218
|
+
this.nodeContextProcessingService = inject(LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
2219
|
+
this.luigiNodesService = inject(LuigiNodesService);
|
|
2220
|
+
this.localConfigurationService = inject(LocalConfigurationServiceImpl);
|
|
2221
|
+
this.nodeSortingService = inject(NodeSortingService);
|
|
2222
|
+
this.childrenNodesService = inject(ChildrenNodesService);
|
|
2223
|
+
this.commonGlobalLuigiNodesService = inject(CommonGlobalLuigiNodesService);
|
|
2224
|
+
this.customNodeProcessingService = inject(LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
2225
|
+
this.customGlobalNodesService = inject(LUIGI_NODES_CUSTOM_GLOBAL_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
2226
|
+
}
|
|
2227
|
+
async processNodes(childrenByEntity) {
|
|
2228
|
+
const globalNodes = [
|
|
2229
|
+
...(childrenByEntity[EntityType.GLOBAL] || []),
|
|
2230
|
+
...(childrenByEntity[EntityType.GLOBAL_TOPNAV] || []),
|
|
2231
|
+
...((await this.customGlobalNodesService?.getCustomGlobalNodes()) || []),
|
|
2232
|
+
...this.commonGlobalLuigiNodesService.getContentNotFoundGlobalNode(),
|
|
2233
|
+
];
|
|
2234
|
+
globalNodes.forEach((node) => {
|
|
2235
|
+
node.context = { ...node.context };
|
|
2236
|
+
node.globalNav = this.isGlobalNavNode(node);
|
|
2237
|
+
this.applyEntityChildrenRecursively(node, childrenByEntity, '');
|
|
2238
|
+
});
|
|
2239
|
+
globalNodes.sort(this.nodeSortingService.nodeComparison);
|
|
2240
|
+
return globalNodes;
|
|
2241
|
+
}
|
|
2242
|
+
isGlobalNavNode(node) {
|
|
2243
|
+
return !node.hideFromNav && node.entityType === EntityType.GLOBAL;
|
|
2244
|
+
}
|
|
2245
|
+
applyEntityChildrenRecursively(node, childrenByEntity, parentEntityPath) {
|
|
2246
|
+
if (Array.isArray(node.children)) {
|
|
2247
|
+
this.nodeSortingService.markEntityRootChildren(node.children);
|
|
2248
|
+
node._portalDirectChildren = node.children;
|
|
2249
|
+
}
|
|
2250
|
+
const directChildren = node._portalDirectChildren || [];
|
|
2251
|
+
if (node.defineEntity) {
|
|
2252
|
+
this.processNodeDefineEntity(node, childrenByEntity, parentEntityPath, directChildren);
|
|
2253
|
+
}
|
|
2254
|
+
else {
|
|
2255
|
+
directChildren.forEach((child) => {
|
|
2256
|
+
this.applyEntityChildrenRecursively(child, childrenByEntity, parentEntityPath);
|
|
2257
|
+
});
|
|
2258
|
+
node.children = async (ctx) => await Promise.all(directChildren
|
|
2259
|
+
.filter((child) => visibleForContext(ctx, child))
|
|
2260
|
+
.map((child) => this.customNodeProcessingService?.processNode(ctx, child) ||
|
|
2261
|
+
child));
|
|
2262
|
+
}
|
|
2263
|
+
if (node.virtualTree) {
|
|
2264
|
+
node.children = undefined;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
processNodeDefineEntity(node, childrenByEntity, parentEntityPath, directChildren) {
|
|
2268
|
+
let newEntityPath = parentEntityPath;
|
|
2269
|
+
if (parentEntityPath?.length > 0) {
|
|
2270
|
+
newEntityPath = parentEntityPath + '.' + node.defineEntity.id;
|
|
2271
|
+
}
|
|
2272
|
+
else {
|
|
2273
|
+
newEntityPath = node.defineEntity.id;
|
|
2274
|
+
}
|
|
2275
|
+
node.children = (ctx) => {
|
|
2276
|
+
return this.entityChildrenProvider(node, ctx, childrenByEntity, directChildren, newEntityPath);
|
|
2277
|
+
};
|
|
2278
|
+
this.processCompoundNode(node, childrenByEntity, newEntityPath);
|
|
2279
|
+
}
|
|
2280
|
+
processCompoundNode(node, childrenByEntity, newEntityPath) {
|
|
2281
|
+
if (node.compound) {
|
|
2282
|
+
if (!node.compound._staticChildren) {
|
|
2283
|
+
node.compound._staticChildren = node.compound.children || [];
|
|
2284
|
+
}
|
|
2285
|
+
const additionalChildren = childrenByEntity[newEntityPath + '::compound'] || [];
|
|
2286
|
+
let children = [
|
|
2287
|
+
...node.compound._staticChildren,
|
|
2288
|
+
...additionalChildren,
|
|
2289
|
+
].sort(this.nodeSortingService.nodeComparison);
|
|
2290
|
+
Object.defineProperty(node.compound, 'children', {
|
|
2291
|
+
set: (newValue) => (children = newValue),
|
|
2292
|
+
get: () => {
|
|
2293
|
+
children.forEach((child) => {
|
|
2294
|
+
child.context.entityContext = {
|
|
2295
|
+
...child.context.entityContext,
|
|
2296
|
+
...node.context?.entityContext,
|
|
2297
|
+
};
|
|
2298
|
+
});
|
|
2299
|
+
return children.filter((child) => visibleForContext(child.context, child));
|
|
2300
|
+
},
|
|
2301
|
+
configurable: true,
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
entityChildrenProvider(entityNode, ctx, childrenByEntity, directChildren, entityPath) {
|
|
2306
|
+
return new Promise(async (resolve, reject) => {
|
|
2307
|
+
const entityTypeId = entityPath || entityNode?.defineEntity?.id;
|
|
2308
|
+
const entityId = ctx[entityNode?.defineEntity?.contextKey];
|
|
2309
|
+
const staticChildren = [
|
|
2310
|
+
...(directChildren || []),
|
|
2311
|
+
...(childrenByEntity[entityTypeId] || []),
|
|
2312
|
+
];
|
|
2313
|
+
await this.nodeContextProcessingService?.processNodeContext(entityId, entityNode, ctx);
|
|
2314
|
+
if (!entityTypeId || !entityNode.defineEntity?.dynamicFetchId) {
|
|
2315
|
+
const serverAndLocalNodes = await this.localConfigurationService.replaceServerNodesWithLocalOnes(staticChildren, [entityPath]);
|
|
2316
|
+
const childrenList = await this.createChildrenList(entityNode, ctx, childrenByEntity, entityPath, serverAndLocalNodes);
|
|
2317
|
+
resolve(childrenList);
|
|
2318
|
+
return;
|
|
2319
|
+
}
|
|
2320
|
+
let dynamicRetrievedChildren, staticRetrievedChildren;
|
|
2321
|
+
try {
|
|
2322
|
+
const fetchContext = computeDynamicFetchContext(entityNode, ctx);
|
|
2323
|
+
const dynamicFetchId = entityNode.defineEntity.dynamicFetchId;
|
|
2324
|
+
dynamicRetrievedChildren =
|
|
2325
|
+
await this.luigiNodesService.retrieveEntityChildren(entityNode.defineEntity, fetchContext.get(dynamicFetchId));
|
|
2326
|
+
const serverAndLocalNodes = await this.localConfigurationService.replaceServerNodesWithLocalOnes(dynamicRetrievedChildren, [entityPath]);
|
|
2327
|
+
dynamicRetrievedChildren = [...staticChildren, ...serverAndLocalNodes];
|
|
2328
|
+
staticRetrievedChildren = staticChildren;
|
|
2329
|
+
}
|
|
2330
|
+
catch (error) {
|
|
2331
|
+
dynamicRetrievedChildren = staticChildren;
|
|
2332
|
+
staticRetrievedChildren = null;
|
|
2333
|
+
}
|
|
2334
|
+
const childrenList = await this.createChildrenList(entityNode, ctx, childrenByEntity, entityPath, dynamicRetrievedChildren, staticRetrievedChildren);
|
|
2335
|
+
resolve(childrenList);
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
createChildrenList(entityNode, ctx, childrenByEntity, entityPath, children, staticChildren) {
|
|
2339
|
+
const entityRootChildren = staticChildren ? [] : children;
|
|
2340
|
+
let mergedChildrenByEntity = childrenByEntity;
|
|
2341
|
+
if (staticChildren) {
|
|
2342
|
+
const entityChildrenByEntity = {};
|
|
2343
|
+
children?.forEach((child) => {
|
|
2344
|
+
if (child.entityType === entityPath ||
|
|
2345
|
+
child.entityType === EntityType.ENTITY_ERROR ||
|
|
2346
|
+
staticChildren.includes(child)) {
|
|
2347
|
+
entityRootChildren.push(child);
|
|
2348
|
+
}
|
|
2349
|
+
else if (child.entityType) {
|
|
2350
|
+
if (!entityChildrenByEntity[child.entityType]) {
|
|
2351
|
+
entityChildrenByEntity[child.entityType] = [];
|
|
2352
|
+
}
|
|
2353
|
+
entityChildrenByEntity[child.entityType].push(child);
|
|
2354
|
+
}
|
|
2355
|
+
else {
|
|
2356
|
+
console.warn('Ignored entity child, no entity type defined', child);
|
|
2357
|
+
}
|
|
2358
|
+
});
|
|
2359
|
+
mergedChildrenByEntity = { ...childrenByEntity };
|
|
2360
|
+
Object.keys(entityChildrenByEntity).forEach((key) => {
|
|
2361
|
+
const existingNodes = mergedChildrenByEntity[key];
|
|
2362
|
+
mergedChildrenByEntity[key] = existingNodes
|
|
2363
|
+
? [...existingNodes, ...entityChildrenByEntity[key]]
|
|
2364
|
+
: entityChildrenByEntity[key];
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
entityRootChildren.forEach((child) => {
|
|
2368
|
+
this.applyEntityChildrenRecursively(child, mergedChildrenByEntity, entityPath);
|
|
2369
|
+
});
|
|
2370
|
+
return this.childrenNodesService.processChildrenForEntity(entityNode, entityRootChildren, ctx);
|
|
2371
|
+
}
|
|
2372
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodesProcessingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2373
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodesProcessingService, providedIn: 'root' }); }
|
|
2374
|
+
}
|
|
2375
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NodesProcessingService, decorators: [{
|
|
2376
|
+
type: Injectable,
|
|
2377
|
+
args: [{ providedIn: 'root' }]
|
|
2378
|
+
}] });
|
|
2379
|
+
|
|
2380
|
+
class NavigationConfigService {
|
|
2381
|
+
constructor(configService, luigiCoreService, luigiNodesService, intentNavigationService, navigationGlobalContextConfigService, userProfileConfigService, appSwitcherConfigService, nodeChangeHookConfigService, nodesProcessingService, headerBarService) {
|
|
2382
|
+
this.configService = configService;
|
|
2383
|
+
this.luigiCoreService = luigiCoreService;
|
|
2384
|
+
this.luigiNodesService = luigiNodesService;
|
|
2385
|
+
this.intentNavigationService = intentNavigationService;
|
|
2386
|
+
this.navigationGlobalContextConfigService = navigationGlobalContextConfigService;
|
|
2387
|
+
this.userProfileConfigService = userProfileConfigService;
|
|
2388
|
+
this.appSwitcherConfigService = appSwitcherConfigService;
|
|
2389
|
+
this.nodeChangeHookConfigService = nodeChangeHookConfigService;
|
|
2390
|
+
this.nodesProcessingService = nodesProcessingService;
|
|
2391
|
+
this.headerBarService = headerBarService;
|
|
2392
|
+
}
|
|
2393
|
+
async getNavigationConfig(childrenByEntity, envConfig) {
|
|
2394
|
+
const allNodes = Object.values(childrenByEntity).reduce((accumulator, value) => accumulator.concat(value), []);
|
|
2395
|
+
const portalConfig = await this.configService.getPortalConfig();
|
|
2396
|
+
this.initFeatureToggles(portalConfig.featureToggles, envConfig);
|
|
2397
|
+
const context = await this.navigationGlobalContextConfigService.getGlobalContext();
|
|
2398
|
+
const luigiNodes = await this.nodesProcessingService.processNodes(childrenByEntity);
|
|
2399
|
+
return {
|
|
2400
|
+
nodes: luigiNodes,
|
|
2401
|
+
viewGroupSettings: this.buildViewGroups(allNodes),
|
|
2402
|
+
appSwitcher: this.appSwitcherConfigService?.getAppSwitcher(luigiNodes),
|
|
2403
|
+
globalContext: context,
|
|
2404
|
+
profile: await this.userProfileConfigService?.getProfile(),
|
|
2405
|
+
addNavHrefs: true,
|
|
2406
|
+
contextSwitcher: undefined,
|
|
2407
|
+
nodeAccessibilityResolver: this.luigiNodesService.nodePolicyResolver,
|
|
2408
|
+
validWebcomponentUrls: envConfig.validWebcomponentUrls,
|
|
2409
|
+
intentMapping: this.intentNavigationService.buildIntentMappings(allNodes),
|
|
2410
|
+
nodeChangeHook: function (prevNode, nextNode) {
|
|
2411
|
+
this.nodeChangeHookConfigService?.nodeChangeHook(prevNode, nextNode);
|
|
2412
|
+
}.bind(this),
|
|
2413
|
+
breadcrumbs: await this.headerBarService.getConfig(),
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
initFeatureToggles(configFeatureToggles, envConfig) {
|
|
2417
|
+
if (envConfig.uiOptions.includes('enableFeatureToggleSetting')) {
|
|
2418
|
+
const featureToggleSettings = featureToggleLocalStorage.read();
|
|
2419
|
+
this.luigiCoreService.setFeatureToggles({
|
|
2420
|
+
...configFeatureToggles,
|
|
2421
|
+
...featureToggleSettings,
|
|
2422
|
+
});
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2425
|
+
this.luigiCoreService.setFeatureToggles(configFeatureToggles);
|
|
2426
|
+
}
|
|
2427
|
+
buildViewGroups(nodes) {
|
|
2428
|
+
const viewGroups = {};
|
|
2429
|
+
nodes.forEach((node) => {
|
|
2430
|
+
if (node.viewGroup && node._preloadUrl) {
|
|
2431
|
+
viewGroups[node.viewGroup] = {
|
|
2432
|
+
preloadUrl: node._preloadUrl,
|
|
2433
|
+
requiredIFramePermissions: node._requiredIFramePermissionsForViewGroup,
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
});
|
|
2437
|
+
return viewGroups;
|
|
2438
|
+
}
|
|
2439
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NavigationConfigService, deps: [{ token: ConfigService }, { token: LuigiCoreService }, { token: LuigiNodesService }, { token: IntentNavigationService }, { token: GlobalContextConfigService }, { token: LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN, optional: true }, { token: LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN, optional: true }, { token: LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN, optional: true }, { token: NodesProcessingService }, { token: HeaderBarService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2440
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NavigationConfigService, providedIn: 'root' }); }
|
|
2441
|
+
}
|
|
2442
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NavigationConfigService, decorators: [{
|
|
2443
|
+
type: Injectable,
|
|
2444
|
+
args: [{ providedIn: 'root' }]
|
|
2445
|
+
}], ctorParameters: () => [{ type: ConfigService }, { type: LuigiCoreService }, { type: LuigiNodesService }, { type: IntentNavigationService }, { type: GlobalContextConfigService }, { type: undefined, decorators: [{
|
|
2446
|
+
type: Optional
|
|
2447
|
+
}, {
|
|
2448
|
+
type: Inject,
|
|
2449
|
+
args: [LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN]
|
|
2450
|
+
}] }, { type: undefined, decorators: [{
|
|
2451
|
+
type: Optional
|
|
2452
|
+
}, {
|
|
2453
|
+
type: Inject,
|
|
2454
|
+
args: [LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN]
|
|
2455
|
+
}] }, { type: undefined, decorators: [{
|
|
2456
|
+
type: Optional
|
|
2457
|
+
}, {
|
|
2458
|
+
type: Inject,
|
|
2459
|
+
args: [LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN]
|
|
2460
|
+
}] }, { type: NodesProcessingService }, { type: HeaderBarService }] });
|
|
2461
|
+
|
|
2462
|
+
class LifecycleHooksConfigService {
|
|
2463
|
+
constructor() {
|
|
2464
|
+
this.authConfigService = inject(AuthConfigService);
|
|
2465
|
+
this.customMessageListenersService = inject(CustomMessageListenersService);
|
|
2466
|
+
this.envConfigService = inject(EnvConfigService);
|
|
2467
|
+
this.i18nService = inject(I18nService);
|
|
2468
|
+
this.luigiNodesService = inject(LuigiNodesService);
|
|
2469
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
2470
|
+
this.routingConfigService = inject(RoutingConfigServiceImpl);
|
|
2471
|
+
this.navigationConfigService = inject(NavigationConfigService);
|
|
2472
|
+
this.userSettingsConfigService = inject(UserSettingsConfigService);
|
|
2473
|
+
this.staticSettingsConfigService = inject(StaticSettingsConfigServiceImpl);
|
|
2474
|
+
this.globalSearchConfigService = inject(LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN, { optional: true });
|
|
2475
|
+
}
|
|
2476
|
+
getLifecycleHooksConfig() {
|
|
2477
|
+
return {
|
|
2478
|
+
luigiAfterInit: async () => {
|
|
2479
|
+
await this.constructLuigiConfiguration();
|
|
2480
|
+
},
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
async constructLuigiConfiguration() {
|
|
2484
|
+
this.i18nService.afterInit();
|
|
2485
|
+
const envConfig = await this.envConfigService.getEnvConfig();
|
|
2486
|
+
let childrenByEntity;
|
|
2487
|
+
try {
|
|
2488
|
+
childrenByEntity =
|
|
2489
|
+
await this.luigiNodesService.retrieveChildrenByEntity();
|
|
2490
|
+
}
|
|
2491
|
+
catch (e) {
|
|
2492
|
+
console.error('Error retrieving Luigi navigation nodes', e);
|
|
2493
|
+
this.openErrorDialog();
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
const config = {
|
|
2497
|
+
auth: await this.authConfigService.getAuthConfig(),
|
|
2498
|
+
settings: await this.staticSettingsConfigService.getStaticSettingsConfig(),
|
|
2499
|
+
communication: this.customMessageListenersService.getMessageListeners(),
|
|
2500
|
+
navigation: await this.navigationConfigService.getNavigationConfig(childrenByEntity, envConfig),
|
|
2501
|
+
routing: this.routingConfigService.getRoutingConfig(),
|
|
2502
|
+
userSettings: await this.userSettingsConfigService.getUserSettings(childrenByEntity),
|
|
2503
|
+
globalSearch: this.globalSearchConfigService?.getGlobalSearchConfig(),
|
|
2504
|
+
};
|
|
2505
|
+
this.luigiCoreService.setConfig(config);
|
|
2506
|
+
this.luigiCoreService.ux().hideAppLoadingIndicator();
|
|
2507
|
+
}
|
|
2508
|
+
openErrorDialog() {
|
|
2509
|
+
const appTitle = this.luigiCoreService.config.settings.header.title;
|
|
2510
|
+
this.luigiCoreService.showAlert({
|
|
2511
|
+
text: $localize `There was an error loading the ${appTitle}`,
|
|
2512
|
+
type: 'error',
|
|
2513
|
+
});
|
|
2514
|
+
}
|
|
2515
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LifecycleHooksConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2516
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LifecycleHooksConfigService, providedIn: 'root' }); }
|
|
2517
|
+
}
|
|
2518
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LifecycleHooksConfigService, decorators: [{
|
|
2519
|
+
type: Injectable,
|
|
2520
|
+
args: [{ providedIn: 'root' }]
|
|
2521
|
+
}] });
|
|
2522
|
+
|
|
2523
|
+
class LuigiComponent {
|
|
2524
|
+
constructor() {
|
|
2525
|
+
this.lifecycleHooksConfigService = inject(LifecycleHooksConfigService);
|
|
2526
|
+
this.luigiCoreService = inject(LuigiCoreService);
|
|
2527
|
+
this.authService = inject(AuthService);
|
|
2528
|
+
this.routingConfigService = inject(RoutingConfigServiceImpl);
|
|
2529
|
+
this.authConfigService = inject(AuthConfigService);
|
|
2530
|
+
this.staticSettingsConfigService = inject(StaticSettingsConfigServiceImpl);
|
|
2531
|
+
}
|
|
2532
|
+
async ngOnInit() {
|
|
2533
|
+
try {
|
|
2534
|
+
this.luigiCoreService.setConfig({
|
|
2535
|
+
auth: await this.authConfigService.getAuthConfig(),
|
|
2536
|
+
routing: this.routingConfigService.getInitialRoutingConfig(),
|
|
2537
|
+
lifecycleHooks: this.lifecycleHooksConfigService.getLifecycleHooksConfig(),
|
|
2538
|
+
settings: await this.staticSettingsConfigService.getStaticSettingsConfig(),
|
|
2539
|
+
});
|
|
2540
|
+
this.luigiCoreService.setAuthData(this.authService.getAuthData());
|
|
2541
|
+
}
|
|
2542
|
+
catch (e) {
|
|
2543
|
+
console.error(`Luigi Component init failed: ${e.toString()}`);
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2547
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: LuigiComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: '', isInline: true }); }
|
|
2548
|
+
}
|
|
2549
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LuigiComponent, decorators: [{
|
|
2550
|
+
type: Component,
|
|
2551
|
+
args: [{
|
|
2552
|
+
template: '',
|
|
2553
|
+
standalone: true,
|
|
2554
|
+
}]
|
|
2555
|
+
}] });
|
|
2556
|
+
|
|
2557
|
+
document.body.classList.add('ui5-content-density-compact');
|
|
2558
|
+
class PortalComponent {
|
|
2559
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: PortalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2560
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: PortalComponent, isStandalone: true, selector: "app-portal", ngImport: i0, template: "<div class=\"fd-page__content\">\n <router-outlet></router-outlet>\n</div>\n", styles: [".fd-page__header{padding-left:1.5rem}.settings-icon-active{color:#0064d9!important}.local-development-settings-indication{position:absolute;top:-4px;right:-4px;width:12px;height:12px;font-size:12px}.entity-nav-header{padding-left:var(--fdNavigation_Padding_X);padding-right:var(--fdNavigation_Padding_X);padding-bottom:1.25rem!important}.entity-nav-header-type{font-size:12px}.entity-nav-header-label{color:var(--sapAccentColor6);padding-top:8px}.fd-container.fd-form-layout-grid-container .fd-row .fd-col{white-space:inherit!important}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
2561
|
+
}
|
|
2562
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: PortalComponent, decorators: [{
|
|
2563
|
+
type: Component,
|
|
2564
|
+
args: [{ selector: 'app-portal', standalone: true, imports: [RouterOutlet], encapsulation: ViewEncapsulation.None, template: "<div class=\"fd-page__content\">\n <router-outlet></router-outlet>\n</div>\n", styles: [".fd-page__header{padding-left:1.5rem}.settings-icon-active{color:#0064d9!important}.local-development-settings-indication{position:absolute;top:-4px;right:-4px;width:12px;height:12px;font-size:12px}.entity-nav-header{padding-left:var(--fdNavigation_Padding_X);padding-right:var(--fdNavigation_Padding_X);padding-bottom:1.25rem!important}.entity-nav-header-type{font-size:12px}.entity-nav-header-label{color:var(--sapAccentColor6);padding-top:8px}.fd-container.fd-form-layout-grid-container .fd-row .fd-col{white-space:inherit!important}\n"] }]
|
|
2565
|
+
}] });
|
|
2566
|
+
|
|
2567
|
+
const portalRouts = [
|
|
2568
|
+
{ path: 'logout', component: LogoutComponent },
|
|
2569
|
+
{ path: '', component: LuigiComponent },
|
|
2570
|
+
{ path: '**', component: LuigiComponent },
|
|
2571
|
+
];
|
|
2572
|
+
|
|
2573
|
+
class CustomReuseStrategy {
|
|
2574
|
+
shouldDetach(route) {
|
|
2575
|
+
// Optionally, you can customize which routes should be detached (stored)
|
|
2576
|
+
return false; // Not detaching any routes for now
|
|
2577
|
+
}
|
|
2578
|
+
store(route, handle) {
|
|
2579
|
+
// Optional: Store the detached route here if needed
|
|
2580
|
+
}
|
|
2581
|
+
shouldAttach(route) {
|
|
2582
|
+
// Optional: Specify which routes to reattach
|
|
2583
|
+
return false; // Not attaching any routes for now
|
|
2584
|
+
}
|
|
2585
|
+
retrieve(route) {
|
|
2586
|
+
// Optional: Retrieve the stored route if needed
|
|
2587
|
+
return null; // Returning null means no route is retrieved
|
|
2588
|
+
}
|
|
2589
|
+
shouldReuseRoute(future, curr) {
|
|
2590
|
+
return (future.routeConfig === curr.routeConfig ||
|
|
2591
|
+
future.routeConfig?.component === curr.routeConfig?.component);
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
function providePortal(options = {}) {
|
|
2596
|
+
const providers = [
|
|
2597
|
+
provideHttpClient(),
|
|
2598
|
+
provideZoneChangeDetection({ eventCoalescing: true }),
|
|
2599
|
+
provideBootstrap(),
|
|
2600
|
+
provideSessionRefresh(),
|
|
2601
|
+
provideNavigationTracker(),
|
|
2602
|
+
provideLanguageServices(),
|
|
2603
|
+
provideRouter(portalRouts),
|
|
2604
|
+
{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy },
|
|
2605
|
+
...addOptionalProviders(options),
|
|
2606
|
+
];
|
|
2607
|
+
return makeEnvironmentProviders(providers);
|
|
2608
|
+
}
|
|
2609
|
+
const addOptionalProviders = (options) => {
|
|
2610
|
+
const providers = [];
|
|
2611
|
+
(options.customMessageListeners || []).forEach((customMessageListenerClass) => providers.push({
|
|
2612
|
+
provide: LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN,
|
|
2613
|
+
multi: true,
|
|
2614
|
+
useClass: customMessageListenerClass,
|
|
2615
|
+
}));
|
|
2616
|
+
providers.push({
|
|
2617
|
+
provide: LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2618
|
+
useClass: options.appSwitcherConfigService || AppSwitcherConfigServiceImpl,
|
|
2619
|
+
});
|
|
2620
|
+
if (options.userProfileConfigService) {
|
|
2621
|
+
providers.push({
|
|
2622
|
+
provide: LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2623
|
+
useClass: options.userProfileConfigService,
|
|
2624
|
+
});
|
|
2625
|
+
}
|
|
2626
|
+
if (options.luigiExtendedGlobalContextConfigService) {
|
|
2627
|
+
providers.push({
|
|
2628
|
+
provide: LUIGI_EXTENDED_GLOBAL_CONTEXT_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2629
|
+
useClass: options.luigiExtendedGlobalContextConfigService,
|
|
2630
|
+
});
|
|
2631
|
+
}
|
|
2632
|
+
if (options.nodeChangeHookConfigService) {
|
|
2633
|
+
providers.push({
|
|
2634
|
+
provide: LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN,
|
|
2635
|
+
useClass: options.nodeChangeHookConfigService,
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
if (options.nodeContextProcessingService) {
|
|
2639
|
+
providers.push({
|
|
2640
|
+
provide: LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN,
|
|
2641
|
+
useClass: options.nodeContextProcessingService,
|
|
2642
|
+
});
|
|
2643
|
+
}
|
|
2644
|
+
if (options.localConfigurationService) {
|
|
2645
|
+
providers.push({
|
|
2646
|
+
provide: LOCAL_CONFIGURATION_SERVICE_INJECTION_TOKEN,
|
|
2647
|
+
useClass: options.localConfigurationService,
|
|
2648
|
+
});
|
|
2649
|
+
}
|
|
2650
|
+
if (options.staticSettingsConfigService) {
|
|
2651
|
+
providers.push({
|
|
2652
|
+
provide: LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2653
|
+
useClass: options.staticSettingsConfigService,
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
if (options.luigiAuthEventsCallbacksService) {
|
|
2657
|
+
providers.push({
|
|
2658
|
+
provide: LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN,
|
|
2659
|
+
useClass: options.luigiAuthEventsCallbacksService,
|
|
2660
|
+
});
|
|
2661
|
+
}
|
|
2662
|
+
if (options.customNodeProcessingService) {
|
|
2663
|
+
providers.push({
|
|
2664
|
+
provide: LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN,
|
|
2665
|
+
useClass: options.customNodeProcessingService,
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
if (options.customGlobalNodesService) {
|
|
2669
|
+
providers.push({
|
|
2670
|
+
provide: LUIGI_NODES_CUSTOM_GLOBAL_SERVICE_INJECTION_TOKEN,
|
|
2671
|
+
useClass: options.customGlobalNodesService,
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
if (options.themingService) {
|
|
2675
|
+
providers.push({
|
|
2676
|
+
provide: THEMING_SERVICE,
|
|
2677
|
+
useClass: options.themingService,
|
|
2678
|
+
});
|
|
2679
|
+
}
|
|
2680
|
+
if (options.globalSearchConfigService) {
|
|
2681
|
+
providers.push({
|
|
2682
|
+
provide: LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2683
|
+
useClass: options.globalSearchConfigService,
|
|
2684
|
+
});
|
|
2685
|
+
}
|
|
2686
|
+
if (options.errorComponentConfig) {
|
|
2687
|
+
providers.push({
|
|
2688
|
+
provide: ERROR_COMPONENT_CONFIG,
|
|
2689
|
+
useValue: options.errorComponentConfig,
|
|
2690
|
+
});
|
|
2691
|
+
}
|
|
2692
|
+
if (options.headerBarConfigService) {
|
|
2693
|
+
providers.push({
|
|
2694
|
+
provide: HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2695
|
+
useClass: options.headerBarConfigService,
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
if (options.routingConfigService) {
|
|
2699
|
+
providers.push({
|
|
2700
|
+
provide: LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN,
|
|
2701
|
+
useClass: options.routingConfigService,
|
|
2702
|
+
});
|
|
2703
|
+
}
|
|
2704
|
+
return providers;
|
|
2705
|
+
};
|
|
2706
|
+
|
|
2707
|
+
/*
|
|
2708
|
+
* Public API Surface of lib
|
|
2709
|
+
*/
|
|
2710
|
+
|
|
2711
|
+
/**
|
|
2712
|
+
* Generated bundle index. Do not edit.
|
|
2713
|
+
*/
|
|
2714
|
+
|
|
2715
|
+
export { AppSwitcherConfigServiceImpl, AuthConfigService, AuthEvent, AuthService, ConfigService, CustomMessageListenersService, CustomReuseStrategy, ERROR_COMPONENT_CONFIG, EntityType, EnvConfigService, GlobalContextConfigService, HEADER_BAR_CONFIG_SERVICE_INJECTION_TOKEN, HeaderBarService, I18nService, IframeService, LOCAL_CONFIGURATION_SERVICE_INJECTION_TOKEN, LUIGI_APP_SWITCHER_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_AUTH_EVENTS_CALLBACKS_SERVICE_INJECTION_TOKEN, LUIGI_BREADCRUMB_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_CUSTOM_MESSAGE_LISTENERS_INJECTION_TOKEN, LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN, LUIGI_CUSTOM_NODE_PROCESSING_SERVICE_INJECTION_TOKEN, LUIGI_EXTENDED_GLOBAL_CONTEXT_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_GLOBAL_SEARCH_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_NODES_CUSTOM_GLOBAL_SERVICE_INJECTION_TOKEN, LUIGI_NODE_CHANGE_HOOK_SERVICE_INJECTION_TOKEN, LUIGI_ROUTING_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_STATIC_SETTINGS_CONFIG_SERVICE_INJECTION_TOKEN, LUIGI_USER_PROFILE_CONFIG_SERVICE_INJECTION_TOKEN, LocalConfigurationServiceImpl, LocalNodesService, LocalStorageKeys, LoginEventService, LoginEventType, LuigiCoreService, LuigiNodesService, NetworkVisibility, NodeUtilsService, PortalComponent, RequestHeadersService, RoutingConfigServiceImpl, SessionRefreshService, StaticSettingsConfigServiceImpl, THEMING_SERVICE, UserSettingsConfigService, featureToggleLocalStorage, localDevelopmentSettingsLocalStorage, matchesJMESPath, providePortal, userSettingsLocalStorage };
|
|
2716
|
+
//# sourceMappingURL=openmfp-portal-ui-lib.mjs.map
|