@masterteam/client-components 0.0.7 → 0.0.9

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.
@@ -0,0 +1,120 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injectable, input, signal, computed, effect, untracked, Component } from '@angular/core';
3
+ import { EntitiesPreview } from '@masterteam/components/entities';
4
+ import { HttpClient } from '@angular/common/http';
5
+
6
+ class ClientInstancePreviewApiService {
7
+ http = inject(HttpClient);
8
+ baseUrl = 'data/modules/cards';
9
+ resolve(config) {
10
+ return this.http.get(this.baseUrl, {
11
+ params: {
12
+ masterModuleDataId: config.instanceId,
13
+ moduleId: config.moduleId,
14
+ levelId: config.levelId,
15
+ displayAreas: config.displayAreas,
16
+ },
17
+ });
18
+ }
19
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientInstancePreviewApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
20
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientInstancePreviewApiService, providedIn: 'root' });
21
+ }
22
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientInstancePreviewApiService, decorators: [{
23
+ type: Injectable,
24
+ args: [{ providedIn: 'root' }]
25
+ }] });
26
+
27
+ class ClientInstancePreview {
28
+ clientInstancePreviewApiService = inject(ClientInstancePreviewApiService);
29
+ loadSub;
30
+ config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
31
+ loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
32
+ error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
33
+ response = signal(null, ...(ngDevMode ? [{ debugName: "response" }] : []));
34
+ entities = computed(() => mapPreviewToEntities(this.response()), ...(ngDevMode ? [{ debugName: "entities" }] : []));
35
+ constructor() {
36
+ effect(() => {
37
+ const config = this.config();
38
+ if (!config) {
39
+ return;
40
+ }
41
+ untracked(() => this.load(config));
42
+ });
43
+ }
44
+ load(config) {
45
+ this.loadSub?.unsubscribe();
46
+ this.loading.set(true);
47
+ this.error.set(null);
48
+ this.loadSub = this.clientInstancePreviewApiService
49
+ .resolve(config)
50
+ .subscribe({
51
+ next: (response) => {
52
+ this.loading.set(false);
53
+ this.response.set(response.data);
54
+ },
55
+ error: (error) => {
56
+ this.loading.set(false);
57
+ this.response.set(null);
58
+ const message = error?.error?.message ??
59
+ error?.message ??
60
+ 'Failed to load instance preview';
61
+ this.error.set(message);
62
+ },
63
+ });
64
+ }
65
+ ngOnDestroy() {
66
+ this.loadSub?.unsubscribe();
67
+ }
68
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientInstancePreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
69
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientInstancePreview, isStandalone: true, selector: "mt-client-instance-preview", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (loading()) {\r\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\r\n @for (item of [1, 2, 3, 4]; track item) {\r\n <div class=\"rounded-2xl border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"mb-3 h-4 w-28 animate-pulse rounded bg-surface-200\"></div>\r\n <div class=\"h-5 w-40 animate-pulse rounded bg-surface-200\"></div>\r\n </div>\r\n }\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ error() }}\r\n </p>\r\n </div>\r\n} @else if (entities().length) {\r\n <mt-entities-preview [entities]=\"entities()\" />\r\n} @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n No preview data is available for this instance.\r\n </p>\r\n </div>\r\n}\r\n", dependencies: [{ kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities"] }] });
70
+ }
71
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientInstancePreview, decorators: [{
72
+ type: Component,
73
+ args: [{ selector: 'mt-client-instance-preview', standalone: true, imports: [EntitiesPreview], template: "@if (loading()) {\r\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\r\n @for (item of [1, 2, 3, 4]; track item) {\r\n <div class=\"rounded-2xl border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"mb-3 h-4 w-28 animate-pulse rounded bg-surface-200\"></div>\r\n <div class=\"h-5 w-40 animate-pulse rounded bg-surface-200\"></div>\r\n </div>\r\n }\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ error() }}\r\n </p>\r\n </div>\r\n} @else if (entities().length) {\r\n <mt-entities-preview [entities]=\"entities()\" />\r\n} @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n No preview data is available for this instance.\r\n </p>\r\n </div>\r\n}\r\n" }]
74
+ }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }] } });
75
+ // ─── Mapping helpers ───
76
+ function buildDisplayConfigLookup(displayConfigurations) {
77
+ const lookup = new Map();
78
+ for (const config of displayConfigurations) {
79
+ for (const prop of config.properties ?? []) {
80
+ if (prop.areaKey !== 'card' || !prop.propertyKey)
81
+ continue;
82
+ lookup.set(prop.propertyKey, prop);
83
+ }
84
+ }
85
+ return lookup;
86
+ }
87
+ function mapPropertiesToEntities(properties, configLookup) {
88
+ return properties
89
+ .map((prop, index) => {
90
+ const displayConfig = configLookup.get(prop.key);
91
+ return {
92
+ id: prop.propertyId,
93
+ propertyId: prop.propertyId,
94
+ key: prop.key,
95
+ normalizedKey: prop.normalizedKey,
96
+ name: prop.name,
97
+ rawValue: prop.rawValue,
98
+ value: prop.value,
99
+ viewType: prop.viewType,
100
+ type: prop.type,
101
+ order: displayConfig?.order ?? index + 1,
102
+ configuration: displayConfig?.configuration ?? { size: 4 },
103
+ };
104
+ })
105
+ .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
106
+ }
107
+ function mapPreviewToEntities(response) {
108
+ if (!response?.master?.properties?.length) {
109
+ return [];
110
+ }
111
+ const configLookup = buildDisplayConfigLookup(response.displayConfigurations ?? []);
112
+ return mapPropertiesToEntities(response.master.properties, configLookup);
113
+ }
114
+
115
+ /**
116
+ * Generated bundle index. Do not edit.
117
+ */
118
+
119
+ export { ClientInstancePreview, ClientInstancePreviewApiService };
120
+ //# sourceMappingURL=masterteam-client-components-client-instance-preview.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"masterteam-client-components-client-instance-preview.mjs","sources":["../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview-api.service.ts","../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview.ts","../../../../packages/masterteam/client-components/client-instance-preview/client-instance-preview.html","../../../../packages/masterteam/client-components/client-instance-preview/masterteam-client-components-client-instance-preview.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { PreviewResponse, Response } from './client-instance-preview.model';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class ClientInstancePreviewApiService {\r\n private readonly http = inject(HttpClient);\r\n private readonly baseUrl = 'data/modules/cards';\r\n\r\n resolve(config: any): Observable<Response<PreviewResponse>> {\r\n return this.http.get<Response<PreviewResponse>>(this.baseUrl, {\r\n params: {\r\n masterModuleDataId: config.instanceId,\r\n moduleId: config.moduleId,\r\n levelId: config.levelId,\r\n displayAreas: config.displayAreas,\r\n },\r\n });\r\n }\r\n}\r\n","import {\n Component,\n computed,\n effect,\n inject,\n input,\n OnDestroy,\n signal,\n untracked,\n} from '@angular/core';\nimport { Subscription } from 'rxjs';\n\r\nimport { EntitiesPreview, EntityData } from '@masterteam/components/entities';\r\n\r\nimport { ClientInstancePreviewApiService } from './client-instance-preview-api.service';\r\nimport {\r\n ClientInstancePreviewConfig,\r\n DisplayConfiguration,\r\n DisplayPropertyConfig,\r\n PreviewProperty,\r\n PreviewResponse,\r\n} from './client-instance-preview.model';\r\n\r\n@Component({\r\n selector: 'mt-client-instance-preview',\r\n standalone: true,\r\n imports: [EntitiesPreview],\r\n templateUrl: './client-instance-preview.html',\r\n})\nexport class ClientInstancePreview implements OnDestroy {\n private readonly clientInstancePreviewApiService = inject(\r\n ClientInstancePreviewApiService,\r\n );\r\n private loadSub?: Subscription;\r\n readonly config = input.required<ClientInstancePreviewConfig>();\r\n readonly loading = signal(false);\r\n readonly error = signal<string | null>(null);\n readonly response = signal<PreviewResponse | null>(null);\n\n readonly entities = computed(() => mapPreviewToEntities(this.response()));\n\n constructor() {\n effect(() => {\n const config = this.config();\n if (!config) {\n return;\n }\n\n untracked(() => this.load(config));\n });\n }\n\n load(config: ClientInstancePreviewConfig): void {\n this.loadSub?.unsubscribe();\n this.loading.set(true);\n this.error.set(null);\n\n this.loadSub = this.clientInstancePreviewApiService\r\n .resolve(config)\r\n .subscribe({\r\n next: (response) => {\r\n this.loading.set(false);\r\n this.response.set(response.data);\r\n },\r\n error: (error) => {\r\n this.loading.set(false);\r\n this.response.set(null);\r\n const message =\r\n error?.error?.message ??\r\n error?.message ??\r\n 'Failed to load instance preview';\r\n this.error.set(message);\r\n },\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.loadSub?.unsubscribe();\r\n }\r\n}\r\n\r\n// ─── Mapping helpers ───\r\n\r\nfunction buildDisplayConfigLookup(\r\n displayConfigurations: DisplayConfiguration[],\r\n): Map<string, DisplayPropertyConfig> {\r\n const lookup = new Map<string, DisplayPropertyConfig>();\r\n for (const config of displayConfigurations) {\r\n for (const prop of config.properties ?? []) {\r\n if (prop.areaKey !== 'card' || !prop.propertyKey) continue;\r\n lookup.set(prop.propertyKey, prop);\r\n }\r\n }\r\n return lookup;\r\n}\r\n\r\nfunction mapPropertiesToEntities(\r\n properties: PreviewProperty[],\r\n configLookup: Map<string, DisplayPropertyConfig>,\r\n): EntityData[] {\r\n return properties\r\n .map((prop, index) => {\r\n const displayConfig = configLookup.get(prop.key);\r\n return {\r\n id: prop.propertyId,\r\n propertyId: prop.propertyId,\r\n key: prop.key,\r\n normalizedKey: prop.normalizedKey,\r\n name: prop.name,\r\n rawValue: prop.rawValue,\r\n value: prop.value as EntityData['value'],\r\n viewType: prop.viewType as EntityData['viewType'],\r\n type: prop.type,\r\n order: displayConfig?.order ?? index + 1,\r\n configuration: displayConfig?.configuration ?? { size: 4 },\r\n } as EntityData;\r\n })\r\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));\r\n}\r\n\r\nfunction mapPreviewToEntities(response: PreviewResponse | null): EntityData[] {\r\n if (!response?.master?.properties?.length) {\r\n return [];\r\n }\r\n\r\n const configLookup = buildDisplayConfigLookup(\r\n response.displayConfigurations ?? [],\r\n );\r\n\r\n return mapPropertiesToEntities(response.master.properties, configLookup);\r\n}\r\n","@if (loading()) {\r\n <div class=\"grid grid-cols-1 gap-3 md:grid-cols-2\">\r\n @for (item of [1, 2, 3, 4]; track item) {\r\n <div class=\"rounded-2xl border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"mb-3 h-4 w-28 animate-pulse rounded bg-surface-200\"></div>\r\n <div class=\"h-5 w-40 animate-pulse rounded bg-surface-200\"></div>\r\n </div>\r\n }\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ error() }}\r\n </p>\r\n </div>\r\n} @else if (entities().length) {\r\n <mt-entities-preview [entities]=\"entities()\" />\r\n} @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-2xl border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n No preview data is available for this instance.\r\n </p>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -113,6 +113,7 @@ class ClientListStateService {
113
113
  take,
