@meshmakers/octo-ui 3.4.280 → 3.4.290

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,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { inject, ChangeDetectionStrategy, Component, Injectable, Input, EventEmitter, Output, ElementRef, forwardRef, ViewChild, signal, computed, input, model, output, effect, untracked, Directive, InjectionToken, HostListener, makeEnvironmentProviders } from '@angular/core';
3
3
  import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
4
- import { AttributeSelectorService, AttributeValueTypeDto as AttributeValueTypeDto$1, CkTypeSelectorService, CkTypeAttributeService, GetEntitiesByCkTypeDtoGQL, RuntimeEntitySelectDataSource, RuntimeEntityDialogDataSource, SearchFilterTypesDto, SortOrdersDto, FieldFilterOperatorsDto, GetCkTypesDtoGQL, GetCkModelByIdDtoGQL, LevelMetaData, RtAssociationMetaData, CkTypeMetaData, GraphDirectionDto, AssociationModOptionsDto, GraphQL, DeleteStrategiesDto, CommunicationService, provideOctoServices } from '@meshmakers/octo-services';
4
+ import { AttributeSelectorService, AttributeValueTypeDto as AttributeValueTypeDto$1, CkTypeSelectorService, CkTypeAttributeService, GetEntitiesByCkTypeDtoGQL, RuntimeEntitySelectDataSource, RuntimeEntityDialogDataSource, SearchFilterTypesDto, SortOrdersDto, FieldFilterOperatorsDto, GetCkTypesDtoGQL, GetCkModelByIdDtoGQL, CkTypeMetaData, GraphDirectionDto, AssociationModOptionsDto, GraphQL, DeleteStrategiesDto, CommunicationService, provideOctoServices } from '@meshmakers/octo-services';
5
5
  import { Roles, provideMmSharedAuth } from '@meshmakers/shared-auth';
6
6
  import { WindowStateService, EntitySelectInputComponent, DataSourceTyped, HierarchyDataSourceBase, NotificationDisplayService, TreeComponent, ListViewComponent, FetchResultTyped, DataSourceBase, InputService, BaseTreeDetailComponent, ConfirmationService, provideMmSharedUi } from '@meshmakers/shared-ui';
7
7
  import * as i1$2 from '@angular/common';
@@ -19,12 +19,12 @@ import * as i5$1 from '@progress/kendo-angular-icons';
19
19
  import { IconsModule, SVGIconModule, SVGIconComponent } from '@progress/kendo-angular-icons';
20
20
  import * as i5 from '@progress/kendo-angular-inputs';
21
21
  import { InputsModule, TextBoxModule, KENDO_INPUTS, SwitchModule } from '@progress/kendo-angular-inputs';
22
- import { searchIcon, sortAscSmallIcon, sortDescSmallIcon, filterClearIcon, fileIcon, folderIcon, calendarIcon, checkboxCheckedIcon, listUnorderedIcon, chevronRightIcon, chevronDownIcon, downloadIcon, windowIcon, arrowRightIcon, arrowLeftIcon, chevronDoubleRightIcon, chevronDoubleLeftIcon, arrowUpIcon, arrowDownIcon, pencilIcon, trashIcon, copyIcon, folderMoreIcon, folderOpenIcon, gearIcon, plusIcon, minusIcon, dollarIcon, hyperlinkOpenIcon, infoCircleIcon, eyeIcon, arrowRotateCcwIcon, locationsIcon, arrowRotateCwIcon, xIcon, checkCircleIcon, exclamationCircleIcon, xCircleIcon, warningCircleIcon, gridIcon, linkIcon } from '@progress/kendo-svg-icons';
22
+ import { searchIcon, sortAscSmallIcon, sortDescSmallIcon, filterClearIcon, fileIcon, folderIcon, calendarIcon, checkboxCheckedIcon, listUnorderedIcon, chevronRightIcon, chevronDownIcon, downloadIcon, windowIcon, arrowRightIcon, arrowLeftIcon, chevronDoubleRightIcon, chevronDoubleLeftIcon, arrowUpIcon, arrowDownIcon, pencilIcon, trashIcon, copyIcon, folderMoreIcon, gearIcon, folderOpenIcon, plusIcon, minusIcon, dollarIcon, hyperlinkOpenIcon, infoCircleIcon, eyeIcon, arrowRotateCcwIcon, locationsIcon, arrowRotateCwIcon, xIcon, checkCircleIcon, exclamationCircleIcon, xCircleIcon, warningCircleIcon, gridIcon, linkIcon } from '@progress/kendo-svg-icons';
23
23
  import { Subject, firstValueFrom, Subscription, of, forkJoin, map as map$1, takeUntil as takeUntil$1, catchError as catchError$1, defer, from, finalize, switchMap as switchMap$1, startWith } from 'rxjs';
24
24
  import { debounceTime, distinctUntilChanged, map, switchMap, tap, catchError, takeUntil } from 'rxjs/operators';
25
25
  import { LoaderModule, BadgeModule } from '@progress/kendo-angular-indicators';
26
26
  import * as i1$3 from 'apollo-angular';
27
- import { gql } from 'apollo-angular';
27
+ import { gql, Apollo } from 'apollo-angular';
28
28
  import { isCompositeFilterDescriptor } from '@progress/kendo-data-query';
29
29
  import { TreeItemDataTyped } from '@meshmakers/shared-services';
30
30
  import * as i7 from '@progress/kendo-angular-dateinputs';
@@ -5488,6 +5488,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
5488
5488
  }]
5489
5489
  }], ctorParameters: () => [{ type: i1$3.Apollo }] });
5490
5490
 
5491
+ const GetCkTypeAssociationRolesDocumentDto = gql `
5492
+ query getCkTypeAssociationRoles($ckTypeId: String!) {
5493
+ constructionKit {
5494
+ types(rtCkId: $ckTypeId, first: 1) {
5495
+ items {
5496
+ rtCkTypeId
5497
+ associations {
5498
+ in {
5499
+ all {
5500
+ roleId {
5501
+ fullName
5502
+ semanticVersionedFullName
5503
+ }
5504
+ rtRoleId
5505
+ navigationPropertyName
5506
+ multiplicity
5507
+ targetCkTypeId {
5508
+ fullName
5509
+ }
5510
+ rtTargetCkTypeId
5511
+ rtOriginCkTypeId
5512
+ }
5513
+ }
5514
+ out {
5515
+ all {
5516
+ roleId {
5517
+ fullName
5518
+ semanticVersionedFullName
5519
+ }
5520
+ rtRoleId
5521
+ navigationPropertyName
5522
+ multiplicity
5523
+ targetCkTypeId {
5524
+ fullName
5525
+ }
5526
+ rtTargetCkTypeId
5527
+ rtOriginCkTypeId
5528
+ }
5529
+ }
5530
+ }
5531
+ }
5532
+ }
5533
+ }
5534
+ }
5535
+ `;
5536
+ class GetCkTypeAssociationRolesDtoGQL extends i1$3.Query {
5537
+ document = GetCkTypeAssociationRolesDocumentDto;
5538
+ constructor(apollo) {
5539
+ super(apollo);
5540
+ }
5541
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetCkTypeAssociationRolesDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
5542
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetCkTypeAssociationRolesDtoGQL, providedIn: 'root' });
5543
+ }
5544
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetCkTypeAssociationRolesDtoGQL, decorators: [{
5545
+ type: Injectable,
5546
+ args: [{
5547
+ providedIn: 'root'
5548
+ }]
5549
+ }], ctorParameters: () => [{ type: i1$3.Apollo }] });
5550
+
5491
5551
  const GetRuntimeEntityAssociationsByIdDocumentDto = gql `
5492
5552
  query getRuntimeEntityAssociationsById($rtId: OctoObjectId!, $ckTypeId: String!, $direction: GraphDirection!, $after: String, $first: Int, $roleId: String, $relatedRtCkId: RtCkTypeId, $relatedRtId: OctoObjectId) {
5493
5553
  runtime {
@@ -5534,39 +5594,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
5534
5594
  }]
5535
5595
  }], ctorParameters: () => [{ type: i1$3.Apollo }] });
5536
5596
 
5537
- const GetTreeNodesDocumentDto = gql `
5538
- query getTreeNodes($rtId: OctoObjectId!, $ckTypeId: String!, $directRoleId: String!, $directTargetCkTypeId: String!, $indirectRoleId: String!, $indirectTargetCkTypeId: String!) {
5597
+ const GetTreeAssociationTargetsDocumentDto = gql `
5598
+ query getTreeAssociationTargets($rtId: OctoObjectId!, $ckTypeId: String!, $roleId: String!, $targetCkTypeId: String!, $direction: GraphDirection!, $first: Int) {
5539
5599
  runtime {
5540
- runtimeEntities(rtId: $rtId, ckId: $ckTypeId) {
5600
+ runtimeEntities(rtId: $rtId, ckId: $ckTypeId, first: 1) {
5541
5601
  items {
5542
- rtId
5543
- ckTypeId
5544
- attributes(attributeNames: ["name", "description"]) {
5545
- items {
5546
- attributeName
5547
- value
5548
- }
5549
- }
5550
5602
  associations {
5551
- targets(roleId: $directRoleId, ckId: $directTargetCkTypeId, direction: INBOUND) {
5603
+ targets(
5604
+ roleId: $roleId
5605
+ ckId: $targetCkTypeId
5606
+ direction: $direction
5607
+ first: $first
5608
+ ) {
5609
+ totalCount
5552
5610
  items {
5553
5611
  rtId
5554
5612
  ckTypeId
5555
- attributes(attributeNames: ["name", "description"]) {
5613
+ rtWellKnownName
5614
+ attributes(
5615
+ attributeNames: ["name", "displayName", "description"]
5616
+ resolveEnumValuesToNames: true
5617
+ ) {
5556
5618
  items {
5557
5619
  attributeName
5558
5620
  value
5559
5621
  }
5560
5622
  }
5561
- associations {
5562
- targets(
5563
- roleId: $indirectRoleId
5564
- ckId: $indirectTargetCkTypeId
5565
- direction: INBOUND
5566
- ) {
5567
- totalCount
5568
- }
5569
- }
5570
5623
  }
5571
5624
  }
5572
5625
  }
@@ -5575,15 +5628,15 @@ const GetTreeNodesDocumentDto = gql `
5575
5628
  }
