@platform-mesh/portal-ui-lib 0.68.7 → 0.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
+ import { EntityType, I18nService, LuigiNodesService, AuthService, LuigiCoreService, ConfigService, EnvConfigService, LocalStorageKeys } from '@openmfp/portal-ui-lib';
1
2
  import * as i0 from '@angular/core';
2
3
  import { inject, Injectable, DestroyRef, signal, computed, ViewChild, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
3
- import { I18nService, EntityType, AuthService, LuigiCoreService, ConfigService, EnvConfigService, LocalStorageKeys } from '@openmfp/portal-ui-lib';
4
4
  import '@ui5/webcomponents/dist/Breadcrumbs.js';
5
5
  import '@ui5/webcomponents/dist/BreadcrumbsItem.js';
6
6
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@@ -13,6 +13,42 @@ import { shareReplay, retry, takeUntil, switchMap, startWith, scan, tap, catchEr
13
13
  import { CommonModule } from '@angular/common';
14
14
  import { DomSanitizer } from '@angular/platform-browser';
15
15
 
16
+ const errorView = {
17
+ viewUrl: '/assets/platform-mesh-portal-ui-wc.js#error-component',
18
+ webcomponent: {
19
+ selfRegistered: true,
20
+ type: 'module',
21
+ },
22
+ };
23
+ function toEntityErrorNode(node, code) {
24
+ return {
25
+ ...node,
26
+ ...errorView,
27
+ compound: undefined,
28
+ viewGroup: undefined,
29
+ virtualTree: undefined,
30
+ ...(node.virtualTree && {
31
+ keepSelectedForChildren: true,
32
+ children: () => [createEntityErrorNode(code)],
33
+ }),
34
+ context: { ...node.context, entityErrorCode: code },
35
+ };
36
+ }
37
+ function createEntityErrorNode(code) {
38
+ return toEntityErrorNode({
39
+ pathSegment: ':errorPath',
40
+ entityType: EntityType.ENTITY_ERROR,
41
+ hideFromNav: true,
42
+ context: {},
43
+ children: () => [createEntityErrorNode(code)],
44
+ }, code);
45
+ }
46
+ const errorComponentConfig = {
47
+ handleEntityRetrievalError: (_entityDefinition, errorCode) => [
48
+ createEntityErrorNode(errorCode),
49
+ ],
50
+ };
51
+
16
52
  class CustomGlobalNodesServiceImpl {
17
53
  constructor() {
18
54
  this.i18nService = inject(I18nService);
@@ -31,15 +67,11 @@ class CustomGlobalNodesServiceImpl {
31
67
  entityType: EntityType.ENTITY_ERROR,
32
68
  hideFromNav: true,
33
69
  hideSideNav: true,
34
- viewUrl: '/assets/platform-mesh-portal-ui-wc.js#error-component',
70
+ ...errorView,
35
71
  context: {
36
72
  id: ':id',
37
73
  translationTable: this.i18nService.translationTable,
38
74
  },
39
- webcomponent: {
40
- selfRegistered: true,
41
- type: 'module',
42
- },
43
75
  },
44
76
  ],
45
77
  },
@@ -88,6 +120,78 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImpor
88
120
  args: [{ providedIn: 'root' }]
89
121
  }] });
90
122
 