114
114
  totalCount,
115
115
  error: null,
116
+ rawData: response,
116
117
  },
117
118
  });
118
119
  }
@@ -143,6 +144,7 @@ class ClientListStateService {
143
144
  take: 0,
144
145
  totalCount: cards.length,
145
146
  error: null,
147
+ rawData: response,
146
148
  },
147
149
  });
148
150
  }
@@ -170,6 +172,7 @@ class ClientListStateService {
170
172
  totalCount: chartsCount,
171
173
  dashboardData,
172
174
  error: null,
175
+ rawData: response,
173
176
  },
174
177
  });
175
178
  }
@@ -205,6 +208,7 @@ class ClientListStateService {
205
208
  take: existing.take,
206
209
  expanded: existing.expanded,
207
210
  dashboardData: existing.dashboardData,
211
+ rawData: existing.rawData,
208
212
  };
209
213
  }
210
214
  getVisibleColumns(columns) {
@@ -344,12 +348,22 @@ class ClientListTableView {
344
348
  slotGridSpan(span) {
345
349
  return `span ${span} / span ${span}`;
346
350
  }
351
+ templateContext(item) {
352
+ return {
353
+ $implicit: item,
354
+ table: item,
355
+ item,
356
+ loading: item.loading,
357
+ error: item.error,
358
+ data: item.rawData,
359
+ };
360
+ }
347
361
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientListTableView, deps: [], target: i0.ɵɵFactoryTarget.Component });
348
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientListTableView, isStandalone: true, selector: "mt-client-list-table-view", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lazyLoad: "lazyLoad" }, ngImport: i0, template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (table().config.contentStart) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.startSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentStart\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: table(),\r\n table: table(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.tableSpan)\">\r\n <mt-card>\r\n @if (table().loading && table().rows.length === 0) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n </div>\r\n } @else if (table().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ table().error }}\r\n </div>\r\n } @else {\r\n <mt-table\r\n [data]=\"table().rows\"\r\n [columns]=\"table().columns\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"table().loading\"\r\n [lazy]=\"table().config.isPaginated\"\r\n [lazyTotalRecords]=\"table().totalCount\"\r\n [pageSize]=\"table().config.isPaginated ? table().take : 10\"\r\n (lazyLoad)=\"lazyLoad.emit($event)\"\r\n />\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (table().config.contentEnd) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.endSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: table(),\r\n table: table(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "showFilters", "loading", "updating", "lazy", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
362
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientListTableView, isStandalone: true, selector: "mt-client-list-table-view", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lazyLoad: "lazyLoad" }, ngImport: i0, template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (table().config.contentStart) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.startSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentStart\"\r\n [ngTemplateOutletContext]=\"templateContext(table())\"\r\n />\r\n </div>\r\n }\r\n\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.tableSpan)\">\r\n <mt-card>\r\n @if (table().loading && table().rows.length === 0) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n </div>\r\n } @else if (table().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ table().error }}\r\n </div>\r\n } @else {\r\n <mt-table\r\n [data]=\"table().rows\"\r\n [columns]=\"table().columns\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"table().loading\"\r\n [lazy]=\"table().config.isPaginated\"\r\n [lazyTotalRecords]=\"table().totalCount\"\r\n [pageSize]=\"table().config.isPaginated ? table().take : 10\"\r\n (lazyLoad)=\"lazyLoad.emit($event)\"\r\n />\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (table().config.contentEnd) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.endSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(table())\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "showFilters", "loading", "updating", "lazy", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "exportable", "exportFilename", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "pageSize", "currentPage", "first", "filterTerm"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
349
363
  }
