@masterteam/client-components 0.0.95 → 0.0.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masterteam/client-components",
3
- "version": "0.0.95",
3
+ "version": "0.0.96",
4
4
  "publishConfig": {
5
5
  "directory": "../../../dist/masterteam/client-components",
6
6
  "linkDirectory": true,
@@ -16,10 +16,10 @@
16
16
  "rxjs": "^7.8.2",
17
17
  "tailwindcss": "^4.2.2",
18
18
  "tailwindcss-primeui": "^0.6.1",
19
- "@masterteam/forms": "^0.0.155",
20
- "@masterteam/components": "^0.0.300",
21
- "@masterteam/dashboard-builder": "^0.0.92",
22
- "@masterteam/icons": "^0.0.17"
19
+ "@masterteam/forms": "^0.0.156",
20
+ "@masterteam/icons": "^0.0.17",
21
+ "@masterteam/components": "^0.0.301",
22
+ "@masterteam/dashboard-builder": "^0.0.92"
23
23
  },
24
24
  "dependencies": {
25
25
  "tslib": "^2.8.1"
@@ -1,7 +1,7 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import { OnDestroy } from '@angular/core';
3
3
  import * as _masterteam_components_entities from '@masterteam/components/entities';
4
- import { EntityData, EntityViewType, EntityListPreviewContext } from '@masterteam/components/entities';
4
+ import { EntityRuntimeContext, EntityData, EntityViewType } from '@masterteam/components/entities';
5
5
  import { Observable } from 'rxjs';
6
6
 
7
7
  interface ClientInstancePreviewConfig {
@@ -9,6 +9,17 @@ interface ClientInstancePreviewConfig {
9
9
  instanceId: number;
10
10
  displayAreas?: string[];
11
11
  processRequestId?: number;
12
+ /**
13
+ * Owning level and level-data ids, for the renderers that fetch data of
14
+ * their own — today a module-backed `EntityList`, which renders as the real
15
+ * related-records table when this is present and as a count-and-drawer
16
+ * trigger when it is not.
17
+ *
18
+ * It has to come from the host. The response's own `context` carries the
19
+ * level id, but its `scopeId` is the *level-module* id, not the level-data
20
+ * row, and nothing else in the payload identifies that row.
21
+ */
22
+ runtimeContext?: EntityRuntimeContext;
12
23
  /**
13
24
  * Optional host projection applied after the preview response is converted
14
25
  * to renderable entities. Use it to merge or derive presentation-only
@@ -75,8 +86,22 @@ interface PreviewFetchCatalog {
75
86
  */
76
87
  nestedProperties?: Record<string, PreviewFetchPropertyMeta[]>;
77
88
  }
89
+ /**
90
+ * The resolved context of the fetched record. `scopeId` is the level-module
91
+ * id (`FetchContext.Scope.CompositeId`), **not** the level-data row — a host
92
+ * that needs that one supplies it through `runtimeContext`.
93
+ */
94
+ interface PreviewFetchContext {
95
+ kind?: string;
96
+ levelId?: number;
97
+ moduleId?: number;
98
+ templateId?: number;
99
+ scopeId?: number;
100
+ hasWorkSpace?: boolean;
101
+ }
78
102
  interface PreviewFetchRecordResponse {
79
103
  contextKey: string;
104
+ context?: PreviewFetchContext | null;
80
105
  schemas?: PreviewFetchSchema[];
81
106
  catalog?: PreviewFetchCatalog;
82
107
  record?: PreviewFetchRecord | null;
@@ -94,6 +119,7 @@ interface DisplayConfiguration {
94
119
  }
95
120
  interface PreviewResponse {
96
121
  contextKey: string;
122
+ context: PreviewFetchContext | null;
97
123
  schemas: PreviewFetchSchema[];
98
124
  catalog: PreviewFetchCatalog;
99
125
  record: PreviewFetchRecord | null;
@@ -103,6 +129,7 @@ interface PreviewResponse {
103
129
  declare class ClientInstancePreview implements OnDestroy {
104
130
  private readonly clientInstancePreviewApiService;
105
131
  private readonly transloco;
132
+ private readonly runtimeContextStore;
106
133
  private loadSub?;
107
134
  readonly config: _angular_core.InputSignal<ClientInstancePreviewConfig>;
108
135
  /** When true, suppresses the "No preview data" empty-state placeholder so the host can collapse. */
@@ -114,28 +141,9 @@ declare class ClientInstancePreview implements OnDestroy {
114
141
  * honored instead. The hard ≤280px overflow stack always applies regardless.
115
142
  */
116
143
  readonly stackOnNarrow: _angular_core.InputSignal<boolean>;
117
- /**
118
- * Level-data row the previewed record belongs to.
119
- *
120
- * Supplying it renders every `EntityList` property as the full read-only
121
- * table the form shows, instead of a count and a drawer. That table loads
122
- * itself from `Properties/{propertyId}/entitylist/table-metadata` and
123
- * `fetch/query`, which need the owning level *and* its level-data scope —
124
- * and the fetch Card payload carries neither, so the host passes this from
125
- * the route while the level is parsed from `contextKey`.
126
- *
127
- * Left null, EntityList keeps the compact renderer: without the scope the
128
- * table would draw its columns and never a row.
129
- */
130
- readonly levelDataId: _angular_core.InputSignal<string | number | null>;
131
144
  readonly loading: _angular_core.WritableSignal<boolean>;
132
145
  readonly error: _angular_core.WritableSignal<string | null>;
133
146
  readonly response: _angular_core.WritableSignal<PreviewResponse | null>;
134
- /**
135
- * Runtime scope handed to each `EntityList` entity, or null when this host
136
- * did not supply a level-data row. See {@link levelDataId}.
137
- */
138
- protected readonly entityListContext: _angular_core.Signal<EntityListPreviewContext | null>;
139
147
  readonly entities: _angular_core.Signal<EntityData[]>;
140
148
  /**
141
149
  * Name of the schema the loaded record belongs to — the level name for a
@@ -144,11 +152,21 @@ declare class ClientInstancePreview implements OnDestroy {
144
152
  * fetch resolves.
145
153
  */
146
154
  readonly schemaName: _angular_core.Signal<string | null>;
155
+ /**
156
+ * What the nested renderers fetch with.
157
+ *
158
+ * The level id is taken from the response when the host did not supply one —
159
+ * `fetch/records` resolves it anyway, so a host that already passes a
160
+ * `contextKey` should not have to repeat it. The level-data id has no such
161
+ * fallback: the response's `scopeId` is the level-module id, so a host that
162
+ * omits `runtimeContext` gets no inline table.
163
+ */
164
+ private readonly runtimeContext;
147
165
  constructor();
148
166
  load(config: ClientInstancePreviewConfig): void;
149
167
  ngOnDestroy(): void;
150
168
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ClientInstancePreview, never>;
151
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<ClientInstancePreview, "mt-client-instance-preview", never, { "config": { "alias": "config"; "required": true; "isSignal": true; }; "hideEmptyState": { "alias": "hideEmptyState"; "required": false; "isSignal": true; }; "stackOnNarrow": { "alias": "stackOnNarrow"; "required": false; "isSignal": true; }; "levelDataId": { "alias": "levelDataId"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
169
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ClientInstancePreview, "mt-client-instance-preview", never, { "config": { "alias": "config"; "required": true; "isSignal": true; }; "hideEmptyState": { "alias": "hideEmptyState"; "required": false; "isSignal": true; }; "stackOnNarrow": { "alias": "stackOnNarrow"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
152
170
  }
153
171
 
154
172
  declare class ClientInstancePreviewApiService {
@@ -161,4 +179,4 @@ declare class ClientInstancePreviewApiService {
161
179
  }
162
180
 
163
181
  export { ClientInstancePreview, ClientInstancePreviewApiService };
164
- export type { ClientInstancePreviewConfig, ClientInstancePreviewEntityTransform, DisplayConfiguration, PreviewFetchCatalog, PreviewFetchPropertyMeta, PreviewFetchRecord, PreviewFetchRecordResponse, PreviewFetchSchema, PreviewFetchValueCell, PreviewResponse, Response };
182
+ export type { ClientInstancePreviewConfig, ClientInstancePreviewEntityTransform, DisplayConfiguration, PreviewFetchCatalog, PreviewFetchContext, PreviewFetchPropertyMeta, PreviewFetchRecord, PreviewFetchRecordResponse, PreviewFetchSchema, PreviewFetchValueCell, PreviewResponse, Response };
@@ -192,15 +192,23 @@ interface ClientListFormConfiguration extends ClientListBaseConfiguration {
192
192
  /** Complete filter array forwarded unchanged to `fetch/query`. */
193
193
  filters?: ClientListFetchRequestFilter[];
194
194
  /**
195
- * `areaType: 'table'` only — fetch the rows owned by this root's
196
- * descendants instead of the rows owned by the context's own records. See
197
- * {@link ClientListFetchHierarchyScope}. Ignored for cards and informative
198
- * lists, which the backend rejects outright.
195
+ * `areaType: 'table'` and `areaType: 'cards'` — fetch the rows owned by this
196
+ * root's descendants instead of the rows owned by the context's own records.
197
+ * See {@link ClientListFetchHierarchyScope}. Ignored for informative lists,
198
+ * which the backend rejects outright.
199
199
  *
200
200
  * Rows then arrive from several owners at once: each carries its owning
201
- * record under {@link CLIENT_LIST_RECORD_SOURCE_KEY}, row actions are
202
- * addressed to that owner's context, and `state.totals` / `state.sourceGroups`
203
- * carry the pre-pagination aggregates.
201
+ * record under {@link CLIENT_LIST_RECORD_SOURCE_KEY} (a card carries it as
202
+ * {@link ClientListCard.source}), row actions are addressed to that owner's
203
+ * context, and `state.totals` / `state.sourceGroups` carry the
204
+ * pre-pagination aggregates.
205
+ *
206
+ * A cards board is still fetched as a `Table` projection — descendant scope
207
+ * is table-only on the backend — and re-dressed with the context's authored
208
+ * card layout. Two consequences: the board shows the module's table
209
+ * selection, so a property the card layout uses but the table hides cannot
210
+ * appear on it; and a write reloads the board rather than splicing, for the
211
+ * same reason a hierarchy table does.
204
212
  */
205
213
  hierarchy?: ClientListFetchHierarchyScope;
206
214
  mode?: ClientListMode;
@@ -611,6 +619,14 @@ interface ClientListCard {
611
619
  properties: ClientListCardProperty[];
612
620
  displayProperties?: Record<string, unknown>;
613
621
  entities: EntityData[];
622
+ /**
623
+ * Descendant boards only: the record that owns this card. Null on an
624
+ * ordinary board, where the list's own context is the owner. Travels into
625
+ * the card's row representation under
626
+ * {@link CLIENT_LIST_RECORD_SOURCE_KEY}, so row actions address the owner
627
+ * rather than the aggregation context.
628
+ */
629
+ source?: ClientListFetchRecordSource | null;
614
630
  }
615
631
  type ClientListCardsPayload = ClientListFetchQueryResponse;
616
632
  interface ClientListInformativeChartLink {
@@ -646,14 +662,19 @@ interface ClientListBaseState {
646
662
  dashboardData: DashboardBuilderData | null;
647
663
  rawData: unknown | null;
648
664
  /**
649
- * Hierarchy tables only: totals over every matching row before pagination,
665
+ * Hierarchy lists only: totals over every matching row before pagination,
650
666
  * so they stay put as the user pages. Undefined for an ordinary list — the
651
667
  * backend sends none, and a page sum would not be the same number.
652
668
  */
653
669
  totals?: ClientListFetchSum[];
654
670
  /**
655
- * Hierarchy tables only: one entry per owning record, with its full matching
671
+ * Hierarchy lists only: one entry per owning record, with its full matching
656
672
  * count and subtotals plus the ids of its rows on the current page.
673
+ *
674
+ * On a board that appends pages as the user scrolls, "the current page"
675
+ * means the page fetched last while `cards` holds every page loaded so far
676
+ * — so read the counts and subtotals, which cover every matching row,
677
+ * rather than `recordIds`.
657
678
  */
658
679
  sourceGroups?: ClientListFetchSourceGroup[];
659
680
  }
@@ -957,11 +978,14 @@ declare class ClientList implements OnDestroy {
957
978
  private resolveType;
958
979
  private resolveMode;
959
980
  /**
960
- * Descendant scope only survives where the backend accepts it: a table, with
961
- * a usable root id. Anywhere else it is dropped rather than sent, because
962
- * the backend answers an unsupported combination with a 400 that takes the
963
- * whole list down — a cards area that happens to share a config object would
964
- * otherwise render nothing at all.
981
+ * Descendant scope only survives where it can actually be fetched: a table
982
+ * or a cards board, with a usable root id. An informative dashboard drops it
983
+ * rather than sending it, because the backend answers an unsupported
984
+ * combination with a 400 that takes the whole list down.
985
+ *
986
+ * A cards board does not send it as `Card` either — the backend takes
987
+ * descendant scope on `Table` only. `ClientListApiService.getCards` fetches
988
+ * the hierarchy table and re-dresses it as cards.
965
989
  */
966
990
  private resolveHierarchyScope;
967
991
  private toNormalizedConfig;
@@ -1026,6 +1050,8 @@ declare class ClientListApiService {
1026
1050
  private readonly http;
1027
1051
  private readonly runtimeFetchBaseUrl;
1028
1052
  private readonly informativeBaseUrl;
1053
+ /** Card layouts already read back, keyed by context. See {@link getCardLayout}. */
1054
+ private readonly cardLayouts;
1029
1055
  /**
1030
1056
  * Fetches a table page. Resolves to the response **and** the `propertyKeys`
1031
1057
  * the request carried, because a write that wants its record projected the
@@ -1045,7 +1071,49 @@ declare class ClientListApiService {
1045
1071
  * having moved out of the root's subtree since it was written.
1046
1072
  */
1047
1073
  getRecord(contextKey: ClientListRuntimeContext, request: ClientListReturnRecordRequest, filters: ClientListFetchRequestFilter[]): Observable<Response<ClientListFetchQueryResponse>>;
1048
- getCards(contextKey: ClientListRuntimeContext, filters?: ClientListFetchRequestFilter[], skip?: number, take?: number): Observable<Response<ClientListCardsPayload>>;
1074
+ /**
1075
+ * Fetches a board of cards.
1076
+ *
1077
+ * Without a `hierarchy` scope this is a plain `Card` projection. With one it
1078
+ * cannot be: the backend accepts descendant scope on the **`Table`
1079
+ * projection only** and answers any other projection with a 400 that takes
1080
+ * the whole list down. So a descendant board is fetched as a hierarchy table
1081
+ * and re-dressed as cards — the rows carry the same records, their owning
1082
+ * record and the pre-pagination totals, and {@link getCardLayout} supplies
1083
+ * the card layout the board would otherwise lose.
1084
+ */
1085
+ getCards(contextKey: ClientListRuntimeContext, filters?: ClientListFetchRequestFilter[], skip?: number, take?: number, hierarchy?: ClientListFetchHierarchyScope | null): Observable<Response<ClientListCardsPayload>>;
1086
+ /**
1087
+ * The card layout authored for a context, with every property key rewritten
1088
+ * to its normalized form.
1089
+ *
1090
+ * A `Card` response names its properties by the owning context's own key
1091
+ * (`leveldatafinancial_title`), while a hierarchy response normalizes every
1092
+ * row, column and catalog entry across the child levels down to the shared
1093
+ * key (`title`). Sent through unchanged the layout would resolve against
1094
+ * nothing and every card would render empty.
1095
+ *
1096
+ * Cached per context for the life of the app: it is a second request on a
1097
+ * path that already makes one, it is pure configuration, and it is re-read
1098
+ * on the next full load anyway. A card layout edited in the control panel
1099
+ * therefore needs a reload of the app to show up on a descendant board —
1100
+ * the same page-load boundary the rest of the display configuration has.
1101
+ */
1102
+ private getCardLayout;
1103
+ private toNormalizedDisplayOrder;
1104
+ /**
1105
+ * Dresses a hierarchy table response as the card payload the board reads:
1106
+ * the same records, plus the authored card layout narrowed to the properties
1107
+ * this response actually carries. A layout entry with no property behind it
1108
+ * would render as a nameless blank slot, so it is dropped — section markers
1109
+ * excepted, since they are layout rather than data and have no property to
1110
+ * begin with.
1111
+ *
1112
+ * Leaves the response untouched when there is no usable layout: the card
1113
+ * mapper then falls back to the response's own table columns, which is a
1114
+ * plainer board but a complete one.
1115
+ */
1116
+ private withCardLayout;
1049
1117
  getInformativeDashboard(levelId: number, moduleId: number): Observable<Response<ClientListInformativeDashboardPayload>>;
1050
1118
  private queryRuntime;
1051
1119
  private resolveTablePropertyKeys;