123
+ class CustomNodeProcessingServiceImpl {
124
+ constructor() {
125
+ this.luigiNodesService = inject(LuigiNodesService);
126
+ this.entityChildrenWrappers = new WeakSet();
127
+ this.failedEntityNodeStates = new WeakMap();
128
+ }
129
+ async processNode(ctx, node) {
130
+ this.wrapEntityChildren(node);
131
+ return ctx?.entityErrorCode
132
+ ? toEntityErrorNode(node, ctx.entityErrorCode)
133
+ : node;
134
+ }
135
+ wrapEntityChildren(node) {
136
+ const children = node.children;
137
+ if (!node.defineEntity ||
138
+ typeof children !== 'function' ||
139
+ this.entityChildrenWrappers.has(children)) {
140
+ return;
141
+ }
142
+ const wrapper = (ctx) => this.resolveEntityChildren(node, children, ctx);
143
+ this.entityChildrenWrappers.add(wrapper);
144
+ node.children = wrapper;
145
+ }
146
+ async resolveEntityChildren(node, children, ctx) {
147
+ this.restoreEntityNode(node, ctx);
148
+ const isBelowFailedEntity = !!ctx.entityErrorCode;
149
+ const result = (await children(ctx)) ?? [];
150
+ const retrievalFailure = result.find((child) => child.entityType === EntityType.ENTITY_ERROR);
151
+ const code = ctx.entityErrorCode ?? retrievalFailure?.context.entityErrorCode;
152
+ if (!code) {
153
+ return result;
154
+ }
155
+ ctx.entityErrorCode = code;
156
+ if (!isBelowFailedEntity) {
157
+ this.luigiNodesService.clearNodeCache();
158
+ }
159
+ if (retrievalFailure || (!result.length && !isBelowFailedEntity)) {
160
+ this.showErrorOnEntityNode(node, code);
161
+ return [createEntityErrorNode(code)];
162
+ }
163
+ return result.map((child) => toEntityErrorNode(child, code));
164
+ }
165
+ restoreEntityNode(node, ctx) {
166
+ const state = this.failedEntityNodeStates.get(node);
167
+ if (state) {
168
+ this.failedEntityNodeStates.delete(node);
169
+ delete ctx.entityErrorCode;
170
+ Object.assign(node, state);
171
+ }
172
+ }
173
+ showErrorOnEntityNode(node, code) {
174
+ this.failedEntityNodeStates.set(node, {
175
+ keepSelectedForChildren: node.keepSelectedForChildren,
176
+ viewUrl: node.viewUrl,
177
+ webcomponent: node.webcomponent,
178
+ compound: node.compound,
179
+ context: node.context,
180
+ });
181
+ Object.assign(node, errorView, {
182
+ keepSelectedForChildren: undefined,
183
+ compound: undefined,
184
+ context: { ...node.context, entityErrorCode: code },
185
+ });
186
+ }
187
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: CustomNodeProcessingServiceImpl, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
188
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: CustomNodeProcessingServiceImpl, providedIn: 'root' }); }
189
+ }
190
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImport: i0, type: CustomNodeProcessingServiceImpl, decorators: [{
191
+ type: Injectable,
192
+ args: [{ providedIn: 'root' }]
193
+ }] });
194
+
91
195
  const breadcrumbRenderer = (containerElement, nodeItems, clickHandler) => {
92
196
  containerElement.style.width = '100%';
93
197
  const ui5breadcrumbs = document.createElement('ui5-breadcrumbs');
@@ -1205,6 +1309,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImpor
1205
1309
  args: [{ providedIn: 'root' }]
1206
1310
  }] });
1207
1311
 