350
364
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientListTableView, decorators: [{
351
365
  type: Component,
352
- args: [{ selector: 'mt-client-list-table-view', standalone: true, imports: [CommonModule, Card, Table, SkeletonModule], template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (table().config.contentStart) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.startSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentStart\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: table(),\r\n table: table(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.tableSpan)\">\r\n <mt-card>\r\n @if (table().loading && table().rows.length === 0) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n </div>\r\n } @else if (table().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ table().error }}\r\n </div>\r\n } @else {\r\n <mt-table\r\n [data]=\"table().rows\"\r\n [columns]=\"table().columns\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"table().loading\"\r\n [lazy]=\"table().config.isPaginated\"\r\n [lazyTotalRecords]=\"table().totalCount\"\r\n [pageSize]=\"table().config.isPaginated ? table().take : 10\"\r\n (lazyLoad)=\"lazyLoad.emit($event)\"\r\n />\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (table().config.contentEnd) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.endSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: table(),\r\n table: table(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n" }]
366
+ args: [{ selector: 'mt-client-list-table-view', standalone: true, imports: [CommonModule, Card, Table, SkeletonModule], template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (table().config.contentStart) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.startSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentStart\"\r\n [ngTemplateOutletContext]=\"templateContext(table())\"\r\n />\r\n </div>\r\n }\r\n\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.tableSpan)\">\r\n <mt-card>\r\n @if (table().loading && table().rows.length === 0) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n <p-skeleton height=\"3rem\" />\r\n </div>\r\n } @else if (table().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ table().error }}\r\n </div>\r\n } @else {\r\n <mt-table\r\n [data]=\"table().rows\"\r\n [columns]=\"table().columns\"\r\n [rowActions]=\"rowActions()\"\r\n [loading]=\"table().loading\"\r\n [lazy]=\"table().config.isPaginated\"\r\n [lazyTotalRecords]=\"table().totalCount\"\r\n [pageSize]=\"table().config.isPaginated ? table().take : 10\"\r\n (lazyLoad)=\"lazyLoad.emit($event)\"\r\n />\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (table().config.contentEnd) {\r\n <div [style.gridColumn]=\"slotGridSpan(table().config.layout.endSpan)\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"table().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(table())\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n" }]
353
367
  }], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: true }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }] } });