5576
5629
  }
5577
5630
  `;
5578
- class GetTreeNodesDtoGQL extends i1$3.Query {
5579
- document = GetTreeNodesDocumentDto;
5631
+ class GetTreeAssociationTargetsDtoGQL extends i1$3.Query {
5632
+ document = GetTreeAssociationTargetsDocumentDto;
5580
5633
  constructor(apollo) {
5581
5634
  super(apollo);
5582
5635
  }
5583
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetTreeNodesDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
5584
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetTreeNodesDtoGQL, providedIn: 'root' });
5636
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetTreeAssociationTargetsDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
5637
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetTreeAssociationTargetsDtoGQL, providedIn: 'root' });
5585
5638
  }
5586
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetTreeNodesDtoGQL, decorators: [{
5639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetTreeAssociationTargetsDtoGQL, decorators: [{
5587
5640
  type: Injectable,
5588
5641
  args: [{
5589
5642
  providedIn: 'root'
@@ -5963,6 +6016,310 @@ const article = {
5963
6016
  viewBox: '0 -960 960 960'
5964
6017
  };
5965
6018
 
6019
+ /** Runtime CK type id of the per-tenant tree navigation configuration singleton. */
6020
+ const CONFIG_CK_TYPE_ID = 'System.UI/TreeNavigationConfiguration';
6021
+ /** rtWellKnownName of the singleton instance. */
6022
+ const CONFIG_WELL_KNOWN_NAME = 'TreeNavigation';
6023
+ /** Matches every source CK type. */
6024
+ const WILDCARD = '*';
6025
+ const CONFIG_TYPE_EXISTS_QUERY = gql `
6026
+ query treeNavigationConfigTypeExists {
6027
+ constructionKit {
6028
+ types(rtCkId: "System.UI/TreeNavigationConfiguration", first: 1) {
6029
+ items {
6030
+ rtCkTypeId
6031
+ }
6032
+ }
6033
+ }
6034
+ }
6035
+ `;
6036
+ const CONFIG_QUERY = gql `
6037
+ query getTreeNavigationConfiguration {
6038
+ runtime {
6039
+ systemUITreeNavigationConfiguration(
6040
+ first: 1
6041
+ fieldFilter: [
6042
+ {
6043
+ attributePath: "rtWellKnownName"
6044
+ operator: EQUALS
6045
+ comparisonValue: "TreeNavigation"
6046
+ }
6047
+ ]
6048
+ ) {
6049
+ items {
6050
+ rtId
6051
+ roles {
6052
+ sourceCkTypeId
6053
+ roleId
6054
+ visible
6055
+ displayName
6056
+ sortIndex
6057
+ grouped
6058
+ icon
6059
+ }
6060
+ }
6061
+ }
6062
+ }
6063
+ }
6064
+ `;
6065
+ const ROLE_SUGGESTIONS_QUERY = gql `
6066
+ query treeNavigationRoleSuggestions($ckTypeId: String!) {
6067
+ constructionKit {
6068
+ types(rtCkId: $ckTypeId, first: 1) {
6069
+ items {
6070
+ associations {
6071
+ in {
6072
+ all {
6073
+ rtRoleId
6074
+ navigationPropertyName
6075
+ }
6076
+ }
6077
+ }
6078
+ }
6079
+ }
6080
+ }
6081
+ }
6082
+ `;
6083
+ const CREATE_CONFIG_MUTATION = gql `
6084
+ mutation createTreeNavigationConfiguration(
6085
+ $entities: [SystemUITreeNavigationConfigurationInput!]!
6086
+ ) {
6087
+ runtime {
6088
+ systemUITreeNavigationConfigurations {
6089
+ create(entities: $entities) {
6090
+ rtId
6091
+ }
6092
+ }
6093
+ }
6094
+ }
6095
+ `;
6096
+ const UPDATE_CONFIG_MUTATION = gql `
6097
+ mutation updateTreeNavigationConfiguration(
6098
+ $entities: [SystemUITreeNavigationConfigurationInputUpdate!]!
6099
+ ) {
6100
+ runtime {
6101
+ systemUITreeNavigationConfigurations {
6102
+ update(entities: $entities) {
6103
+ rtId
6104
+ }
6105
+ }
6106
+ }
6107
+ }
6108
+ `;
6109
+ /**
6110
+ * Loads the optional per-tenant `System.UI/TreeNavigationConfiguration` singleton
6111
+ * and resolves per-association overrides for the entity trees.
6112
+ *
6113
+ * Design notes:
6114
+ * - The config entity is OPTIONAL. When the CK type is not installed on the
6115
+ * tenant (System.UI < 2.2.0) or no instance exists, every lookup returns
6116
+ * undefined and the trees fall back to pure auto-discovery.
6117
+ * - The singleton field (`systemUITreeNavigationConfiguration`) only exists in
6118
+ * the tenant schema when the CK type is installed, so querying it blindly
6119
+ * would raise a GraphQL validation error (and a user-facing toast). We first
6120
+ * probe the CK schema with the always-valid `constructionKit.types` query and
6121
+ * only run the singleton query when the type is present.
6122
+ * - Uses inline `gql` (not codegen) so the feature is decoupled from a schema
6123
+ * re-introspection that includes the new CK type.
6124
+ */
6125
+ class TreeNavigationConfigService {
6126
+ apollo = inject(Apollo);
6127
+ /** key `${sourceCkTypeId}::${roleId}` -> override; cached for the session. */
6128
+ overridesPromise;
6129
+ /**
6130
+ * Resolves the override for one (source type, role) pair, preferring an exact
6131
+ * source-type match over a wildcard (`*`) rule. Returns undefined when nothing
6132
+ * is configured.
6133
+ */
6134
+ async resolve(sourceCkTypeId, roleId) {
6135
+ const overrides = await this.getOverrides();
6136
+ return (overrides.get(`${sourceCkTypeId}::${roleId}`) ??
6137
+ overrides.get(`${WILDCARD}::${roleId}`));
6138
+ }
6139
+ /** Forces a reload on next access (e.g. after a tenant switch). */
6140
+ reset() {
6141
+ this.overridesPromise = undefined;
6142
+ }
6143
+ /**
6144
+ * Returns the inbound association roles declared on a CK type, for the role
6145
+ * autocomplete in the settings editor. Returns `{ roleId, label }` where the
6146
+ * label is the friendly inbound name plus the role id. Empty for `*` or an
6147
+ * unknown type (orphan roles can still be typed as custom values).
6148
+ */
6149
+ async getRoleSuggestions(ckTypeId) {
6150
+ if (!ckTypeId || ckTypeId === WILDCARD) {
6151
+ return [];
6152
+ }
6153
+ try {
6154
+ const result = await firstValueFrom(this.apollo.query({
6155
+ query: ROLE_SUGGESTIONS_QUERY,
6156
+ variables: { ckTypeId },
6157
+ fetchPolicy: 'network-only',
6158
+ }));
6159
+ const all = result.data?.constructionKit?.types?.items?.[0]?.associations?.in
6160
+ ?.all ?? [];
6161
+ const byRole = new Map();
6162
+ for (const role of all) {
6163
+ const roleId = String(role?.rtRoleId ?? '');
6164
+ if (!roleId || byRole.has(roleId)) {
6165
+ continue;
6166
+ }
6167
+ const nav = role?.navigationPropertyName ?? '';
6168
+ byRole.set(roleId, nav ? `${nav} (${roleId})` : roleId);
6169
+ }
6170
+ return [...byRole.entries()].map(([roleId, label]) => ({ roleId, label }));
6171
+ }
6172
+ catch (error) {
6173
+ console.error('Error loading role suggestions for', ckTypeId, error);
6174
+ return [];
6175
+ }
6176
+ }
6177
+ getOverrides() {
6178
+ if (!this.overridesPromise) {
6179
+ this.overridesPromise = this.load().catch((error) => {
6180
+ console.error('Error loading tree navigation configuration', error);
6181
+ // Drop the cache so a later expand can retry, fall back to no overrides.
6182
+ this.overridesPromise = undefined;
6183
+ return new Map();
6184
+ });
6185
+ }
6186
+ return this.overridesPromise;
6187
+ }
6188
+ async load() {
6189
+ const map = new Map();
6190
+ const { rawRoles } = await this.fetchSingleton();
6191
+ for (const raw of rawRoles) {
6192
+ if (!raw?.sourceCkTypeId || !raw?.roleId) {
6193
+ continue;
6194
+ }
6195
+ map.set(`${raw.sourceCkTypeId}::${raw.roleId}`, {
6196
+ visible: raw.visible ?? undefined,
6197
+ displayName: raw.displayName ?? undefined,
6198
+ sortIndex: raw.sortIndex ?? undefined,
6199
+ grouped: raw.grouped ?? undefined,
6200
+ icon: raw.icon ?? undefined,
6201
+ });
6202
+ }
6203
+ return map;
6204
+ }
6205
+ /**
6206
+ * Loads the full configuration for editing (settings page). Returns whether
6207
+ * the CK type is installed (so the page can show a clear "upgrade System.UI"
6208
+ * hint), the singleton rtId (null when not created yet), and the role rules.
6209
+ */
6210
+ async loadConfig() {
6211
+ const { typePresent, rtId, rawRoles } = await this.fetchSingleton();
6212
+ const roles = [];
6213
+ for (const raw of rawRoles) {
6214
+ if (!raw?.sourceCkTypeId || !raw?.roleId) {
6215
+ continue;
6216
+ }
6217
+ roles.push({
6218
+ sourceCkTypeId: raw.sourceCkTypeId,
6219
+ roleId: raw.roleId,
6220
+ visible: raw.visible ?? undefined,
6221
+ displayName: raw.displayName ?? undefined,
6222
+ sortIndex: raw.sortIndex ?? undefined,
6223
+ grouped: raw.grouped ?? undefined,
6224
+ icon: raw.icon ?? undefined,
6225
+ });
6226
+ }
6227
+ return { typePresent, rtId, roles };
6228
+ }
6229
+ /**
6230
+ * Creates or updates the singleton with the given rules, then invalidates the
6231
+ * resolve cache so the trees pick up the change on the next expand. Returns the
6232
+ * singleton rtId.
6233
+ */
6234
+ async saveConfig(rtId, roles) {
6235
+ const cleanRoles = roles
6236
+ .filter((r) => r.sourceCkTypeId && r.roleId)
6237
+ .map((r) => this.toRoleInput(r));
6238
+ let savedRtId;
6239
+ if (rtId) {
6240
+ const result = await firstValueFrom(this.apollo.mutate({
6241
+ mutation: UPDATE_CONFIG_MUTATION,
6242
+ variables: { entities: [{ rtId, item: { roles: cleanRoles } }] },
6243
+ fetchPolicy: 'no-cache',
6244
+ }));
6245
+ savedRtId =
6246
+ result.data?.runtime?.systemUITreeNavigationConfigurations?.update?.[0]
6247
+ ?.rtId ?? rtId;
6248
+ }
6249
+ else {
6250
+ const result = await firstValueFrom(this.apollo.mutate({
6251
+ mutation: CREATE_CONFIG_MUTATION,
6252
+ variables: {
6253
+ entities: [
6254
+ {
6255
+ rtWellKnownName: CONFIG_WELL_KNOWN_NAME,
6256
+ name: 'Tree Navigation',
6257
+ roles: cleanRoles,
6258
+ },
6259
+ ],
6260
+ },
6261
+ fetchPolicy: 'no-cache',
6262
+ }));
6263
+ const created = result.data?.runtime?.systemUITreeNavigationConfigurations?.create?.[0]
6264
+ ?.rtId;
6265
+ if (!created) {
6266
+ throw new Error('createTreeNavigationConfiguration returned no entity');
6267
+ }
6268
+ savedRtId = created;
6269
+ }
6270
+ this.reset();
6271
+ return savedRtId;
6272
+ }
6273
+ /** Drops undefined fields so the record-array input only carries set values. */
6274
+ toRoleInput(role) {
6275
+ const input = {
6276
+ sourceCkTypeId: role.sourceCkTypeId,
6277
+ roleId: role.roleId,
6278
+ };
6279
+ if (role.visible !== undefined)
6280
+ input['visible'] = role.visible;
6281
+ if (role.displayName !== undefined && role.displayName !== '') {
6282
+ input['displayName'] = role.displayName;
6283
+ }
6284
+ if (role.sortIndex !== undefined && role.sortIndex !== null) {
6285
+ input['sortIndex'] = role.sortIndex;
6286
+ }
6287
+ if (role.grouped !== undefined)
6288
+ input['grouped'] = role.grouped;
6289
+ if (role.icon !== undefined && role.icon !== '')
6290
+ input['icon'] = role.icon;
6291
+ return input;
6292
+ }
6293
+ /** Probes the CK schema and (when present) loads the singleton's raw roles. */
6294
+ async fetchSingleton() {
6295
+ const exists = await firstValueFrom(this.apollo.query({ query: CONFIG_TYPE_EXISTS_QUERY, fetchPolicy: 'network-only' }));
6296
+ const typePresent = (exists.data?.constructionKit?.types?.items?.length ?? 0) > 0;
6297
+ if (!typePresent) {
6298
+ return { typePresent: false, rtId: null, rawRoles: [] };
6299
+ }
6300
+ const result = await firstValueFrom(this.apollo.query({ query: CONFIG_QUERY, fetchPolicy: 'network-only' }));
6301
+ const item = result.data?.runtime?.systemUITreeNavigationConfiguration?.items?.[0];
6302
+ return {
6303
+ typePresent: true,
6304
+ rtId: item?.rtId ?? null,
6305
+ rawRoles: item?.roles ?? [],
6306
+ };
6307
+ }
6308
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TreeNavigationConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6309
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TreeNavigationConfigService, providedIn: 'root' });
6310
+ }
6311
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: TreeNavigationConfigService, decorators: [{
6312
+ type: Injectable,
6313
+ args: [{
6314
+ providedIn: 'root',
6315
+ }]
6316
+ }] });
6317
+ const TREE_NAVIGATION_CONFIG_CONSTANTS = {
6318
+ CONFIG_CK_TYPE_ID,
6319
+ CONFIG_WELL_KNOWN_NAME,
6320
+ WILDCARD,
6321
+ };
6322
+
5966
6323
  /**
5967
6324
  * Performs helpful Octomesh Types operations, like checks, comparisons etc.
5968
6325
  */
@@ -5988,9 +6345,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
5988
6345
  }]
5989
6346
  }] });
5990
6347
 
6348
+ /** Well-known role id of the hierarchical parent-child association. */
6349
+ const PARENT_CHILD_ROLE_ID = 'System/ParentChild';
6350
+ /**
6351
+ * Target CK types that cannot be navigated in the tree. `System/Entity` is the
6352
+ * universal abstract base type and has no defining collection root, so the
6353
+ * generic `System/Related` association (target `System/Entity`, present as an
6354
+ * inbound role on every type) makes `targets(ckId: "System/Entity")` throw
6355
+ * server-side ("has no defining collection root"). Skipping it here keeps the
6356
+ * tree from firing a guaranteed-failing query for every entity.
6357
+ */
6358
+ const NON_NAVIGABLE_TARGET_CK_TYPES = new Set(['System/Entity']);
5991
6359
  class RuntimeBrowserDataSource extends OctoGraphQlHierarchyDataSource {
5992
6360
  getTreesDtoGQL = inject(GetTreesDtoGQL);
5993
- getTreeNodesDtoGQL = inject(GetTreeNodesDtoGQL);
6361
+ getCkTypeAssociationRolesDtoGQL = inject(GetCkTypeAssociationRolesDtoGQL);
6362
+ getTreeAssociationTargetsDtoGQL = inject(GetTreeAssociationTargetsDtoGQL);
5994
6363
  getCkModelsGQL = inject(GetCkModelsDtoGQL);
5995
6364
  getCkTypesGQL = inject(GetCkTypesDtoGQL);
5996
6365
  getCkModelByIdDtoGQL = inject(GetCkModelByIdDtoGQL);
@@ -5999,6 +6368,7 @@ class RuntimeBrowserDataSource extends OctoGraphQlHierarchyDataSource {
5999
6368
  updateRuntimeEntitiesDtoGQL = inject(UpdateRuntimeEntitiesDtoGQL);
6000
6369
  updateTreeNodesDtoGQL = inject(UpdateTreeNodesDtoGQL);
6001
6370
  typeHelperService = inject(TypeHelperService);
6371
+ treeNavConfig = inject(TreeNavigationConfigService);
6002
6372
  isCkModelsRoot(item) {
6003
6373
  return !!item && 'isCkModelsRoot' in item;
6004
6374
  }
@@ -6008,20 +6378,16 @@ class RuntimeBrowserDataSource extends OctoGraphQlHierarchyDataSource {
6008
6378
  isCkType(item) {
6009
6379
  return !!item && 'ckTypeId' in item && !('rtId' in item) && !('id' in item);
6010
6380
  }
6011
- // Define metadata for different entity types and their hierarchical relationships
6012
- static levelMetaData = [
6013
- new LevelMetaData('Basic/Tree', [new RtAssociationMetaData('System/ParentChild', 'Basic/TreeNode')], [
6014
- new RtAssociationMetaData('System/ParentChild', 'Basic/TreeNode'),
6015
- new RtAssociationMetaData('Basic/RelatedClassification', 'Basic/Asset'),
6016
- ]),
6017
- new LevelMetaData('*', [
6018
- new RtAssociationMetaData('System/ParentChild', 'Basic/TreeNode'),
6019
- new RtAssociationMetaData('Basic/RelatedClassification', 'Basic/Asset'),
6020
- ], [
6021
- new RtAssociationMetaData('System/ParentChild', 'Basic/TreeNode'),
6022
- new RtAssociationMetaData('Basic/RelatedClassification', 'Basic/Asset'),
6023
- ]),
6024
- ];
6381
+ isAssociationGroup(item) {
6382
+ return !!item && 'isAssociationGroup' in item;
6383
+ }
6384
+ /**
6385
+ * Cache of inbound association roles per CK type id. Discovered lazily from
6386
+ * the CK schema and reused across tree expansions (and to decide whether a
6387
+ * child entity node is expandable). Lives on the instance because the tree is
6388
+ * created fresh per browser/picker mount.
6389
+ */
6390
+ inboundRolesCache = new Map();
6025
6391
  // Define visual metadata for different entity types
6026
6392
  static ckTypeMetaData = [
6027
6393
  new CkTypeMetaData('Basic/Tree', 'Tree', 'Tree Structure', folderMoreIcon),
@@ -6043,92 +6409,287 @@ class RuntimeBrowserDataSource extends OctoGraphQlHierarchyDataSource {
6043
6409
  if (this.isCkType(item.item)) {
6044
6410
  return [];
6045
6411
  }
6412
+ // Handle association group node - lazily load its target entities
6413
+ if (this.isAssociationGroup(item.item)) {
6414
+ const group = item.item;
6415
+ const targets = await this.fetchAssociationTargets(group.parentRtId, group.parentCkTypeId, group.roleId, group.targetCkTypeId, group.direction);
6416
+ return this.buildEntityTreeItems(targets);
6417
+ }
6046
6418
  // Handle regular runtime entity
6047
6419
  const rtEntity = item.item;
6048
6420
  if (!rtEntity.rtId || !rtEntity.ckTypeId) {
6049
6421
  return [];
6050
6422
  }
6051
- // Find metadata for the current item type
6052
- let metaData = RuntimeBrowserDataSource.levelMetaData.find((x) => x.ckTypeId === rtEntity.ckTypeId);
6053
- if (!metaData) {
6054
- metaData = RuntimeBrowserDataSource.levelMetaData.find((x) => x.ckTypeId === '*');
6423
+ // Discover the inbound association roles from the entity's ACTUAL inbound
6424
+ // edges (associations.definitions), not the CK type schema. This mirrors the
6425
+ // entity detail "Associations" tab and also surfaces roles that exist as
6426
+ // runtime edges but are no longer declared on the type in the installed CK
6427
+ // model (orphan roles after model evolution). Each group carries its concrete
6428
+ // origin CK type (the ckId used to load its targets) and an exact count.
6429
+ const roleGroups = await this.discoverEntityInboundRoleGroups(rtEntity.rtId, rtEntity.ckTypeId);
6430
+ // Apply the optional per-tenant TreeNavigationConfiguration overrides on top
6431
+ // of auto-discovery: hide (visible), relabel (displayName), reorder
6432
+ // (sortIndex), flatten vs group (grouped), icon. Defaults reproduce Phase 1:
6433
+ // System/ParentChild flat, every other role grouped.
6434
+ const annotated = await Promise.all(roleGroups.map(async (group) => {
6435
+ const override = await this.treeNavConfig.resolve(rtEntity.ckTypeId, group.roleId);
6436
+ return {
6437
+ group,
6438
+ visible: override?.visible !== false,
6439
+ grouped: override?.grouped ?? group.roleId !== PARENT_CHILD_ROLE_ID,
6440
+ displayName: override?.displayName,
6441
+ sortIndex: override?.sortIndex,
6442
+ icon: override?.icon,
6443
+ };
6444
+ }));
6445
+ const visibleRoles = annotated.filter((a) => a.visible);
6446
+ const result = [];
6447
+ // 1. Flattened roles (default: System/ParentChild) — their targets appear
6448
+ // directly under the node to preserve the familiar hierarchy navigation.
6449
+ const flattenedTargetLists = await Promise.all(visibleRoles
6450
+ .filter((a) => !a.grouped)
6451
+ .map((a) => this.fetchAssociationTargets(rtEntity.rtId, rtEntity.ckTypeId, a.group.roleId, a.group.targetCkTypeId, GraphDirectionDto.InboundDto)));
6452
+ result.push(...(await this.buildEntityTreeItems(flattenedTargetLists.flat())));
6453
+ // 2. Grouped roles become expandable group nodes (counts already known from
6454
+ // the discovered edges). Ordered by configured sortIndex.
6455
+ const groupNodes = visibleRoles
6456
+ .filter((a) => a.grouped && a.group.count > 0)
6457
+ .sort((x, y) => this.compareGroupOrder(x, y));
6458
+ for (const a of groupNodes) {
6459
+ const group = a.group;
6460
+ const groupNode = {
6461
+ isAssociationGroup: true,
6462
+ parentRtId: rtEntity.rtId,
6463
+ parentCkTypeId: rtEntity.ckTypeId,
6464
+ roleId: group.roleId,
6465
+ targetCkTypeId: group.targetCkTypeId,
6466
+ direction: GraphDirectionDto.InboundDto,
6467
+ };
6468
+ const label = `${a.displayName ?? group.navigationPropertyName} (${group.count})`;
6469
+ result.push(new TreeItemDataTyped(this.buildGroupNodeId(rtEntity.rtId, rtEntity.ckTypeId, group), label, `${group.roleId} → ${group.targetCkTypeId}`, groupNode, this.resolveGroupIcon(a.icon), true));
6470
+ }
6471
+ return result;
6472
+ }
6473
+ /**
6474
+ * Discovers the navigable inbound role groups of an entity from its ACTUAL
6475
+ * inbound edges (associations.definitions), grouped by (roleId, origin CK
6476
+ * type) with exact counts. Labels are enriched from the CK type schema
6477
+ * (friendly inbound navigation property name) when the role is declared on the
6478
+ * type, and otherwise derived from the role id (so orphan roles still get a
6479
+ * readable label).
6480
+ */
6481
+ async discoverEntityInboundRoleGroups(rtId, ckTypeId) {
6482
+ let definitions = [];
6483
+ try {
6484
+ const response = await firstValueFrom(this.getRuntimeEntityAssociationsByIdDtoGQL.fetch({
6485
+ variables: {
6486
+ rtId,
6487
+ ckTypeId,
6488
+ direction: GraphDirectionDto.InboundDto,
6489
+ first: 2000,
6490
+ },
6491
+ fetchPolicy: 'network-only',
6492
+ }));
6493
+ definitions =
6494
+ response.data?.runtime?.runtimeEntities?.items?.[0]?.associations
6495
+ ?.definitions?.items ?? [];
6055
6496
  }
6056
- if (!metaData) {
6497
+ catch (error) {
6498
+ console.error('Error discovering inbound association edges', { ckTypeId, rtId }, error);
6057
6499
  return [];
6058
6500
  }
6059
- const mergedResultsMap = {};
6060
- // Fetch children based on direct and indirect associations
6061
- for (const directRole of metaData.directRoles) {
6062
- const rtEntitiesOrigins = new Array();
6063
- for (const indirectRole of metaData.indirectRoles) {
6064
- try {
6065
- const result = await firstValueFrom(this.getTreeNodesDtoGQL
6066
- .fetch({
6067
- variables: {
6068
- rtId: rtEntity.rtId,
6069
- ckTypeId: rtEntity.ckTypeId,
6070
- directRoleId: directRole.roleId,
6071
- directTargetCkTypeId: directRole.ckTypeId,
6072
- indirectRoleId: indirectRole.roleId,
6073
- indirectTargetCkTypeId: indirectRole.ckTypeId,
6074
- },
6075
- })
6076
- .pipe(map((r) => r.data?.runtime?.runtimeEntities?.items?.at(0))));
6077
- if (result) {
6078
- rtEntitiesOrigins.push(result);
6079
- }
6080
- }
6081
- catch (error) {
6082
- console.error('Error fetching tree nodes:', error);
6083
- }
6501
+ // Count edges per role and remember a representative concrete origin type
6502
+ // (used as a fallback ckId for orphan roles not declared on the type).
6503
+ const edgeCount = new Map();
6504
+ const edgeOrigin = new Map();
6505
+ for (const def of definitions) {
6506
+ const roleId = String(def?.ckAssociationRoleId ?? '');
6507
+ const origin = String(def?.originCkTypeId ?? '');
6508
+ if (!roleId || !origin || NON_NAVIGABLE_TARGET_CK_TYPES.has(origin)) {
6509
+ continue;
6510
+ }
6511
+ edgeCount.set(roleId, (edgeCount.get(roleId) ?? 0) + 1);
6512
+ if (!edgeOrigin.has(roleId)) {
6513
+ edgeOrigin.set(roleId, origin);
6514
+ }
6515
+ }
6516
+ // Declared roles from the CK type schema give the friendly inbound name and,
6517
+ // crucially, the origin BASE type — using it as the ckId aggregates all
6518
+ // concrete subtypes into a single group (e.g. one "Sensoren (5)" instead of
6519
+ // one group per concrete sensor type).
6520
+ const schemaRoles = await this.getInboundRoles(ckTypeId);
6521
+ const schemaByRole = new Map();
6522
+ for (const r of schemaRoles) {
6523
+ if (!schemaByRole.has(r.roleId)) {
6524
+ schemaByRole.set(r.roleId, {
6525
+ origin: r.targetCkTypeId,
6526
+ nav: r.navigationPropertyName,
6527
+ });
6084
6528
  }
6085
- // Process children and build tree items
6086
- for (const root of rtEntitiesOrigins) {
6087
- if (!root?.associations?.targets?.items) {
6529
+ }
6530
+ // One group per role actually present on the entity. Declared roles use the
6531
+ // schema base type as ckId; orphan roles (edge exists but role not declared
6532
+ // on the type in the installed model, e.g. EnergyIQ/StoreyElements) fall back
6533
+ // to the concrete edge origin type and a derived label.
6534
+ const groups = [];
6535
+ for (const [roleId, count] of edgeCount) {
6536
+ const schema = schemaByRole.get(roleId);
6537
+ groups.push({
6538
+ roleId,
6539
+ targetCkTypeId: schema?.origin ?? edgeOrigin.get(roleId) ?? '',
6540
+ navigationPropertyName: schema?.nav ?? this.deriveRoleLabel(roleId),
6541
+ count,
6542
+ });
6543
+ }
6544
+ return groups;
6545
+ }
6546
+ /** Readable fallback label for a role id without a schema navigation name. */
6547
+ deriveRoleLabel(roleId) {
6548
+ const slash = roleId.lastIndexOf('/');
6549
+ return slash >= 0 ? roleId.slice(slash + 1) : roleId;
6550
+ }
6551
+ /**
6552
+ * Orders group nodes by configured sortIndex (ascending, unconfigured last),
6553
+ * then by navigation property name for a stable, readable order.
6554
+ */
6555
+ compareGroupOrder(x, y) {
6556
+ const xi = x.sortIndex ?? Number.MAX_SAFE_INTEGER;
6557
+ const yi = y.sortIndex ?? Number.MAX_SAFE_INTEGER;
6558
+ if (xi !== yi) {
6559
+ return xi - yi;
6560
+ }
6561
+ return x.group.navigationPropertyName.localeCompare(y.group.navigationPropertyName);
6562
+ }
6563
+ /** Resolves a configured group icon name to an SVG icon (folder by default). */
6564
+ resolveGroupIcon(name) {
6565
+ switch (name) {
6566
+ case 'file':
6567
+ return fileIcon;
6568
+ case 'gear':
6569
+ return gearIcon;
6570
+ case 'database':
6571
+ return storage;
6572
+ case 'code':
6573
+ return code;
6574
+ case 'folder':
6575
+ default:
6576
+ return folderMoreIcon;
6577
+ }
6578
+ }
6579
+ /**
6580
+ * Returns the inbound association roles of a CK type, discovered from the CK
6581
+ * schema and cached per type id for the lifetime of this data source.
6582
+ */
6583
+ getInboundRoles(ckTypeId) {
6584
+ const cached = this.inboundRolesCache.get(ckTypeId);
6585
+ if (cached) {
6586
+ return cached;
6587
+ }
6588
+ const promise = firstValueFrom(this.getCkTypeAssociationRolesDtoGQL.fetch({ variables: { ckTypeId } }))
6589
+ .then((response) => {
6590
+ const all = response.data?.constructionKit?.types?.items?.[0]?.associations?.in
6591
+ ?.all ?? [];
6592
+ const roles = [];
6593
+ for (const role of all) {
6594
+ if (!role) {
6088
6595
  continue;
6089
6596
  }
6090
- for (const child of root.associations.targets.items) {
6091
- if (!child?.rtId || !child?.ckTypeId) {
6092
- continue;
6093
- }
6094
- const rtId = child?.rtId;
6095
- if (!mergedResultsMap[rtId]) {
6096
- // Find or create metadata for this child type
6097
- let childMetaData = RuntimeBrowserDataSource.ckTypeMetaData.find((x) => x.ckTypeId === child?.ckTypeId);
6098
- if (!childMetaData) {
6099
- childMetaData = new CkTypeMetaData(child?.ckTypeId || 'Unknown', child?.ckTypeId || 'Unknown', child?.ckTypeId || 'Unknown', code);
6100
- }
6101
- // Extract display name and description from attributes
6102
- const nameValue = child.attributes?.items?.find((x) => x?.attributeName === 'name')?.value;
6103
- const displayNameValue = child.attributes?.items?.find((x) => x?.attributeName === 'displayName')?.value;
6104
- // Debug logging
6105
- if (typeof nameValue === 'object') {
6106
- console.warn('Child name value is an object:', nameValue);
6107
- }
6108
- const text = (typeof nameValue === 'string'
6109
- ? nameValue
6110
- : typeof nameValue === 'object' && nameValue !== null
6111
- ? JSON.stringify(nameValue)
6112
- : null) ||
6113
- (typeof displayNameValue === 'string'
6114
- ? displayNameValue
6115
- : null) ||
6116
- child.ckTypeId ||
6117
- 'Unknown';
6118
- const descValue = child.attributes?.items?.find((x) => x?.attributeName === 'description')?.value;
6119
- const tooltip = (typeof descValue === 'string' ? descValue : null) ||
6120
- `${child.ckTypeId} - ${child.rtId}`;
6121
- mergedResultsMap[rtId] = new TreeItemDataTyped(rtId, text, tooltip, child, childMetaData.svgIcon, (child?.associations?.targets?.totalCount ?? 0) > 0);
6122
- }
6123
- else {
6124
- // Update expandable status if object already exists
6125
- mergedResultsMap[rtId].expandable ||=
6126
- (child?.associations?.targets?.totalCount ?? 0) > 0;
6127
- }
6597
+ // Use the RUNTIME ids from the backend, never the versioned fullName.
6598
+ // For an INBOUND role this entity is the association's TARGET side, so the
6599
+ // related entities to navigate to are on the ORIGIN side: query
6600
+ // targets(direction: INBOUND, ckId: rtOriginCkTypeId). rtTargetCkTypeId
6601
+ // here is this entity's own (target) type and would return nothing.
6602
+ // The runtime form must come from the backend (rtOriginCkTypeId) — it
6603
+ // follows a resolution logic that simply stripping the version does not.
6604
+ const targetCkTypeId = String(role.rtOriginCkTypeId ?? '');
6605
+ if (!targetCkTypeId || NON_NAVIGABLE_TARGET_CK_TYPES.has(targetCkTypeId)) {
6606
+ continue;
6128
6607
  }
6608
+ roles.push({
6609
+ roleId: String(role.rtRoleId ?? ''),
6610
+ navigationPropertyName: role.navigationPropertyName,
6611
+ targetCkTypeId,
6612
+ multiplicity: role.multiplicity,
6613
+ });
6614
+ }
6615
+ return roles;
6616
+ })
6617
+ .catch((error) => {
6618
+ console.error('Error fetching association roles for type', ckTypeId, error);
6619
+ // Drop the failed promise from the cache so a later expand can retry.
6620
+ this.inboundRolesCache.delete(ckTypeId);
6621
+ return [];
6622
+ });
6623
+ this.inboundRolesCache.set(ckTypeId, promise);
6624
+ return promise;
6625
+ }
6626
+ /** Loads the target entities reachable from an entity through one role. */
6627
+ async fetchAssociationTargets(rtId, ckTypeId, roleId, targetCkTypeId, direction) {
6628
+ try {
6629
+ const response = await firstValueFrom(this.getTreeAssociationTargetsDtoGQL.fetch({
6630
+ variables: { rtId, ckTypeId, roleId, targetCkTypeId, direction },
6631
+ }));
6632
+ const items = response.data?.runtime?.runtimeEntities?.items?.[0]?.associations
6633
+ ?.targets?.items ?? [];
6634
+ return items.filter((i) => !!i);
6635
+ }
6636
+ catch (error) {
6637
+ console.error('Error fetching association targets', { ckTypeId, roleId, targetCkTypeId }, error);
6638
+ return [];
6639
+ }
6640
+ }
6641
+ /**
6642
+ * Builds tree items for runtime entities, de-duplicating by rtId and marking
6643
+ * an entity expandable when its CK type defines at least one inbound
6644
+ * association role.
6645
+ */
6646
+ async buildEntityTreeItems(entities) {
6647
+ const unique = new Map();
6648
+ for (const entity of entities) {
6649
+ if (entity?.rtId && entity?.ckTypeId && !unique.has(entity.rtId)) {
6650
+ unique.set(entity.rtId, entity);
6129
6651
  }
6130
6652
  }
6131
- return Object.values(mergedResultsMap);
6653
+ // Warm the role cache for every distinct child type in parallel so the
6654
+ // expandable flag can be resolved without a per-entity round trip.
6655
+ const distinctTypes = [
6656
+ ...new Set([...unique.values()].map((e) => e.ckTypeId)),
6657
+ ];
6658
+ await Promise.all(distinctTypes.map((t) => this.getInboundRoles(t)));
6659
+ const result = [];
6660
+ for (const entity of unique.values()) {
6661
+ const roles = await this.getInboundRoles(entity.ckTypeId);
6662
+ result.push(new TreeItemDataTyped(entity.rtId, this.extractDisplayName(entity), this.extractTooltip(entity), entity, this.resolveIcon(entity.ckTypeId), roles.length > 0));
6663
+ }
6664
+ return result;
6665
+ }
6666
+ /** Stable tree-node id for an association group node. */
6667
+ buildGroupNodeId(parentRtId, parentCkTypeId, role) {
6668
+ return `assoc:${parentCkTypeId}@${parentRtId}:${role.roleId}:${role.targetCkTypeId}`;
6669
+ }
6670
+ /** Resolves the display label of an entity from its name/displayName attributes. */
6671
+ extractDisplayName(entity) {
6672
+ const nameValue = entity.attributes?.items?.find((x) => x?.attributeName === 'name')?.value;
6673
+ const displayNameValue = entity.attributes?.items?.find((x) => x?.attributeName === 'displayName')?.value;
6674
+ return ((typeof nameValue === 'string'
6675
+ ? nameValue
6676
+ : typeof nameValue === 'object' && nameValue !== null
6677
+ ? JSON.stringify(nameValue)
6678
+ : null) ||
6679
+ (typeof displayNameValue === 'string' ? displayNameValue : null) ||
6680
+ entity.rtWellKnownName ||
6681
+ entity.ckTypeId ||
6682
+ 'Unknown');
6683
+ }
6684
+ /** Resolves the tooltip of an entity from its description attribute. */
6685
+ extractTooltip(entity) {
6686
+ const descValue = entity.attributes?.items?.find((x) => x?.attributeName === 'description')?.value;
6687
+ return ((typeof descValue === 'string' ? descValue : null) ||
6688
+ `${entity.ckTypeId} - ${entity.rtId}`);
6689
+ }
6690
+ /** Resolves the icon for a CK type, falling back to a generic entity icon. */
6691
+ resolveIcon(ckTypeId) {
6692
+ return (RuntimeBrowserDataSource.ckTypeMetaData.find((x) => x.ckTypeId === ckTypeId)?.svgIcon ?? code);
6132
6693
  }
6133
6694
  async fetchRootNodes() {
6134
6695
  try {
@@ -9907,64 +10468,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
9907
10468
  type: Input
9908
10469
  }] } });
9909
10470
 
9910
- const GetCkTypeAssociationRolesDocumentDto = gql `
9911
- query getCkTypeAssociationRoles($ckTypeId: String!) {
9912
- constructionKit {
9913
- types(rtCkId: $ckTypeId, first: 1) {
9914
- items {
9915
- rtCkTypeId
9916
- associations {
9917
- in {
9918
- all {
9919
- roleId {
9920
- fullName
9921
- semanticVersionedFullName
9922
- }
9923
- rtRoleId
9924
- navigationPropertyName
9925
- multiplicity
9926
- targetCkTypeId {
9927
- fullName
9928
- }
9929
- rtTargetCkTypeId
9930
- }
9931
- }
9932
- out {
9933
- all {
9934
- roleId {
9935
- fullName
9936
- semanticVersionedFullName
9937
- }
9938
- rtRoleId
9939
- navigationPropertyName
9940
- multiplicity
9941
- targetCkTypeId {
9942
- fullName
9943
- }
9944
- rtTargetCkTypeId
9945
- }
9946
- }
9947
- }
9948
- }
9949
- }
9950
- }
9951
- }
9952
- `;
9953
- class GetCkTypeAssociationRolesDtoGQL extends i1$3.Query {
9954
- document = GetCkTypeAssociationRolesDocumentDto;
9955
- constructor(apollo) {
9956
- super(apollo);
9957
- }
9958
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetCkTypeAssociationRolesDtoGQL, deps: [{ token: i1$3.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
9959
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetCkTypeAssociationRolesDtoGQL, providedIn: 'root' });
9960
- }
9961
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: GetCkTypeAssociationRolesDtoGQL, decorators: [{
9962
- type: Injectable,
9963
- args: [{
9964
- providedIn: 'root'
9965
- }]
9966
- }], ctorParameters: () => [{ type: i1$3.Apollo }] });
9967
-
9968
10471
  /**
9969
10472
  * Validates whether a drag-and-drop move (reparenting) is allowed by the CK model.
9970
10473
  *
@@ -14870,7 +15373,7 @@ class RuntimeBrowserComponent {
14870
15373
  </div>
14871
15374
  </div>
14872
15375
  </div>
14873
- `, isInline: true, styles: [".runtime-browser-container{display:flex;flex-direction:column;height:100%;padding:16px;gap:16px}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:linear-gradient(180deg,var(--octo-mint-30),transparent);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:linear-gradient(180deg,var(--octo-mint-50),var(--octo-mint-20))}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:Roboto,sans-serif;transition:all .2s ease;border-radius:4px}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--octo-mint-10);color:var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:linear-gradient(90deg,var(--octo-mint-20),transparent);color:var(--octo-mint);border-left:3px solid var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected:hover{background:linear-gradient(90deg,var(--octo-mint-25),transparent)}::ng-deep mm-base-tree-detail .toolbar{background:linear-gradient(90deg,var(--octo-mint-05),transparent);border-bottom:1px solid var(--octo-mint-20)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}@media(max-width:1024px){.runtime-browser-container{padding:12px;gap:12px}}@media(max-width:768px){.runtime-browser-container{padding:8px;gap:10px}}\n"], dependencies: [{ kind: "component", type: BaseTreeDetailComponent, selector: "mm-base-tree-detail", inputs: ["treeDataSource", "leftPaneSize", "leftToolbarActions", "rightToolbarActions"], outputs: ["nodeSelected", "nodeDropped"] }, { kind: "component", type: RuntimeBrowserDetailsComponent, selector: "mm-runtime-browser-details", inputs: ["selectedItem", "showDataMapping", "messages", "expressionValidator"], outputs: ["entitySaved"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
15376
+ `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.runtime-browser-container{display:flex;flex-direction:column;height:100%;padding:16px;gap:16px}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:linear-gradient(180deg,var(--octo-mint-30),transparent);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:linear-gradient(180deg,var(--octo-mint-50),var(--octo-mint-20))}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:Roboto,sans-serif;transition:all .2s ease;border-radius:4px}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--octo-mint-10);color:var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:linear-gradient(90deg,var(--octo-mint-20),transparent);color:var(--octo-mint);border-left:3px solid var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected:hover{background:linear-gradient(90deg,var(--octo-mint-25),transparent)}::ng-deep mm-base-tree-detail .toolbar{background:linear-gradient(90deg,var(--octo-mint-05),transparent);border-bottom:1px solid var(--octo-mint-20)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}@media(max-width:1024px){.runtime-browser-container{padding:12px;gap:12px}}@media(max-width:768px){.runtime-browser-container{padding:8px;gap:10px}}\n"], dependencies: [{ kind: "component", type: BaseTreeDetailComponent, selector: "mm-base-tree-detail", inputs: ["treeDataSource", "leftPaneSize", "leftToolbarActions", "rightToolbarActions"], outputs: ["nodeSelected", "nodeDropped"] }, { kind: "component", type: RuntimeBrowserDetailsComponent, selector: "mm-runtime-browser-details", inputs: ["selectedItem", "showDataMapping", "messages", "expressionValidator"], outputs: ["entitySaved"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
14874
15377
  }
14875
15378
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RuntimeBrowserComponent, decorators: [{
14876
15379
  type: Component,
@@ -14936,7 +15439,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
14936
15439
  </div>
14937
15440
  </div>
14938
15441
  </div>
14939
- `, changeDetection: ChangeDetectionStrategy.Eager, styles: [".runtime-browser-container{display:flex;flex-direction:column;height:100%;padding:16px;gap:16px}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:linear-gradient(180deg,var(--octo-mint-30),transparent);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:linear-gradient(180deg,var(--octo-mint-50),var(--octo-mint-20))}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:Roboto,sans-serif;transition:all .2s ease;border-radius:4px}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--octo-mint-10);color:var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:linear-gradient(90deg,var(--octo-mint-20),transparent);color:var(--octo-mint);border-left:3px solid var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected:hover{background:linear-gradient(90deg,var(--octo-mint-25),transparent)}::ng-deep mm-base-tree-detail .toolbar{background:linear-gradient(90deg,var(--octo-mint-05),transparent);border-bottom:1px solid var(--octo-mint-20)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}@media(max-width:1024px){.runtime-browser-container{padding:12px;gap:12px}}@media(max-width:768px){.runtime-browser-container{padding:8px;gap:10px}}\n"] }]
15442
+ `, changeDetection: ChangeDetectionStrategy.Eager, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}.runtime-browser-container{display:flex;flex-direction:column;height:100%;padding:16px;gap:16px}::ng-deep mm-base-tree-detail .k-splitter{background:transparent;border:none}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar{background:linear-gradient(180deg,var(--octo-mint-30),transparent);width:4px!important}::ng-deep mm-base-tree-detail .k-splitter .k-splitbar:hover{background:linear-gradient(180deg,var(--octo-mint-50),var(--octo-mint-20))}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf{font-family:Roboto,sans-serif;transition:all .2s ease;border-radius:4px}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf:hover{background:var(--octo-mint-10);color:var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected{background:linear-gradient(90deg,var(--octo-mint-20),transparent);color:var(--octo-mint);border-left:3px solid var(--octo-mint)}::ng-deep mm-base-tree-detail kendo-treeview .k-treeview-item .k-treeview-leaf.k-selected:hover{background:linear-gradient(90deg,var(--octo-mint-25),transparent)}::ng-deep mm-base-tree-detail .toolbar{background:linear-gradient(90deg,var(--octo-mint-05),transparent);border-bottom:1px solid var(--octo-mint-20)}::ng-deep mm-base-tree-detail .base-tree-detail-container{height:100%;display:flex;flex-direction:column}::ng-deep mm-base-tree-detail .base-tree-detail-container .k-splitter{flex:1;min-height:0}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane{display:flex!important;flex-direction:column!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details{display:flex!important;flex:1!important;min-height:0!important;height:100%!important}::ng-deep mm-base-tree-detail kendo-splitter-pane.detail-pane>mm-runtime-browser-details>.runtime-browser-details{flex:1;display:flex;flex-direction:column;min-height:0}@media(max-width:1024px){.runtime-browser-container{padding:12px;gap:12px}}@media(max-width:768px){.runtime-browser-container{padding:8px;gap:10px}}\n"] }]
14940
15443
  }], propDecorators: { messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: false }] }], showDataMapping: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDataMapping", required: false }] }], expressionValidator: [{ type: i0.Input, args: [{ isSignal: true, alias: "expressionValidator", required: false }] }], treeDetail: [{
14941
15444
  type: ViewChild,
14942
15445
  args: ['treeDetail', { static: false }]
@@ -14951,17 +15454,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
14951
15454
  */
14952
15455
  class RuntimeBrowserOutletComponent {
14953
15456
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RuntimeBrowserOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14954
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.2", type: RuntimeBrowserOutletComponent, isStandalone: true, selector: "mm-runtime-browser-outlet", ngImport: i0, template: `<router-outlet />`, isInline: true, dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
15457
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.2", type: RuntimeBrowserOutletComponent, isStandalone: true, selector: "mm-runtime-browser-outlet", ngImport: i0, template: `<router-outlet />`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
14955
15458
  }
14956
15459
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RuntimeBrowserOutletComponent, decorators: [{
14957
15460
  type: Component,
14958
- args: [{
14959
- selector: 'mm-runtime-browser-outlet',
14960
- standalone: true,
14961
- imports: [RouterOutlet],
14962
- changeDetection: ChangeDetectionStrategy.Eager,
14963
- template: `<router-outlet />`,
14964
- }]
15461
+ args: [{ selector: 'mm-runtime-browser-outlet', standalone: true, imports: [RouterOutlet], changeDetection: ChangeDetectionStrategy.Eager, template: `<router-outlet />`, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}\n"] }]
14965
15462
  }] });
14966
15463
 
14967
15464
  /**
@@ -14982,17 +15479,11 @@ class RuntimeBrowserPageComponent {
14982
15479
  ? this.injectedMessages
14983
15480
  : DEFAULT_RUNTIME_BROWSER_MESSAGES;
14984
15481
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RuntimeBrowserPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14985
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.2", type: RuntimeBrowserPageComponent, isStandalone: true, selector: "mm-runtime-browser-page", ngImport: i0, template: `<mm-runtime-browser [messages]="messages" />`, isInline: true, dependencies: [{ kind: "component", type: RuntimeBrowserComponent, selector: "mm-runtime-browser", inputs: ["messages", "showDataMapping", "expressionValidator"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
15482
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.2", type: RuntimeBrowserPageComponent, isStandalone: true, selector: "mm-runtime-browser-page", ngImport: i0, template: `<mm-runtime-browser [messages]="messages" />`, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}\n"], dependencies: [{ kind: "component", type: RuntimeBrowserComponent, selector: "mm-runtime-browser", inputs: ["messages", "showDataMapping", "expressionValidator"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
14986
15483
  }
14987
15484
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: RuntimeBrowserPageComponent, decorators: [{
14988
15485
  type: Component,
14989
- args: [{
14990
- selector: 'mm-runtime-browser-page',
14991
- standalone: true,
14992
- imports: [RuntimeBrowserComponent],
14993
- changeDetection: ChangeDetectionStrategy.Eager,
14994
- template: `<mm-runtime-browser [messages]="messages" />`,
14995
- }]
15486
+ args: [{ selector: 'mm-runtime-browser-page', standalone: true, imports: [RuntimeBrowserComponent], changeDetection: ChangeDetectionStrategy.Eager, template: `<mm-runtime-browser [messages]="messages" />`, styles: [":host{display:flex;flex-direction:column;height:100%;width:100%}\n"] }]
14996
15487
  }] });
14997
15488
 
14998
15489
  /**
@@ -18018,5 +18509,5 @@ function provideOctoUi() {
18018
18509
  * Generated bundle index. Do not edit.
18019
18510
  */
18020
18511
 
18021
- export { AssociationValidationService, AttributeSelectorDialogComponent, AttributeSelectorDialogService, AttributeSortSelectorDialogComponent, AttributeSortSelectorDialogService, AttributeValueTypeDto, CkTypeSelectorDialogComponent, CkTypeSelectorDialogService, CkTypeSelectorInputComponent, DEFAULT_CK_TYPE_SELECTOR_DIALOG_MESSAGES, DEFAULT_CK_TYPE_SELECTOR_INPUT_MESSAGES, DEFAULT_DATA_POINT, DEFAULT_MAPPING_COVERAGE_TREE_CONFIG, DEFAULT_PROPERTY_GRID_MESSAGES, DEFAULT_RUNTIME_BROWSER_MESSAGES, DataMappingOverviewComponent, DataPointPickerComponent, DataPointResolverService, DefaultPropertyCategory, EntityDetailComponent, EntityIdInfoComponent, EntitySelectorDialogComponent, EntitySelectorDialogService, FieldFilterEditorComponent, MappingCoverageTreeComponent, MappingCoverageTreeDataSource, MappingEditDialogComponent, MappingEditDialogService, OctoGraphQlDataSource, OctoGraphQlHierarchyDataSource, OctoLoaderComponent, PropertyConverterService, PropertyDisplayMode, PropertyGridComponent, PropertyValueDisplayComponent, RUNTIME_BROWSER_MESSAGES, RecordDetailDialogComponent, RtEntityIdHelper, RuntimeBrowserComponent, RuntimeBrowserOutletComponent, RuntimeBrowserPageComponent, RuntimeBrowserStateService, RuntimeEntityVariableDialogComponent, RuntimeEntityVariableDialogService, TenantSwitcherComponent, account_tree, add, analytics, app_registration, article, botService, category, chat, checklist, code, component_exchange, computer, createRuntimeBrowserRoutes, customer, dashboard, event_list, extractDataPointNames, graphic_eq, group, identityService, insert_link, manage_accounts, more_time, notifications, page_info, pages, person_search, playlist_add_check, pool, power, provideOctoUi, publicIcon, query_builder, schedule_send, settings, sort, storage, swagger, swagger_asset, swagger_bot, swagger_communication, swagger_identity, team_dashboard, tenancy, text_snippet, travel_explore, user_diagnostics, webhook, work };
18512
+ export { AssociationValidationService, AttributeSelectorDialogComponent, AttributeSelectorDialogService, AttributeSortSelectorDialogComponent, AttributeSortSelectorDialogService, AttributeValueTypeDto, CkTypeSelectorDialogComponent, CkTypeSelectorDialogService, CkTypeSelectorInputComponent, DEFAULT_CK_TYPE_SELECTOR_DIALOG_MESSAGES, DEFAULT_CK_TYPE_SELECTOR_INPUT_MESSAGES, DEFAULT_DATA_POINT, DEFAULT_MAPPING_COVERAGE_TREE_CONFIG, DEFAULT_PROPERTY_GRID_MESSAGES, DEFAULT_RUNTIME_BROWSER_MESSAGES, DataMappingOverviewComponent, DataPointPickerComponent, DataPointResolverService, DefaultPropertyCategory, EntityDetailComponent, EntityIdInfoComponent, EntitySelectorDialogComponent, EntitySelectorDialogService, FieldFilterEditorComponent, MappingCoverageTreeComponent, MappingCoverageTreeDataSource, MappingEditDialogComponent, MappingEditDialogService, OctoGraphQlDataSource, OctoGraphQlHierarchyDataSource, OctoLoaderComponent, PropertyConverterService, PropertyDisplayMode, PropertyGridComponent, PropertyValueDisplayComponent, RUNTIME_BROWSER_MESSAGES, RecordDetailDialogComponent, RtEntityIdHelper, RuntimeBrowserComponent, RuntimeBrowserOutletComponent, RuntimeBrowserPageComponent, RuntimeBrowserStateService, RuntimeEntityVariableDialogComponent, RuntimeEntityVariableDialogService, TREE_NAVIGATION_CONFIG_CONSTANTS, TenantSwitcherComponent, TreeNavigationConfigService, account_tree, add, analytics, app_registration, article, botService, category, chat, checklist, code, component_exchange, computer, createRuntimeBrowserRoutes, customer, dashboard, event_list, extractDataPointNames, graphic_eq, group, identityService, insert_link, manage_accounts, more_time, notifications, page_info, pages, person_search, playlist_add_check, pool, power, provideOctoUi, publicIcon, query_builder, schedule_send, settings, sort, storage, swagger, swagger_asset, swagger_bot, swagger_communication, swagger_identity, team_dashboard, tenancy, text_snippet, travel_explore, user_diagnostics, webhook, work };
18022
18513
  //# sourceMappingURL=meshmakers-octo-ui.mjs.map