1312
+ const ORGANIZATION_NOT_READY_ERROR_CODE = 503;
1208
1313
  class NodeContextProcessingServiceImpl {
1209
1314
  constructor() {
1210
1315
  this.crdGatewayKcpPatchResolver = inject(CrdGatewayKcpPatchResolver);
@@ -1218,7 +1323,7 @@ class NodeContextProcessingServiceImpl {
1218
1323
  async processNodeContext(dynamicEntityId, entityNode, ctx) {
1219
1324
  const kind = entityNode.defineEntity?.type;
1220
1325
  const entityId = dynamicEntityId || entityNode.context.resourceDefinition?.name;
1221
- if (!entityId) {
1326
+ if (!entityId || ctx.entityErrorCode) {
1222
1327
  return;
1223
1328
  }
1224
1329
  const { kcpPath, accountPath } = await this.crdGatewayKcpPatchResolver.resolveCrdGatewayKcpPath(entityNode, entityId, kind);
@@ -1243,32 +1348,14 @@ class NodeContextProcessingServiceImpl {
1243
1348
  // update the node context of sa node to contain the entity for future context calculations
1244
1349
  this.addFieldsToContextFromAccountInfo(entityNode.context, entityId, accountInfo);
1245
1350
  // we were able to ready the account info so on this kcpPath we can query for the organization ready state
1246
- this.organizationReadyService.checkOrganizationReady();
1247
- }
1248
- catch (e) {
1249
- if (this.errorHandlerService.redirectToErrorPage(e, this.isLocationWithinEntity(entityNode, dynamicEntityId))) {
1250
- await this.abandonPendingNavigation();
1351
+ if (!(await this.organizationReadyService.isOrganizationReady())) {
1352
+ ctx.entityErrorCode = ORGANIZATION_NOT_READY_ERROR_CODE;
1251
1353
  }
1252
- this.errorHandlerService.handleError(e, 'Failed to read account info.');
1253
1354
  }
1254
- }
1255
- abandonPendingNavigation() {
1256
- return new Promise(() => { });
1257
- }
1258
- isLocationWithinEntity(entityNode, dynamicEntityId) {
1259
- const locationSegments = window.location.pathname
1260
- .split('/')
1261
- .filter(Boolean);
1262
- const entitySegments = [];
1263
- for (let node = entityNode; node; node = node.parent) {
1264
- if (!node.pathSegment) {
1265
- continue;
1266
- }
1267
- const isDynamicSegment = node.pathSegment.startsWith(':');
1268
- const dynamicSegmentValue = node === entityNode ? dynamicEntityId || undefined : undefined;
1269
- entitySegments.unshift(isDynamicSegment ? dynamicSegmentValue : node.pathSegment);
1355
+ catch (e) {
1356
+ ctx.entityErrorCode = this.errorHandlerService.errorCode(e);
1357
+ console.error('Failed to read account info.', e);
1270
1358
  }
1271
- return entitySegments.every((segment, index) => segment === undefined || segment === locationSegments[index]);
1272
1359
  }
1273
1360
  addFieldsToContext(ctx, entityId, kcpPath, accountPath, kind, namespace) {
1274
1361
  ctx.kcpPath = kcpPath;
@@ -1285,7 +1372,7 @@ class NodeContextProcessingServiceImpl {
1285
1372
  ctx.namespaces = await firstValueFrom(this.namespaceService.list(ctx));
1286
1373
  }
1287
1374
  catch (e) {
1288
- this.errorHandlerService.showError(e, 'Failed to read namespaces.');
1375
+ this.errorHandlerService.handleError(e, 'Failed to read namespaces.');
1289
1376
  }
1290
1377
  }
1291
1378
  addFieldsToContextFromAccountInfo(ctx, entityId, accountInfo) {
@@ -1420,5 +1507,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.2.1", ngImpor
1420
1507
  * Generated bundle index. Do not edit.
1421
1508
  */
1422
1509
 
1423
- export { CustomGlobalNodesServiceImpl, CustomRoutingConfigServiceImpl, HeaderBarConfigServiceImpl, LuigiExtendedGlobalContextConfigServiceImpl, NavigationRedirectStrategyServiceImpl, NodeChangeHookConfigServiceImpl, NodeContextProcessingServiceImpl, OpenPersistentPanelListener, UserProfileConfigServiceImpl };
1510
+ export { CustomGlobalNodesServiceImpl, CustomNodeProcessingServiceImpl, CustomRoutingConfigServiceImpl, HeaderBarConfigServiceImpl, LuigiExtendedGlobalContextConfigServiceImpl, NavigationRedirectStrategyServiceImpl, NodeChangeHookConfigServiceImpl, NodeContextProcessingServiceImpl, OpenPersistentPanelListener, UserProfileConfigServiceImpl, errorComponentConfig };
1424
1511
  //# sourceMappingURL=platform-mesh-portal-ui-lib-portal-options.mjs.map