354
368
 
355
369
  class ClientListCardsView {
@@ -371,12 +385,22 @@ class ClientListInformativeView {
371
385
  slotGridSpan(span) {
372
386
  return `span ${span} / span ${span}`;
373
387
  }
388
+ templateContext(item) {
389
+ return {
390
+ $implicit: item,
391
+ table: item,
392
+ item,
393
+ loading: item.loading,
394
+ error: item.error,
395
+ data: item.rawData,
396
+ };
397
+ }
374
398
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientListInformativeView, deps: [], target: i0.ɵɵFactoryTarget.Component });
375
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientListInformativeView, isStandalone: true, selector: "mt-client-list-informative-view", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (informativeState().config.contentStart) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.startSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentStart\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: informativeState(),\r\n table: informativeState(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.tableSpan)\r\n \"\r\n >\r\n <mt-card>\r\n @if (\r\n informativeState().loading &&\r\n !informativeState().dashboardData?.charts?.length\r\n ) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"6rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n </div>\r\n } @else if (informativeState().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ informativeState().error }}\r\n </div>\r\n } @else if (!informativeState().dashboardData?.charts?.length) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n No informative dashboard found.\r\n </div>\r\n } @else {\r\n <div class=\"min-h-[420px]\">\r\n <mt-dashboard-viewer\r\n [isPage]=\"false\"\r\n [showFilters]=\"false\"\r\n [dashboardData]=\"informativeState().dashboardData\"\r\n />\r\n </div>\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (informativeState().config.contentEnd) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.endSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: informativeState(),\r\n table: informativeState(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DashboardViewer, selector: "mt-dashboard-viewer", inputs: ["isPage", "pageTitle", "backButton", "pageId", "dashboardData", "chartsData", "dialogsData", "filtersData", "showFilters"], outputs: ["pageLoaded", "onBack", "chartClick"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
399
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientListInformativeView, isStandalone: true, selector: "mt-client-list-informative-view", inputs: { state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (informativeState().config.contentStart) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.startSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentStart\"\r\n [ngTemplateOutletContext]=\"templateContext(informativeState())\"\r\n />\r\n </div>\r\n }\r\n\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.tableSpan)\r\n \"\r\n >\r\n <mt-card>\r\n @if (\r\n informativeState().loading &&\r\n !informativeState().dashboardData?.charts?.length\r\n ) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"6rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n </div>\r\n } @else if (informativeState().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ informativeState().error }}\r\n </div>\r\n } @else if (!informativeState().dashboardData?.charts?.length) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n No informative dashboard found.\r\n </div>\r\n } @else {\r\n <div class=\"min-h-[420px]\">\r\n <mt-dashboard-viewer\r\n [isPage]=\"false\"\r\n [showFilters]=\"false\"\r\n [dashboardData]=\"informativeState().dashboardData\"\r\n />\r\n </div>\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (informativeState().config.contentEnd) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.endSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(informativeState())\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: DashboardViewer, selector: "mt-dashboard-viewer", inputs: ["isPage", "pageTitle", "backButton", "pageId", "dashboardData", "chartsData", "dialogsData", "filtersData", "showFilters"], outputs: ["pageLoaded", "onBack", "chartClick"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i2.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
376
400
  }
