@openmfp/portal-ui-lib 0.182.14 → 0.183.1

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.
@@ -173,14 +173,16 @@ class RequestHeadersService {
173
173
  language = params['language'];
174
174
  }
175
175
  });
176
+ const headers = new HttpHeaders({
177
+ 'Accept-Language': language || '',
178
+ });
176
179
  if (!authData?.idToken) {
177
- throw new Error('Unable to create authorization header, no id token present.');
180
+ return {
181
+ headers,
182
+ };
178
183
  }
179
184
  return {
180
- headers: new HttpHeaders({
181
- authorization: 'Bearer ' + authData.idToken,
182
- 'Accept-Language': language || '',
183
- }),
185
+ headers: headers.append('authorization', 'Bearer ' + authData.idToken),
184
186
  };
185
187
  }
186
188
  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 }); }
@@ -228,8 +230,9 @@ class ConfigService {
228
230
  this.entityConfigCache[entity] = {};
229
231
  }
230
232
  const entityCacheKey = JSON.stringify(context);
231
- if (this.entityConfigCache[entity][entityCacheKey]) {
232
- return this.entityConfigCache[entity][entityCacheKey];
233
+ const cachedConfig = this.entityConfigCache[entity][entityCacheKey];
234
+ if (cachedConfig) {
235
+ return cachedConfig;
233
236
  }
234
237
  const options = this.requestHeadersService.createOptionsWithAuthHeader();
235
238
  const entityConfig = firstValueFrom(this.http.get(`/rest/config/${entity}`, {
@@ -669,6 +672,9 @@ const localDevelopmentSettingsLocalStorage = {
669
672
  return null;
670
673
  }
671
674
  try {
675
+ if (!localDevelopmentSettingsFromLocalStore) {
676
+ return null;
677
+ }
672
678
  return JSON.parse(localDevelopmentSettingsFromLocalStore);
673
679
  }
674
680
  catch (e) {
@@ -795,7 +801,7 @@ class IframeService {
795
801
  allow += ';';
796
802
  }
797
803
  permissions.allow.forEach((policy) => {
798
- if (this.isIFrameFeaturePolicyAllowed(policy, iframe.getAttribute('src'))) {
804
+ if (this.isIFrameFeaturePolicyAllowed(policy, this.getIframeSrc(iframe))) {
799
805
  // feature policies are separated by semicolon
800
806
  allow += ` ${policy};`;
801
807
  }
@@ -805,7 +811,7 @@ class IframeService {
805
811
  if (permissions.sandbox) {
806
812
  let sandbox = (iframe.getAttribute('sandbox') || '').trim();
807
813
  permissions.sandbox.forEach((permission) => {
808
- if (this.isIFrameSandboxPermissionAllowed(permission, iframe.getAttribute('src'))) {
814
+ if (this.isIFrameSandboxPermissionAllowed(permission, this.getIframeSrc(iframe))) {
809
815
  // sandbox permission are separated by whitespace
810
816
  sandbox += ' ' + permission;
811
817
  }
@@ -813,6 +819,17 @@ class IframeService {
813
819
  iframe.setAttribute('sandbox', sandbox.trim());
814
820
  }
815
821
  }
822
+ getIframeSrc(iframe) {
823
+ const src = iframe.getAttribute('src');
824
+ if (!src) {
825
+ this.luigiCoreService.showAlert({
826
+ text: 'Iframe source not found',
827
+ type: 'error',
828
+ });
829
+ throw new Error('Iframe source not found');
830
+ }
831
+ return src;
832
+ }
816
833
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IframeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
817
834
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: IframeService, providedIn: 'root' }); }
818
835
  }
@@ -1002,7 +1019,7 @@ class UserSettingsConfigService {
1002
1019
  this.applyNewTheme(settings, previous);
1003
1020
  this.changeToSelectedLanguage(settings, previous);
1004
1021
  this.saveLocalDevelopmentSettings(settings, previous);
1005
- if (envConfig.uiOptions.includes('enableFeatureToggleSetting')) {
1022
+ if (envConfig.uiOptions?.includes('enableFeatureToggleSetting')) {
1006
1023
  this.saveFeatureToggleSettings(settings);
1007
1024
  }
1008
1025
  },
@@ -1015,7 +1032,7 @@ class UserSettingsConfigService {
1015
1032
  await this.addUserSettings(settings);
1016
1033
  await this.addThemingSettings(settings);
1017
1034
  this.addLocalDevelopmentSettings(settings);
1018
- if (envConfig.uiOptions.includes('enableFeatureToggleSetting')) {
1035
+ if (envConfig.uiOptions?.includes('enableFeatureToggleSetting')) {
1019
1036
  this.addFeatureToggleSettings(settings);
1020
1037
  }
1021
1038
  this.addInfoSettings(settings);
@@ -1023,10 +1040,12 @@ class UserSettingsConfigService {
1023
1040
  }
1024
1041
  saveFeatureToggleSettings(settings) {
1025
1042
  const currentFeatureToggleSettings = settings?.frame_featureToggle?.featureToggleSettings;
1026
- featureToggleLocalStorage.store(currentFeatureToggleSettings);
1027
- this.luigiCoreService.unsetAllFeatureToggles();
1028
- this.luigiCoreService.setFeatureToggles(currentFeatureToggleSettings);
1029
- globalThis.location.reload();
1043
+ if (currentFeatureToggleSettings) {
1044
+ featureToggleLocalStorage.store(currentFeatureToggleSettings);
1045
+ this.luigiCoreService.unsetAllFeatureToggles();
1046
+ this.luigiCoreService.setFeatureToggles(currentFeatureToggleSettings);
1047
+ globalThis.location.reload();
1048
+ }
1030
1049
  }
1031
1050
  saveLocalDevelopmentSettings(settings, previous) {
1032
1051
  const currentLocalDevelopmentSettings = settings?.frame_development?.localDevelopmentSettings;
@@ -1079,10 +1098,10 @@ class UserSettingsConfigService {
1079
1098
  const user = this.authService.getUserInfo();
1080
1099
  const userSettings = await userSettingsLocalStorage.read(user);
1081
1100
  const selectedTheme = userSettings?.frame_appearance?.selectedTheme ||
1082
- this.luigiThemingService.getDefaultThemeId();
1083
- return this.luigiThemingService
1084
- .getAvailableThemes()
1085
- .find((t) => t.id === selectedTheme)?.name;
1101
+ this.luigiThemingService?.getDefaultThemeId();
1102
+ return (this.luigiThemingService
1103
+ ?.getAvailableThemes()
1104
+ ?.find((t) => t.id === selectedTheme)?.name || '');
1086
1105
  }
1087
1106
  async addThemingSettings(settings) {
1088
1107
  if (this.luigiThemingService) {
@@ -1263,8 +1282,8 @@ class AppSwitcherConfigServiceImpl {
1263
1282
  })
1264
1283
  .map((node) => {
1265
1284
  const nodeConfig = {
1266
- title: node.label,
1267
- icon: node.icon,
1285
+ title: node.label || '',
1286
+ icon: node.icon || '',
1268
1287
  link: '/' + node.pathSegment,
1269
1288
  };
1270
1289
  return nodeConfig;
@@ -1354,6 +1373,9 @@ class AuthConfigService {
1354
1373
  }
1355
1374
  async getAuthConfig() {
1356
1375
  const { oauthServerUrl, clientId } = await this.envConfigService.getEnvConfig();
1376
+ if (!oauthServerUrl || !clientId) {
1377
+ return undefined;
1378
+ }
1357
1379
  return {
1358
1380
  use: 'oAuth2AuthCode',
1359
1381
  storage: 'none',
@@ -1488,9 +1510,9 @@ class LocalConfigurationServiceImpl {
1488
1510
  this.luigiCoreService.showAlert({
1489
1511
  text: `
1490
1512
  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.
1513
+ You will not be able to see your local changes and local development results unless you correct the data and reload the page.
1492
1514
  Please see below the detailed information: <br/><br/>
1493
-
1515
+
1494
1516
  ${message}
1495
1517
  `,
1496
1518
  type: 'error',
@@ -1541,8 +1563,8 @@ class LocalConfigurationServiceImpl {
1541
1563
  const localEntityTypes = [...new Set(localNodes.map((n) => n.entityType))]
1542
1564
  .filter(Boolean)
1543
1565
  .join(',');
1544
- console.debug(`Found '${serverLuigiNodes.length}' server nodes.
1545
- Found '${localNodes.length}' local luigi nodes.
1566
+ console.debug(`Found '${serverLuigiNodes.length}' server nodes.
1567
+ Found '${localNodes.length}' local luigi nodes.
1546
1568
  The entities of the server node are: [${serverEntityTypes}]
1547
1569
  The entities of local nodes are: [${localEntityTypes}]`);
1548
1570
  }
@@ -1552,10 +1574,10 @@ class LocalConfigurationServiceImpl {
1552
1574
  }
1553
1575
  async getLocalConfigurations(localDevelopmentSettings) {
1554
1576
  const initialConfigurations = localDevelopmentSettings.configs
1555
- .filter((config) => config.data)
1577
+ .filter((config) => !!config.data)
1556
1578
  .map((config) => config.data);
1557
1579
  const configurations = (await Promise.allSettled(localDevelopmentSettings.configs
1558
- .filter((config) => config.url)
1580
+ .filter((config) => !!config.url)
1559
1581
  .map((config) => lastValueFrom(this.http.get(config.url)).then((contentConfiguration) => ({
1560
1582
  ...contentConfiguration,
1561
1583
  url: config.url,
@@ -1579,6 +1601,7 @@ class LuigiNodesService {
1579
1601
  constructor() {
1580
1602
  this.i18nService = inject(I18nService);
1581
1603
  this.configService = inject(ConfigService);
1604
+ this.luigiCoreService = inject(LuigiCoreService);
1582
1605
  this.localConfigurationService = inject(LocalConfigurationServiceImpl);
1583
1606
  this.errorComponentConfig = inject(ERROR_COMPONENT_CONFIG, {
1584
1607
  optional: true,
@@ -1615,18 +1638,19 @@ class LuigiNodesService {
1615
1638
  let configsForEntity;
1616
1639
  const entityType = entityDefinition.dynamicFetchId;
1617
1640
  try {
1641
+ if (!entityType) {
1642
+ throw new Error('Entity type is required');
1643
+ }
1618
1644
  configsForEntity = await this.configService.getEntityConfig(entityType, additionalContext);
1645
+ return configsForEntity.providers.flatMap((p) => p.nodes);
1619
1646
  }
1620
1647
  catch (e) {
1621
1648
  errorCode = e.status || 500;
1622
1649
  console.warn(`Could not retrieve nodes for entity: ${entityType}, error: `, e);
1650
+ return this.createErrorNodes(entityDefinition, errorCode, additionalContext);
1623
1651
  }
1624
- if (errorCode) {
1625
- return this.createErrorNodes(entityDefinition, additionalContext, errorCode);
1626
- }
1627
- return configsForEntity.providers.flatMap((p) => p.nodes);
1628
1652
  }
1629
- createErrorNodes(entityDefinition, additionalContext, errorCode) {
1653
+ createErrorNodes(entityDefinition, errorCode, additionalContext) {
1630
1654
  return [
1631
1655
  {
1632
1656
  pathSegment: 'error',
@@ -1951,10 +1975,10 @@ function logJMESException(context, jmesPathExpression, error) {
1951
1975
 
1952
1976
  const visibleForContext = (ctx, node) => {
1953
1977
  // visibleForEntityContext is deprecated
1954
- if (!isMatch(ctx.entityContext, node.visibleForEntityContext)) {
1978
+ if (!isMatch(ctx?.entityContext, node.visibleForEntityContext)) {
1955
1979
  return false;
1956
1980
  }
1957
- return matchesJMESPath(ctx, node.visibleForContext);
1981
+ return matchesJMESPath(ctx, node.visibleForContext ?? '');
1958
1982
  };
1959
1983
  const computeDynamicFetchContext = (entityNode, ctx) => {
1960
1984
  const contextForEntityConfig = new Map();
@@ -2052,6 +2076,9 @@ class NodeSortingService {
2052
2076
  const sortedOther = otherChildren.sort(this.nodeComparison);
2053
2077
  if (slotNodes.length > 0) {
2054
2078
  slotNodes.forEach((slotNode) => {
2079
+ if (!slotNode.defineSlot) {
2080
+ return;
2081
+ }
2055
2082
  if (slottedChildrenMap[slotNode.defineSlot]) {
2056
2083
  this.appendChildrenToSlot(sortedNodes, slotNode, slottedChildrenMap[slotNode.defineSlot].sort(this.nodeComparison));
2057
2084
  delete slottedChildrenMap[slotNode.defineSlot];
@@ -2114,7 +2141,7 @@ class ChildrenNodesService {
2114
2141
  entityContext[dynamicFetchId] = (await this.configService.getEntityConfig(dynamicFetchId, context)).entityContext;
2115
2142
  }
2116
2143
  catch (error) {
2117
- console.error(entityNode.defineEntity.id, 'does not exist', context);
2144
+ console.error(entityNode.defineEntity?.id, 'does not exist', context);
2118
2145
  }
2119
2146
  }));
2120
2147
  childrenNodes.forEach((child) => {
@@ -2183,6 +2210,7 @@ class CommonGlobalLuigiNodesService {
2183
2210
  label: 'Content not found',
2184
2211
  order: '1000',
2185
2212
  hideFromNav: true,
2213
+ context: {},
2186
2214
  children: [
2187
2215
  {
2188
2216
  pathSegment: ':id',
@@ -2216,6 +2244,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
2216
2244
  class NodesProcessingService {
2217
2245
  constructor() {
2218
2246
  this.nodeContextProcessingService = inject(LUIGI_CUSTOM_NODE_CONTEXT_PROCESSING_SERVICE_INJECTION_TOKEN, { optional: true });
2247
+ this.luigiCoreService = inject(LuigiCoreService);
2219
2248
  this.luigiNodesService = inject(LuigiNodesService);
2220
2249
  this.localConfigurationService = inject(LocalConfigurationServiceImpl);
2221
2250
  this.nodeSortingService = inject(NodeSortingService);
@@ -2265,6 +2294,13 @@ class NodesProcessingService {
2265
2294
  }
2266
2295
  }
2267
2296
  processNodeDefineEntity(node, childrenByEntity, parentEntityPath, directChildren) {
2297
+ if (!node.defineEntity) {
2298
+ this.luigiCoreService.showAlert({
2299
+ text: 'Node defineEntity is missing',
2300
+ type: 'error',
2301
+ });
2302
+ throw new Error('Node defineEntity is missing');
2303
+ }
2268
2304
  let newEntityPath = parentEntityPath;
2269
2305
  if (parentEntityPath?.length > 0) {
2270
2306
  newEntityPath = parentEntityPath + '.' + node.defineEntity.id;
@@ -2305,10 +2341,11 @@ class NodesProcessingService {
2305
2341
  entityChildrenProvider(entityNode, ctx, childrenByEntity, directChildren, entityPath) {
2306
2342
  return new Promise(async (resolve, reject) => {
2307
2343
  const entityTypeId = entityPath || entityNode?.defineEntity?.id;
2308
- const entityId = ctx[entityNode?.defineEntity?.contextKey];
2344
+ const contextKey = entityNode?.defineEntity?.contextKey;
2345
+ const entityId = contextKey ? ctx[contextKey] : undefined;
2309
2346
  const staticChildren = [
2310
2347
  ...(directChildren || []),
2311
- ...(childrenByEntity[entityTypeId] || []),
2348
+ ...(childrenByEntity[entityTypeId ?? ''] || []),
2312
2349
  ];
2313
2350
  await this.nodeContextProcessingService?.processNodeContext(entityId, entityNode, ctx);
2314
2351
  if (!entityTypeId || !entityNode.defineEntity?.dynamicFetchId) {
@@ -2329,7 +2366,7 @@ class NodesProcessingService {
2329
2366
  }
2330
2367
  catch (error) {
2331
2368
  dynamicRetrievedChildren = staticChildren;
2332
- staticRetrievedChildren = null;
2369
+ staticRetrievedChildren = undefined;
2333
2370
  }
2334
2371
  const childrenList = await this.createChildrenList(entityNode, ctx, childrenByEntity, entityPath, dynamicRetrievedChildren, staticRetrievedChildren);
2335
2372
  resolve(childrenList);
@@ -2414,7 +2451,7 @@ class NavigationConfigService {
2414
2451
  };
2415
2452
  }
2416
2453
  initFeatureToggles(configFeatureToggles, envConfig) {
2417
- if (envConfig.uiOptions.includes('enableFeatureToggleSetting')) {
2454
+ if (envConfig.uiOptions?.includes('enableFeatureToggleSetting')) {
2418
2455
  const featureToggleSettings = featureToggleLocalStorage.read();
2419
2456
  this.luigiCoreService.setFeatureToggles({
2420
2457
  ...configFeatureToggles,
@@ -2506,7 +2543,7 @@ class LifecycleHooksConfigService {
2506
2543
  this.luigiCoreService.ux().hideAppLoadingIndicator();
2507
2544
  }
2508
2545
  openErrorDialog() {
2509
- const appTitle = this.luigiCoreService.config.settings.header.title;
2546
+ const appTitle = this.luigiCoreService.config?.settings?.header?.title;
2510
2547
  this.luigiCoreService.showAlert({
2511
2548
  text: $localize `There was an error loading the ${appTitle}`,
2512
2549
  type: 'error',