377
401
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientListInformativeView, decorators: [{
378
402
  type: Component,
379
- args: [{ selector: 'mt-client-list-informative-view', standalone: true, imports: [CommonModule, Card, DashboardViewer, SkeletonModule], template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (informativeState().config.contentStart) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.startSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentStart\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: informativeState(),\r\n table: informativeState(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.tableSpan)\r\n \"\r\n >\r\n <mt-card>\r\n @if (\r\n informativeState().loading &&\r\n !informativeState().dashboardData?.charts?.length\r\n ) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"6rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n </div>\r\n } @else if (informativeState().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ informativeState().error }}\r\n </div>\r\n } @else if (!informativeState().dashboardData?.charts?.length) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n No informative dashboard found.\r\n </div>\r\n } @else {\r\n <div class=\"min-h-[420px]\">\r\n <mt-dashboard-viewer\r\n [isPage]=\"false\"\r\n [showFilters]=\"false\"\r\n [dashboardData]=\"informativeState().dashboardData\"\r\n />\r\n </div>\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (informativeState().config.contentEnd) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.endSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: informativeState(),\r\n table: informativeState(),\r\n }\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n" }]
403
+ args: [{ selector: 'mt-client-list-informative-view', standalone: true, imports: [CommonModule, Card, DashboardViewer, SkeletonModule], template: "<div class=\"grid gap-4\" [style.gridTemplateColumns]=\"gridTemplateColumns\">\r\n @if (informativeState().config.contentStart) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.startSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentStart\"\r\n [ngTemplateOutletContext]=\"templateContext(informativeState())\"\r\n />\r\n </div>\r\n }\r\n\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.tableSpan)\r\n \"\r\n >\r\n <mt-card>\r\n @if (\r\n informativeState().loading &&\r\n !informativeState().dashboardData?.charts?.length\r\n ) {\r\n <div class=\"flex flex-col gap-3 py-3\">\r\n <p-skeleton height=\"6rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n <p-skeleton height=\"12rem\" />\r\n </div>\r\n } @else if (informativeState().error) {\r\n <div\r\n class=\"rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700\"\r\n >\r\n {{ informativeState().error }}\r\n </div>\r\n } @else if (!informativeState().dashboardData?.charts?.length) {\r\n <div class=\"p-6 text-center text-gray-400\">\r\n No informative dashboard found.\r\n </div>\r\n } @else {\r\n <div class=\"min-h-[420px]\">\r\n <mt-dashboard-viewer\r\n [isPage]=\"false\"\r\n [showFilters]=\"false\"\r\n [dashboardData]=\"informativeState().dashboardData\"\r\n />\r\n </div>\r\n }\r\n </mt-card>\r\n </div>\r\n\r\n @if (informativeState().config.contentEnd) {\r\n <div\r\n [style.gridColumn]=\"\r\n slotGridSpan(informativeState().config.layout.endSpan)\r\n \"\r\n >\r\n <ng-container\r\n [ngTemplateOutlet]=\"informativeState().config.contentEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(informativeState())\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n" }]
380
404
  }], propDecorators: { state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: true }] }] } });
381
405
 
382
406
  const DEFAULT_AREA_TYPE = 'table';
@@ -444,6 +468,10 @@ class ClientList {
444
468
  return {
445
469
  $implicit: item,
446
470
  table: item,
471
+ item,
472
+ loading: item.loading,
473
+ error: item.error,
474
+ data: item.rawData,
447
475
  };
448
476
  }
449
477
  defaultTitle(item) {
@@ -471,17 +499,20 @@ class ClientList {
471
499
  const isPaginated = !isInformative &&
472
500
  areaType === 'table' &&
473
501
  (config.isPaginated ?? true);
502
+ const showHeader = config.showHeader ?? true;
474
503
  const take = !isInformative && areaType === 'table'
475
504
  ? isPaginated
476
505
  ? (config.take ?? this.defaultTake())
477
506
  : LOCAL_PAGE_SIZE_SOURCE
478
507
  : 0;
479
- const collapseEnabled = (config.collapse?.enabled ?? true) && hasMultipleConfigs;
508
+ const collapseEnabled = showHeader &&
509
+ (config.collapse?.enabled ?? true) &&
510
+ hasMultipleConfigs;
480
511
  const layout = this.resolveLayout(config);
481
512
  const key = config.key ??
482
513
  `${config.levelId ?? 'x'}-${config.levelDataId ?? 'x'}-${config.moduleId ?? 'x'}-${index}`;
483
514
  const existing = previousItems[key];
484
- const normalizedConfig = this.toNormalizedConfig(config, type, areaType, mode, isPaginated, take, collapseEnabled, layout);
515
+ const normalizedConfig = this.toNormalizedConfig(config, type, areaType, mode, isPaginated, take, showHeader, collapseEnabled, layout);
485
516
  if (isInformative) {
486
517
  return {
487
518
  key,
@@ -500,6 +531,7 @@ class ClientList {
500
531
  take: 0,
501
532
  expanded: existing?.expanded ?? config.collapse?.expandedByDefault ?? true,
502
533
  dashboardData: existing?.dashboardData ?? null,
534
+ rawData: existing?.rawData ?? null,
503
535
  };
504
536
  }
505
537
  if (areaType === 'cards') {
@@ -520,6 +552,7 @@ class ClientList {
520
552
  take: 0,
521
553
  expanded: existing?.expanded ?? config.collapse?.expandedByDefault ?? true,
522
554
  dashboardData: null,
555
+ rawData: existing?.rawData ?? null,
523
556
  };
524
557
  }
525
558
  return {
@@ -539,6 +572,7 @@ class ClientList {
539
572
  take,
540
573
  expanded: existing?.expanded ?? config.collapse?.expandedByDefault ?? true,
541
574
  dashboardData: null,
575
+ rawData: existing?.rawData ?? null,
542
576
  };
543
577
  });
544
578
  this.state.setConfigs(normalized);
@@ -579,10 +613,11 @@ class ClientList {
579
613
  .getRows(config.levelId, config.levelDataId, config.moduleId, query)
580
614
  .subscribe({
581
615
  next: (response) => {
616
+ let hasLoadedData = false;
582
617
  if (response.data) {
583
618
  this.state.setRowsResult(key, response.data, config, query.skip, query.take);
584
619
  this.fulfilledRequestSignatures.set(key, requestSignature);
585
- this.loaded.emit(key);
620
+ hasLoadedData = true;
586
621
  }
587
622
  else {
588
623
  const message = response.message ?? 'Failed to load table rows';
@@ -591,6 +626,10 @@ class ClientList {
591
626
  }
592
627
  this.state.setLoading(key, false);
593
628
  this.inFlightRequestSignatures.delete(key);
629
+ if (hasLoadedData) {
630
+ this.notifyDataLoaded(key);
631
+ this.loaded.emit(key);
632
+ }
594
633
  },
595
634
  error: (error) => {
596
635
  const message = error?.error?.message ?? error?.message ?? 'Failed to load rows';
@@ -625,10 +664,11 @@ class ClientList {
625
664
  .getCards(config.levelDataId, config.moduleId)
626
665
  .subscribe({
627
666
  next: (response) => {
667
+ let hasLoadedData = false;
628
668
  if (response.data) {
629
669
  this.state.setCardsResult(key, response.data, config);
630
670
  this.fulfilledRequestSignatures.set(key, requestSignature);
631
- this.loaded.emit(key);
671
+ hasLoadedData = true;
632
672
  }
633
673
  else {
634
674
  const message = response.message ?? 'Failed to load cards';
@@ -637,6 +677,10 @@ class ClientList {
637
677
  }
638
678
  this.state.setLoading(key, false);
639
679
  this.inFlightRequestSignatures.delete(key);
680
+ if (hasLoadedData) {
681
+ this.notifyDataLoaded(key);
682
+ this.loaded.emit(key);
683
+ }
640
684
  },
641
685
  error: (error) => {
642
686
  const message = error?.error?.message ?? error?.message ?? 'Failed to load cards';
@@ -671,17 +715,19 @@ class ClientList {
671
715
  next: (response) => {
672
716
  this.state.setInformativeResult(key, response.data ?? null, config);
673
717
  this.fulfilledRequestSignatures.set(key, requestSignature);
674
- this.loaded.emit(key);
675
718
  this.state.setLoading(key, false);
676
719
  this.inFlightRequestSignatures.delete(key);
720
+ this.notifyDataLoaded(key);
721
+ this.loaded.emit(key);
677
722
  },
678
723
  error: (error) => {
679
724
  if (error?.status === 404) {
680
725
  this.state.setInformativeResult(key, null, config);
681
726
  this.fulfilledRequestSignatures.set(key, requestSignature);
682
- this.loaded.emit(key);
683
727
  this.state.setLoading(key, false);
684
728
  this.inFlightRequestSignatures.delete(key);
729
+ this.notifyDataLoaded(key);
730
+ this.loaded.emit(key);
685
731
  return;
686
732
  }
687
733
  const message = error?.error?.message ??
@@ -706,7 +752,7 @@ class ClientList {
706
752
  return DEFAULT_MODE;
707
753
  return (columnKeys ?? []).length > 0 ? 'override' : DEFAULT_MODE;
708
754
  }
709
- toNormalizedConfig(config, type, areaType, mode, isPaginated, take, collapseEnabled, layout) {
755
+ toNormalizedConfig(config, type, areaType, mode, isPaginated, take, showHeader, collapseEnabled, layout) {
710
756
  return {
711
757
  levelId: config.levelId,
712
758
  levelDataId: config.levelDataId,
@@ -717,12 +763,15 @@ class ClientList {
717
763
  isPaginated,
718
764
  take,
719
765
  title: config.title,
766
+ showHeader,
720
767
  columnKeys: config.columnKeys ?? [],
721
768
  headerStart: config.headerStart,
722
769
  headerEnd: config.headerEnd,
723
770
  contentStart: config.contentStart,
724
771
  contentEnd: config.contentEnd,
772
+ templateContent: config.templateContent,
725
773
  rowActions: config.rowActions ?? [],
774
+ dataLoaded: config.dataLoaded,
726
775
  collapse: {
727
776
  enabled: collapseEnabled,
728
777
  expandedByDefault: config.collapse?.expandedByDefault ?? true,
@@ -768,6 +817,13 @@ class ClientList {
768
817
  }
769
818
  }
770
819
  }
820
+ notifyDataLoaded(key) {
821
+ const item = this.state.itemsByKey()[key];
822
+ if (!item) {
823
+ return;
824
+ }
825
+ item.config.dataLoaded?.(this.templateContext(item));
826
+ }
771
827
  toTableQuery(config, skip, take) {
772
828
  return {
773
829
  mode: config.mode,
@@ -825,7 +881,7 @@ class ClientList {
825
881
  return 'Missing identifiers: levelId, levelDataId and moduleId are required';
826
882
  }
827
883
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientList, deps: [], target: i0.ɵɵFactoryTarget.Component });
828
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientList, isStandalone: true, selector: "mt-client-list", inputs: { configurations: { classPropertyName: "configurations", publicName: "configurations", isSignal: true, isRequired: true, transformFunction: null }, defaultTake: { classPropertyName: "defaultTake", publicName: "defaultTake", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loaded: "loaded", errored: "errored" }, providers: [ClientListStateService], ngImport: i0, template: "<div class=\"flex flex-col gap-4\">\r\n @for (item of items(); track item.key) {\r\n <section class=\"flex flex-col gap-4\">\r\n <div class=\"flex w-full items-center gap-2\">\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (item.config.collapse.enabled) {\r\n <mt-button\r\n variant=\"text\"\r\n severity=\"secondary\"\r\n [icon]=\"\r\n item.expanded\r\n ? item.config.collapse.collapseIcon\r\n : item.config.collapse.expandIcon\r\n \"\r\n (onClick)=\"toggleExpanded(item.key)\"\r\n />\r\n }\r\n <h3 class=\"m-0 text-lg font-bold\">\r\n {{ item.title || item.moduleKey || defaultTitle(item) }}\r\n </h3>\r\n @if (item.config.headerStart) {\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerStart\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n @if (item.config.headerEnd) {\r\n <div class=\"ml-auto flex shrink-0 items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (item.expanded || !item.config.collapse.enabled) {\r\n @if (item.type === \"informative\") {\r\n <mt-client-list-informative-view [state]=\"item\" />\r\n } @else if (item.areaType === \"table\") {\r\n <mt-client-list-table-view\r\n [state]=\"item\"\r\n [rowActions]=\"item.config.rowActions\"\r\n (lazyLoad)=\"onLazyLoad(item.key, $event)\"\r\n />\r\n } @else {\r\n <mt-client-list-cards-view [state]=\"item\" />\r\n }\r\n }\r\n </section>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ClientListTableView, selector: "mt-client-list-table-view", inputs: ["state", "rowActions"], outputs: ["lazyLoad"] }, { kind: "component", type: ClientListCardsView, selector: "mt-client-list-cards-view", inputs: ["state"] }, { kind: "component", type: ClientListInformativeView, selector: "mt-client-list-informative-view", inputs: ["state"] }] });
884
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: ClientList, isStandalone: true, selector: "mt-client-list", inputs: { configurations: { classPropertyName: "configurations", publicName: "configurations", isSignal: true, isRequired: true, transformFunction: null }, defaultTake: { classPropertyName: "defaultTake", publicName: "defaultTake", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { loaded: "loaded", errored: "errored" }, providers: [ClientListStateService], ngImport: i0, template: "<div class=\"flex flex-col gap-4\">\r\n @for (item of items(); track item.key) {\r\n <section class=\"flex flex-col gap-4\">\r\n @if (item.config.showHeader) {\r\n <div class=\"flex w-full items-center gap-2\">\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (item.config.collapse.enabled) {\r\n <mt-button\r\n variant=\"text\"\r\n severity=\"secondary\"\r\n [icon]=\"\r\n item.expanded\r\n ? item.config.collapse.collapseIcon\r\n : item.config.collapse.expandIcon\r\n \"\r\n (onClick)=\"toggleExpanded(item.key)\"\r\n />\r\n }\r\n <h3 class=\"m-0 text-lg font-bold\">\r\n {{ item.title || item.moduleKey || defaultTitle(item) }}\r\n </h3>\r\n @if (item.config.headerStart) {\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerStart\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n @if (item.config.headerEnd) {\r\n <div class=\"ml-auto flex shrink-0 items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (item.expanded || !item.config.collapse.enabled) {\r\n @if (item.config.templateContent) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.templateContent\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n } @else if (item.type === \"informative\") {\r\n <mt-client-list-informative-view [state]=\"item\" />\r\n } @else if (item.areaType === \"table\") {\r\n <mt-client-list-table-view\r\n [state]=\"item\"\r\n [rowActions]=\"item.config.rowActions\"\r\n (lazyLoad)=\"onLazyLoad(item.key, $event)\"\r\n />\r\n } @else {\r\n <mt-client-list-cards-view [state]=\"item\" />\r\n }\r\n }\r\n </section>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ClientListTableView, selector: "mt-client-list-table-view", inputs: ["state", "rowActions"], outputs: ["lazyLoad"] }, { kind: "component", type: ClientListCardsView, selector: "mt-client-list-cards-view", inputs: ["state"] }, { kind: "component", type: ClientListInformativeView, selector: "mt-client-list-informative-view", inputs: ["state"] }] });
829
885
  }
830
886
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: ClientList, decorators: [{
831
887
  type: Component,
@@ -835,7 +891,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
835
891
  ClientListTableView,
836
892
  ClientListCardsView,
837
893
  ClientListInformativeView,
838
- ], providers: [ClientListStateService], template: "<div class=\"flex flex-col gap-4\">\r\n @for (item of items(); track item.key) {\r\n <section class=\"flex flex-col gap-4\">\r\n <div class=\"flex w-full items-center gap-2\">\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (item.config.collapse.enabled) {\r\n <mt-button\r\n variant=\"text\"\r\n severity=\"secondary\"\r\n [icon]=\"\r\n item.expanded\r\n ? item.config.collapse.collapseIcon\r\n : item.config.collapse.expandIcon\r\n \"\r\n (onClick)=\"toggleExpanded(item.key)\"\r\n />\r\n }\r\n <h3 class=\"m-0 text-lg font-bold\">\r\n {{ item.title || item.moduleKey || defaultTitle(item) }}\r\n </h3>\r\n @if (item.config.headerStart) {\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerStart\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n @if (item.config.headerEnd) {\r\n <div class=\"ml-auto flex shrink-0 items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n\r\n @if (item.expanded || !item.config.collapse.enabled) {\r\n @if (item.type === \"informative\") {\r\n <mt-client-list-informative-view [state]=\"item\" />\r\n } @else if (item.areaType === \"table\") {\r\n <mt-client-list-table-view\r\n [state]=\"item\"\r\n [rowActions]=\"item.config.rowActions\"\r\n (lazyLoad)=\"onLazyLoad(item.key, $event)\"\r\n />\r\n } @else {\r\n <mt-client-list-cards-view [state]=\"item\" />\r\n }\r\n }\r\n </section>\r\n }\r\n</div>\r\n" }]
894
+ ], providers: [ClientListStateService], template: "<div class=\"flex flex-col gap-4\">\r\n @for (item of items(); track item.key) {\r\n <section class=\"flex flex-col gap-4\">\r\n @if (item.config.showHeader) {\r\n <div class=\"flex w-full items-center gap-2\">\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (item.config.collapse.enabled) {\r\n <mt-button\r\n variant=\"text\"\r\n severity=\"secondary\"\r\n [icon]=\"\r\n item.expanded\r\n ? item.config.collapse.collapseIcon\r\n : item.config.collapse.expandIcon\r\n \"\r\n (onClick)=\"toggleExpanded(item.key)\"\r\n />\r\n }\r\n <h3 class=\"m-0 text-lg font-bold\">\r\n {{ item.title || item.moduleKey || defaultTitle(item) }}\r\n </h3>\r\n @if (item.config.headerStart) {\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerStart\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n @if (item.config.headerEnd) {\r\n <div class=\"ml-auto flex shrink-0 items-center gap-2\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.headerEnd\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n @if (item.expanded || !item.config.collapse.enabled) {\r\n @if (item.config.templateContent) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"item.config.templateContent\"\r\n [ngTemplateOutletContext]=\"templateContext(item)\"\r\n />\r\n } @else if (item.type === \"informative\") {\r\n <mt-client-list-informative-view [state]=\"item\" />\r\n } @else if (item.areaType === \"table\") {\r\n <mt-client-list-table-view\r\n [state]=\"item\"\r\n [rowActions]=\"item.config.rowActions\"\r\n (lazyLoad)=\"onLazyLoad(item.key, $event)\"\r\n />\r\n } @else {\r\n <mt-client-list-cards-view [state]=\"item\" />\r\n }\r\n }\r\n </section>\r\n }\r\n</div>\r\n" }]
839
895
  }], ctorParameters: () => [], propDecorators: { configurations: [{ type: i0.Input, args: [{ isSignal: true, alias: "configurations", required: true }] }], defaultTake: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultTake", required: false }] }], loaded: [{ type: i0.Output, args: ["loaded"] }], errored: [{ type: i0.Output, args: ["errored"] }] } });
840
896
 
841
897
  /**