@mintplayer/ng-spark 22.22.0 → 22.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +181 -0
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +100 -47
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +308 -329
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs +175 -135
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-grid.mjs +2259 -1117
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +611 -0
- package/fesm2022/mintplayer-ng-spark-history.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-icon.mjs +64 -27
- package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +365 -753
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +1212 -0
- package/fesm2022/mintplayer-ng-spark-moderation.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs +52 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +1122 -765
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +273 -169
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +786 -410
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +292 -284
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +2187 -1225
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +516 -303
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +17 -55
- package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +216 -177
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-routes.mjs +24 -28
- package/fesm2022/mintplayer-ng-spark-routes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +625 -640
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-shell.mjs +1013 -397
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +294 -0
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark.mjs +13 -50
- package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
- package/package.json +17 -1
- package/types/mintplayer-ng-spark-attribute-description.d.ts +25 -18
- package/types/mintplayer-ng-spark-client-operations.d.ts +133 -160
- package/types/mintplayer-ng-spark-column-filter.d.ts +73 -55
- package/types/mintplayer-ng-spark-grid.d.ts +885 -448
- package/types/mintplayer-ng-spark-history.d.ts +223 -0
- package/types/mintplayer-ng-spark-icon.d.ts +15 -13
- package/types/mintplayer-ng-spark-models.d.ts +624 -573
- package/types/mintplayer-ng-spark-moderation.d.ts +402 -0
- package/types/mintplayer-ng-spark-panels.d.ts +108 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +120 -149
- package/types/mintplayer-ng-spark-po-create.d.ts +46 -37
- package/types/mintplayer-ng-spark-po-detail.d.ts +177 -117
- package/types/mintplayer-ng-spark-po-edit.d.ts +64 -65
- package/types/mintplayer-ng-spark-po-form.d.ts +507 -371
- package/types/mintplayer-ng-spark-query-list.d.ts +118 -82
- package/types/mintplayer-ng-spark-renderers.d.ts +79 -85
- package/types/mintplayer-ng-spark-retry-action-modal.d.ts +31 -34
- package/types/mintplayer-ng-spark-routes.d.ts +7 -11
- package/types/mintplayer-ng-spark-services.d.ts +377 -261
- package/types/mintplayer-ng-spark-shell.d.ts +209 -128
- package/types/mintplayer-ng-spark-soft-delete.d.ts +90 -0
- package/types/mintplayer-ng-spark.d.ts +7 -12
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { SparkLanguageService } from
|
|
9
|
-
import { ReferenceChip } from
|
|
10
|
-
|
|
1
|
+
import { BsDatatableFetch, BsDatatableRowEvent, DatatableDistincts, DatatableSettings, FilterChangeDetail } from "@mintplayer/ng-bootstrap/datatable";
|
|
2
|
+
import { CustomActionDefinition, EntityAttributeDefinition, EntityPermissions, EntityType, LookupReference, PersistentObject, QueryColumn, QueryResultItem, SparkCellColumn, SparkDeletedFilter, SparkQuery, SparkSelectionModeSetting } from "@mintplayer/ng-spark/models";
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import { TemplateRef, Type } from "@angular/core";
|
|
5
|
+
import { HttpErrorResponse } from "@angular/common/http";
|
|
6
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
7
|
+
import { ConnectedPosition } from "@angular/cdk/overlay";
|
|
8
|
+
import { SparkLanguageService } from "@mintplayer/ng-spark/services";
|
|
9
|
+
import { ReferenceChip } from "@mintplayer/ng-spark/pipes";
|
|
11
10
|
/** Page sizes offered by every Spark grid. */
|
|
12
|
-
declare const SPARK_GRID_PAGE_SIZES: number[];
|
|
11
|
+
export declare const SPARK_GRID_PAGE_SIZES: number[];
|
|
13
12
|
/**
|
|
14
13
|
* The attributes a grid shows, in display order.
|
|
15
14
|
*
|
|
@@ -17,17 +16,16 @@ declare const SPARK_GRID_PAGE_SIZES: number[];
|
|
|
17
16
|
* copy of this expression, which is the kind of thing that stays identical right up until it
|
|
18
17
|
* doesn't.
|
|
19
18
|
*/
|
|
20
|
-
declare function visibleGridAttributes(entityType: EntityType | null): EntityAttributeDefinition[];
|
|
19
|
+
export declare function visibleGridAttributes(entityType: EntityType | null): EntityAttributeDefinition[];
|
|
21
20
|
/**
|
|
22
21
|
* Initial datatable settings for a query, seeded with the query's declared sort.
|
|
23
22
|
*
|
|
24
23
|
* The datatable owns paging and sorting from here on and calls the fetch callback per page; this
|
|
25
24
|
* only decides where it starts.
|
|
26
25
|
*/
|
|
27
|
-
declare function initialGridSettings(query: SparkQuery | null): DatatableSettings;
|
|
26
|
+
export declare function initialGridSettings(query: SparkQuery | null): DatatableSettings;
|
|
28
27
|
/** Whether a query renders as a virtual-scrolling grid rather than a paged one. */
|
|
29
|
-
declare function isVirtualScrollingQuery(query: SparkQuery | null): boolean;
|
|
30
|
-
|
|
28
|
+
export declare function isVirtualScrollingQuery(query: SparkQuery | null): boolean;
|
|
31
29
|
/**
|
|
32
30
|
* Renderer lookup and lookup-reference loading for a Spark grid.
|
|
33
31
|
*
|
|
@@ -41,38 +39,37 @@ declare function isVirtualScrollingQuery(query: SparkQuery | null): boolean;
|
|
|
41
39
|
* separate because it is stateless service-shaped logic rather than view state, and because it is
|
|
42
40
|
* what a custom grid would need in order to render Spark cells at all.
|
|
43
41
|
*/
|
|
44
|
-
declare class SparkGridRenderers {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
42
|
+
export declare class SparkGridRenderers {
|
|
43
|
+
private readonly registry;
|
|
44
|
+
private readonly sparkService;
|
|
45
|
+
/** The registered column component for a column, or null to fall back to the default cell. */
|
|
46
|
+
columnComponentFor(column: SparkCellColumn): Type<any> | null;
|
|
47
|
+
/** The registered filter-label function for a column, or null to use the server-computed text. */
|
|
48
|
+
filterLabelFor(column: SparkCellColumn): ((value: unknown) => string) | null;
|
|
49
|
+
/**
|
|
50
|
+
* Inputs for a query-grid cell renderer, filtered to what the component actually declares —
|
|
51
|
+
* `NgComponentOutlet` throws on an input the target does not have, which is what lets every
|
|
52
|
+
* member of the renderer contract be optional.
|
|
53
|
+
*/
|
|
54
|
+
columnInputsFor(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any>;
|
|
55
|
+
/**
|
|
56
|
+
* The same contract for a row that is not a query result — an AsDetail sub-table row, which is
|
|
57
|
+
* a plain dictionary of embedded values with no id and no column metadata of its own, so its
|
|
58
|
+
* value cannot be read the way {@link columnInputsFor} reads one.
|
|
59
|
+
*
|
|
60
|
+
* Only the extraction differs; the renderer contract is identical, and stating it once is what
|
|
61
|
+
* stops the two from drifting the way the cell markup already had.
|
|
62
|
+
*/
|
|
63
|
+
cellInputsFor(component: Type<any>, value: unknown, column: SparkCellColumn, item: unknown): Record<string, any>;
|
|
64
|
+
/**
|
|
65
|
+
* Loads every lookup reference the visible columns need, in one pass.
|
|
66
|
+
*
|
|
67
|
+
* Returns an empty map rather than throwing when there are none, so callers never branch on it.
|
|
68
|
+
*/
|
|
69
|
+
loadLookupOptions(columns: readonly (SparkCellColumn | EntityAttributeDefinition)[]): Promise<Record<string, LookupReference>>;
|
|
70
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkGridRenderers, never>;
|
|
71
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
74
72
|
}
|
|
75
|
-
|
|
76
73
|
/**
|
|
77
74
|
* Header slots for `<spark-query-card>`.
|
|
78
75
|
*
|
|
@@ -113,8 +110,8 @@ declare class SparkGridRenderers {
|
|
|
113
110
|
* `contentChildren`.
|
|
114
111
|
*/
|
|
115
112
|
/** Resolves a slot list to the one that applies to a query: targeted first, then untargeted. */
|
|
116
|
-
declare function slotFor<T extends {
|
|
117
|
-
|
|
113
|
+
export declare function slotFor<T extends {
|
|
114
|
+
forQuery: () => string;
|
|
118
115
|
}>(slots: readonly T[], query: SparkQuery | null): T | null;
|
|
119
116
|
/**
|
|
120
117
|
* The icon at the header's leading edge. No default: nothing in the model describes one.
|
|
@@ -125,13 +122,19 @@ declare function slotFor<T extends {
|
|
|
125
122
|
* </spark-query-card>
|
|
126
123
|
* ```
|
|
127
124
|
*/
|
|
128
|
-
declare class SparkQueryIconDirective {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
export declare class SparkQueryIconDirective {
|
|
126
|
+
readonly templateRef: TemplateRef<SparkQuerySlotContext>;
|
|
127
|
+
/** Query alias or id this slot applies to. Empty targets every query on the page. */
|
|
128
|
+
readonly forQuery: import("@angular/core").InputSignal<string>;
|
|
129
|
+
static ngTemplateContextGuard(_dir: SparkQueryIconDirective, ctx: unknown): ctx is SparkQuerySlotContext;
|
|
130
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryIconDirective, never>;
|
|
131
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<SparkQueryIconDirective, "[sparkQueryIcon]", never, {
|
|
132
|
+
"forQuery": {
|
|
133
|
+
"alias": "sparkQueryIcon";
|
|
134
|
+
"required": false;
|
|
135
|
+
"isSignal": true;
|
|
136
|
+
};
|
|
137
|
+
}, {}, never, never, true, never>;
|
|
135
138
|
}
|
|
136
139
|
/**
|
|
137
140
|
* The header caption. Defaults to the query's translated description, falling back to its name.
|
|
@@ -139,12 +142,18 @@ declare class SparkQueryIconDirective {
|
|
|
139
142
|
* The context carries that resolved default as `$implicit`, so a host can decorate it — add a
|
|
140
143
|
* count, a badge — without re-resolving the translation itself.
|
|
141
144
|
*/
|
|
142
|
-
declare class SparkQueryCaptionDirective {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
export declare class SparkQueryCaptionDirective {
|
|
146
|
+
readonly templateRef: TemplateRef<SparkQueryCaptionContext>;
|
|
147
|
+
readonly forQuery: import("@angular/core").InputSignal<string>;
|
|
148
|
+
static ngTemplateContextGuard(_dir: SparkQueryCaptionDirective, ctx: unknown): ctx is SparkQueryCaptionContext;
|
|
149
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryCaptionDirective, never>;
|
|
150
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<SparkQueryCaptionDirective, "[sparkQueryCaption]", never, {
|
|
151
|
+
"forQuery": {
|
|
152
|
+
"alias": "sparkQueryCaption";
|
|
153
|
+
"required": false;
|
|
154
|
+
"isSignal": true;
|
|
155
|
+
};
|
|
156
|
+
}, {}, never, never, true, never>;
|
|
148
157
|
}
|
|
149
158
|
/**
|
|
150
159
|
* The buttons at the header's trailing edge. Defaults to the server-declared custom actions.
|
|
@@ -160,30 +169,57 @@ declare class SparkQueryCaptionDirective {
|
|
|
160
169
|
* </ng-container>
|
|
161
170
|
* ```
|
|
162
171
|
*/
|
|
163
|
-
declare class SparkQueryActionsDirective {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
172
|
+
export declare class SparkQueryActionsDirective {
|
|
173
|
+
readonly templateRef: TemplateRef<SparkQueryActionsContext>;
|
|
174
|
+
readonly forQuery: import("@angular/core").InputSignal<string>;
|
|
175
|
+
static ngTemplateContextGuard(_dir: SparkQueryActionsDirective, ctx: unknown): ctx is SparkQueryActionsContext;
|
|
176
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryActionsDirective, never>;
|
|
177
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<SparkQueryActionsDirective, "[sparkQueryActions]", never, {
|
|
178
|
+
"forQuery": {
|
|
179
|
+
"alias": "sparkQueryActions";
|
|
180
|
+
"required": false;
|
|
181
|
+
"isSignal": true;
|
|
182
|
+
};
|
|
183
|
+
}, {}, never, never, true, never>;
|
|
169
184
|
}
|
|
170
185
|
/** Context for the icon slot: the query whose card is being rendered. */
|
|
171
|
-
declare class SparkQuerySlotContext {
|
|
172
|
-
|
|
186
|
+
export declare class SparkQuerySlotContext {
|
|
187
|
+
$implicit: SparkQuery | null;
|
|
173
188
|
}
|
|
174
|
-
declare class SparkQueryCaptionContext {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
189
|
+
export declare class SparkQueryCaptionContext {
|
|
190
|
+
/** The caption the card would have rendered: description, or the query name. */
|
|
191
|
+
$implicit: string;
|
|
192
|
+
query: SparkQuery | null;
|
|
178
193
|
}
|
|
179
|
-
declare class SparkQueryActionsContext {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
export declare class SparkQueryActionsContext {
|
|
195
|
+
/** The custom actions the card would have rendered, already filtered for this query. */
|
|
196
|
+
$implicit: CustomActionDefinition[];
|
|
197
|
+
/** Rows currently ticked. Empty unless an action is selection-gated. */
|
|
198
|
+
selection: PersistentObject[];
|
|
199
|
+
query: SparkQuery | null;
|
|
185
200
|
}
|
|
186
|
-
|
|
201
|
+
/**
|
|
202
|
+
* One button of a query's toolbar (#460, M15): the built-in New or Delete, or a custom action.
|
|
203
|
+
*
|
|
204
|
+
* Built by `SparkQueryGridComponent.toolbarActions()` and rendered by every host of the grid — the
|
|
205
|
+
* query card's header and the query-list page's action bar — so both surfaces offer the same
|
|
206
|
+
* actions, enabled by the same rules.
|
|
207
|
+
*/
|
|
208
|
+
export interface SparkQueryToolbarAction {
|
|
209
|
+
kind: 'new' | 'delete' | 'custom';
|
|
210
|
+
/** The action's name, unique within the toolbar. */
|
|
211
|
+
name: string;
|
|
212
|
+
/** Its catalogue entry: label, icon, `selectionRule`, `variant`, confirmation. */
|
|
213
|
+
definition: CustomActionDefinition;
|
|
214
|
+
/** `*bsPriorityNavItem` priority: New first, then Delete, then custom actions by offset. */
|
|
215
|
+
priority: number;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* The button classes for an action's `variant`: an allow-list, so a typo cannot inject a class, and
|
|
219
|
+
* the neutral outline default for anything else. Shared by the detail page, the query card and the
|
|
220
|
+
* query-list page.
|
|
221
|
+
*/
|
|
222
|
+
export declare function sparkActionClass(definition: CustomActionDefinition, size?: 'sm'): string;
|
|
187
223
|
/**
|
|
188
224
|
* The one Spark grid: a `<bs-datatable>` rendering a query or a sub-query.
|
|
189
225
|
*
|
|
@@ -213,273 +249,482 @@ declare class SparkQueryActionsContext {
|
|
|
213
249
|
* reference variable — `<spark-query-grid #grid>` … `grid.query()` — not `viewChild`: hosts wrap
|
|
214
250
|
* grids in `@if`, where a `viewChild` is intermittently undefined.
|
|
215
251
|
*/
|
|
216
|
-
declare class SparkQueryGridComponent {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
252
|
+
export declare class SparkQueryGridComponent {
|
|
253
|
+
private readonly sparkService;
|
|
254
|
+
private readonly gridRenderers;
|
|
255
|
+
private readonly queryRefresh;
|
|
256
|
+
readonly lang: SparkLanguageService;
|
|
257
|
+
/** Query alias or id. */
|
|
258
|
+
queryId: import("@angular/core").InputSignal<string>;
|
|
259
|
+
/**
|
|
260
|
+
* The parent persistent object this query is scoped to, when it has one.
|
|
261
|
+
*
|
|
262
|
+
* Optional, because not every query is a detail of something: a page can host a grid that
|
|
263
|
+
* stands on its own — "my accounts", a dashboard list — and the server already treats an absent
|
|
264
|
+
* parent as "no parent" rather than as an error. Requiring these made that shape impossible to
|
|
265
|
+
* express: the component simply never loaded, with no request, no error and no log.
|
|
266
|
+
*
|
|
267
|
+
* Pass both or neither. One without the other is ignored, matching `SparkService.executeQuery`,
|
|
268
|
+
* which omits either param when it is falsy, and the execute endpoint, which resolves a parent
|
|
269
|
+
* only when both are present.
|
|
270
|
+
*/
|
|
271
|
+
parentId: import("@angular/core").InputSignal<string>;
|
|
272
|
+
parentType: import("@angular/core").InputSignal<string>;
|
|
273
|
+
/**
|
|
274
|
+
* Rows supplied from outside. When bound, the grid renders these and runs no fetch.
|
|
275
|
+
*
|
|
276
|
+
* This is how streaming stays out of this component (see the class comment). `null` — the
|
|
277
|
+
* default — means "fetch for yourself"; an empty array means "you have been given no rows",
|
|
278
|
+
* which is a different statement and renders an empty grid rather than triggering a load.
|
|
279
|
+
*/
|
|
280
|
+
data: import("@angular/core").InputSignal<QueryResultItem[] | null>;
|
|
281
|
+
/**
|
|
282
|
+
* Server-side search term, passed through to the query.
|
|
283
|
+
*
|
|
284
|
+
* An input rather than a box, so the host owns the control and the grid owns the request. A
|
|
285
|
+
* host with client-side rows filters them itself before binding `data`.
|
|
286
|
+
*/
|
|
287
|
+
search: import("@angular/core").InputSignal<string>;
|
|
288
|
+
/**
|
|
289
|
+
* Column metadata for externally supplied rows. Required whenever `data` is bound, because a
|
|
290
|
+
* projection cannot describe itself — there is no per-row metadata left to infer it from.
|
|
291
|
+
*/
|
|
292
|
+
columns: import("@angular/core").InputSignal<QueryColumn[] | null>;
|
|
293
|
+
/**
|
|
294
|
+
* Change this to re-run the query. Any value works; only its identity matters.
|
|
295
|
+
*
|
|
296
|
+
* A declarative token rather than only a `reload()` method, because calling a method means
|
|
297
|
+
* holding a component handle, and hosts wrap this grid in `@if`, where a `viewChild` is
|
|
298
|
+
* intermittently undefined.
|
|
299
|
+
*
|
|
300
|
+
* This drives the CHEAP refresh (see {@link reload}). It deliberately does not feed the main
|
|
301
|
+
* effect: re-running `loadData` would re-resolve the query, the entity types, the permissions
|
|
302
|
+
* and the lookups, and reset the user's page and sort on every button press.
|
|
303
|
+
*/
|
|
304
|
+
reloadToken: import("@angular/core").InputSignal<unknown>;
|
|
305
|
+
/**
|
|
306
|
+
* Soft-deletion mode (#460, T2): `exclude` (the default, not sent), `include` or `only` (the
|
|
307
|
+
* recycle bin). Sent with every page and distinct-values request; the server honours a widening
|
|
308
|
+
* only for `ViewDeleted` holders. A change goes back to page 1 and refetches, like a filter.
|
|
309
|
+
* While set, row links carry `?deleted=` so the detail page loads the row the same way — a deleted
|
|
310
|
+
* row is a 404 by id otherwise.
|
|
311
|
+
*/
|
|
312
|
+
deleted: import("@angular/core").InputSignal<SparkDeletedFilter | null | undefined>;
|
|
313
|
+
/** The mode actually sent: `exclude` and "unset" are the same request. */
|
|
314
|
+
protected readonly effectiveDeleted: import("@angular/core").Signal<"include" | "only" | undefined>;
|
|
315
|
+
/**
|
|
316
|
+
* The rows' parent is soft-deleted (#460): the detail page it sits on was opened from the recycle
|
|
317
|
+
* bin with `?deleted=only`. Nothing may be created, deleted or run under a deleted row, so the grid
|
|
318
|
+
* offers no actions — the same rule as {@link recycleBin}. The fetch is unchanged.
|
|
319
|
+
*/
|
|
320
|
+
parentDeleted: import("@angular/core").InputSignal<boolean>;
|
|
321
|
+
/**
|
|
322
|
+
* The recycle-bin rule (#460), applied here once for every host: while the grid lists `?deleted=only`
|
|
323
|
+
* (or sits under a deleted parent), it offers no New, no default Delete and no custom action, in
|
|
324
|
+
* the toolbar or the row menu — as the detail page does for a row opened from the recycle bin. The
|
|
325
|
+
* server would refuse them anyway: every action judges live rows, and a deleted row is a 404 to it.
|
|
326
|
+
* Restore and Purge are the SoftDelete entry point's own actions, on the row's detail page.
|
|
327
|
+
*/
|
|
328
|
+
readonly recycleBin: import("@angular/core").Signal<boolean>;
|
|
329
|
+
/** Query parameters for the row links; null keeps a plain link. */
|
|
330
|
+
protected readonly rowQueryParams: import("@angular/core").Signal<{
|
|
331
|
+
deleted: "include" | "only";
|
|
332
|
+
} | null>;
|
|
333
|
+
private readonly router;
|
|
334
|
+
private readonly currentUrl;
|
|
335
|
+
/**
|
|
336
|
+
* Navigation state for a row link: this page's URL, so the detail page can return to this list
|
|
337
|
+
* (with its `?deleted=` mode) once the row is deleted or purged. See SparkReturnNavigationService.
|
|
338
|
+
*/
|
|
339
|
+
protected readonly rowLinkState: import("@angular/core").Signal<{
|
|
340
|
+
sparkReturnUrl: string;
|
|
341
|
+
}>;
|
|
342
|
+
/**
|
|
343
|
+
* A click anywhere on a row opens it, like its first-column link — the link used to be the only
|
|
344
|
+
* target, so a row whose first column was empty ("—") could not be opened at all. While rows are
|
|
345
|
+
* selectable a click selects instead, and a double-click opens. Clicks on the link itself or on an
|
|
346
|
+
* interactive element inside the row (a vote button, a checkbox) are theirs, not the row's; a
|
|
347
|
+
* modified click (Ctrl, ⌘, Shift, middle) is left to the browser.
|
|
348
|
+
*/
|
|
349
|
+
protected onRowClick(event: BsDatatableRowEvent<unknown>): void;
|
|
350
|
+
protected onRowDblClick(event: BsDatatableRowEvent<unknown>): void;
|
|
351
|
+
private openRow;
|
|
352
|
+
/**
|
|
353
|
+
* Paging and sorting. Two-way, so a host driving `data` can sort those rows by whatever the
|
|
354
|
+
* user actually clicked — the datatable writes the new sort back through here.
|
|
355
|
+
*/
|
|
356
|
+
settings: import("@angular/core").ModelSignal<DatatableSettings>;
|
|
357
|
+
/** Rows the user has ticked. Two-way so chrome outside the grid can read and clear them. */
|
|
358
|
+
selection: import("@angular/core").ModelSignal<QueryResultItem[]>;
|
|
359
|
+
/**
|
|
360
|
+
* Replaces where the first column's link points, per row.
|
|
361
|
+
*
|
|
362
|
+
* Return `null` to suppress the link for that row — useful when a grid mixes rows that have a
|
|
363
|
+
* detail page with rows that do not.
|
|
364
|
+
*
|
|
365
|
+
* ⚠️ **It changes the destination, not the permission.** `canRead()` still gates whether any
|
|
366
|
+
* link is rendered at all, and this function is never consulted when that gate is closed. It
|
|
367
|
+
* cannot be used to reach a row the rights model withheld; it exists for the case where the
|
|
368
|
+
* row's natural destination is not `/po/{type}/{id}` — a composed row that maps to a page of
|
|
369
|
+
* its own, or a grid embedded in a route that owns its own child paths.
|
|
370
|
+
*/
|
|
371
|
+
rowRoute: import("@angular/core").InputSignal<((row: QueryResultItem) => unknown[] | null) | null>;
|
|
372
|
+
/**
|
|
373
|
+
* Overrides the query's own `selectionMode` (#460, D17) — the detail page passes the sub-query
|
|
374
|
+
* entry's. `null` (the default) defers to the query, whose absent setting is `'auto'`.
|
|
375
|
+
*/
|
|
376
|
+
selectionModeSetting: import("@angular/core").InputSignal<SparkSelectionModeSetting | null>;
|
|
377
|
+
/** Emitted whenever a load or a page fetch fails, for a host in bespoke chrome. */
|
|
378
|
+
error: import("@angular/core").OutputEmitterRef<HttpErrorResponse>;
|
|
379
|
+
rowClicked: import("@angular/core").OutputEmitterRef<QueryResultItem>;
|
|
380
|
+
customActionExecuted: import("@angular/core").OutputEmitterRef<{
|
|
381
|
+
action: CustomActionDefinition;
|
|
382
|
+
}>;
|
|
383
|
+
/** Emitted when the toolbar's New is pressed, just before the grid navigates to the create page. */
|
|
384
|
+
createClicked: import("@angular/core").OutputEmitterRef<void>;
|
|
385
|
+
colors: typeof Color;
|
|
386
|
+
/**
|
|
387
|
+
* Where the first column's link points for this row: the host's `rowRoute` when it supplied one,
|
|
388
|
+
* otherwise the row's own detail page.
|
|
389
|
+
*
|
|
390
|
+
* A method rather than a computed because the answer is per row, and the template already
|
|
391
|
+
* iterates rows — a computed would have to be a map keyed by id, rebuilt on every page.
|
|
392
|
+
*/
|
|
393
|
+
protected rowRouteFor(row: QueryResultItem): unknown[] | null;
|
|
394
|
+
query: import("@angular/core").WritableSignal<SparkQuery | null>;
|
|
395
|
+
entityType: import("@angular/core").WritableSignal<EntityType | null>;
|
|
396
|
+
allEntityTypes: import("@angular/core").WritableSignal<EntityType[]>;
|
|
397
|
+
lookupReferenceOptions: import("@angular/core").WritableSignal<Record<string, LookupReference>>;
|
|
398
|
+
loading: import("@angular/core").WritableSignal<boolean>;
|
|
399
|
+
canRead: import("@angular/core").WritableSignal<boolean>;
|
|
400
|
+
canCreate: import("@angular/core").WritableSignal<boolean>;
|
|
401
|
+
/** The entity type's full rights, for hosts (the query page hands them to its add-on actions). */
|
|
402
|
+
permissions: import("@angular/core").WritableSignal<EntityPermissions | null>;
|
|
403
|
+
resultCount: import("@angular/core").WritableSignal<number | null>;
|
|
404
|
+
customActions: import("@angular/core").WritableSignal<CustomActionDefinition[]>;
|
|
405
|
+
/** The built-in New and Delete the server listed for this caller (#460, D18); see `toolbarActions`. */
|
|
406
|
+
defaultActions: import("@angular/core").WritableSignal<CustomActionDefinition[]>;
|
|
407
|
+
/** Names the server withheld for this RESULT; see QueryResult.disabledActions. */
|
|
408
|
+
private readonly disabledActions;
|
|
409
|
+
/**
|
|
410
|
+
* The actions actually offered for this result.
|
|
411
|
+
*
|
|
412
|
+
* The catalogue at `/spark/actions/{objectTypeId}` is per TYPE and is never told what an
|
|
413
|
+
* execution returned, so an action that applies to only some results cannot be filtered there.
|
|
414
|
+
* The entity's `OnDisableActionsAsync` hook withholds what does not apply to this query (#460,
|
|
415
|
+
* D13), and the answer arrives on the result. The server asks the same hook when an action is
|
|
416
|
+
* submitted from this query and refuses a disabled one with 403.
|
|
417
|
+
*/
|
|
418
|
+
/**
|
|
419
|
+
* Whether to offer "New": the type-level right, unless the result withholds `New` (or `Save`) --
|
|
420
|
+
* the server's OnDisableActionsAsync said so and would refuse the create with 403 (#460, D13).
|
|
421
|
+
* `canCreate` stays the bare right, since hosts read it as exactly that.
|
|
422
|
+
*/
|
|
423
|
+
offersCreate: import("@angular/core").Signal<boolean>;
|
|
424
|
+
visibleCustomActions: import("@angular/core").Signal<CustomActionDefinition[]>;
|
|
425
|
+
fetchFn: import("@angular/core").WritableSignal<BsDatatableFetch<QueryResultItem> | null>;
|
|
426
|
+
/**
|
|
427
|
+
* Why the component renders its own failure instead of only reporting one.
|
|
428
|
+
*
|
|
429
|
+
* `SparkService` is a bare `firstValueFrom` passthrough with no interceptor, so every failure
|
|
430
|
+
* surfaces here and nowhere else. A host embedding this grid cannot surface what it never sees,
|
|
431
|
+
* and the default has to be visible with no host cooperation — hence a rendered alert, not just
|
|
432
|
+
* an output.
|
|
433
|
+
*/
|
|
434
|
+
errorMessage: import("@angular/core").WritableSignal<string | null>;
|
|
435
|
+
/**
|
|
436
|
+
* The rendered selection mode (#460, D17): the host's override (a sub-query entry's
|
|
437
|
+
* `selectionMode`), else the query's own, else `'auto'` — derived from the CUSTOM actions offered,
|
|
438
|
+
* exactly as before the setting existed, so no existing grid changes behaviour. The default Delete
|
|
439
|
+
* does not widen `'auto'`: selection is opt-in, and without it Delete stays reachable per row
|
|
440
|
+
* through the row menu.
|
|
441
|
+
*/
|
|
442
|
+
selectionMode: import("@angular/core").Signal<import("@mintplayer/ng-spark/models").SparkSelectionMode>;
|
|
443
|
+
/**
|
|
444
|
+
* The actions a host renders in its toolbar, in one list (#460, M15): New, Delete and the custom
|
|
445
|
+
* actions, each with the rule that enables it. The query card and the query-list page render this
|
|
446
|
+
* same list, so the two surfaces cannot drift.
|
|
447
|
+
*
|
|
448
|
+
* - New: the default entry's `showedOn` includes the query, the caller holds `New/T`, and the
|
|
449
|
+
* result does not withhold `New`/`Save`.
|
|
450
|
+
* - Delete: likewise with `Delete/T` and `Delete`, and only while rows can be selected (otherwise
|
|
451
|
+
* it could never be enabled — the row menu offers it per row instead).
|
|
452
|
+
* - Custom: `visibleCustomActions()`.
|
|
453
|
+
* - In the recycle bin ({@link recycleBin}) none of the three: the list is empty.
|
|
454
|
+
*/
|
|
455
|
+
toolbarActions: import("@angular/core").Signal<SparkQueryToolbarAction[]>;
|
|
456
|
+
/**
|
|
457
|
+
* The per-row `⋮` menu: every offered action whose rule accepts exactly one row — Delete included,
|
|
458
|
+
* whatever the selection mode. An action without a rule acts on the query, not on a row, and is
|
|
459
|
+
* left to the toolbar.
|
|
460
|
+
*/
|
|
461
|
+
rowActions: import("@angular/core").Signal<SparkQueryToolbarAction[]>;
|
|
462
|
+
/** The default Delete: not withheld by the result, and never in the recycle bin. */
|
|
463
|
+
private offersDelete;
|
|
464
|
+
/** Whether a toolbar action can run with the current selection. The server checks again. */
|
|
465
|
+
isToolbarActionEnabled(action: SparkQueryToolbarAction): boolean;
|
|
466
|
+
/** Runs a toolbar action on the current selection. */
|
|
467
|
+
runToolbarAction(action: SparkQueryToolbarAction): Promise<void>;
|
|
468
|
+
/**
|
|
469
|
+
* The chip's ⊗, offered only for single selection: there the datatable renders no checkbox
|
|
470
|
+
* column, so it has no header deselect-all, and a row click never deselects.
|
|
471
|
+
*/
|
|
472
|
+
clearSelection(): void;
|
|
473
|
+
/** The id of the row whose `⋮` menu is open; at most one is. */
|
|
474
|
+
readonly openRowMenu: import("@angular/core").WritableSignal<string | null>;
|
|
475
|
+
/** Below the toggle, right-aligned; above it when there is no room below. */
|
|
476
|
+
readonly rowMenuPositions: ConnectedPosition[];
|
|
477
|
+
toggleRowMenu(row: QueryResultItem): void;
|
|
478
|
+
/**
|
|
479
|
+
* Closes the open row menu. With a `rowId`, only when that row's menu is the open one: a row's
|
|
480
|
+
* overlay reports its outside click and its detach AFTER another row's toggle has already opened
|
|
481
|
+
* that row's menu, and an unscoped close there shut the menu the user had just opened.
|
|
482
|
+
*/
|
|
483
|
+
closeRowMenu(rowId?: string): void;
|
|
484
|
+
/**
|
|
485
|
+
* A click outside the open menu closes it — except on its own toggle, whose click handler toggles
|
|
486
|
+
* it; closing here as well would reopen it at once.
|
|
487
|
+
*/
|
|
488
|
+
onRowMenuOutsideClick(event: MouseEvent, toggle: HTMLElement, rowId: string): void;
|
|
489
|
+
/** Runs the chosen row-menu item and closes the menu. */
|
|
490
|
+
chooseRowAction(action: SparkQueryToolbarAction, row: QueryResultItem): Promise<void>;
|
|
491
|
+
/**
|
|
492
|
+
* Runs a row-menu action on that ONE row. The checkbox selection is neither read nor changed:
|
|
493
|
+
* the menu is a shortcut for this row, not a second way to tick it.
|
|
494
|
+
*/
|
|
495
|
+
runRowAction(action: SparkQueryToolbarAction, row: QueryResultItem): Promise<void>;
|
|
496
|
+
/**
|
|
497
|
+
* New from this grid: the create page, carrying the sub-query's parent (#460, D19) as query
|
|
498
|
+
* parameters so it survives the navigation and a reload of the create page. The server's
|
|
499
|
+
* `OnNewAsync` receives the parent; its base fills the parent reference.
|
|
500
|
+
*/
|
|
501
|
+
startNew(): void;
|
|
502
|
+
/**
|
|
503
|
+
* The default Delete on `ids`: one request, all rows or none (#460, D18). Asks first — with the
|
|
504
|
+
* entry's `confirmationMessageKey` — then clears the selection and refreshes.
|
|
505
|
+
*/
|
|
506
|
+
deleteRows(ids: string[], definition?: CustomActionDefinition): Promise<void>;
|
|
507
|
+
isVirtualScrolling: import("@angular/core").Signal<boolean>;
|
|
508
|
+
/**
|
|
509
|
+
* Columns as sent with the most recent fetched page.
|
|
510
|
+
*
|
|
511
|
+
* A host binding `data` (streaming) supplies its own via the `columns` input instead — the
|
|
512
|
+
* snapshot carries them once, exactly as a paged result does.
|
|
513
|
+
*/
|
|
514
|
+
private readonly fetchedColumns;
|
|
515
|
+
/** Every column on the wire, drawn or not — what renderers and lookups resolve against. */
|
|
516
|
+
allColumns: import("@angular/core").Signal<QueryColumn[]>;
|
|
517
|
+
/**
|
|
518
|
+
* The columns the grid draws. `isVisible: false` ships a value without a column, so a renderer
|
|
519
|
+
* can read a sibling the grid does not show; undefined means visible, so a server that predates
|
|
520
|
+
* the field still draws everything.
|
|
521
|
+
*/
|
|
522
|
+
visibleColumns: import("@angular/core").Signal<QueryColumn[]>;
|
|
523
|
+
/**
|
|
524
|
+
* True when rows do not come from this component's own fetch.
|
|
525
|
+
*
|
|
526
|
+
* Either because the host bound `data`, or because the query streams — a streaming query's rows
|
|
527
|
+
* arrive over a socket and `/execute` is not a way to get them. The grid recognises the second
|
|
528
|
+
* case itself rather than waiting to be told, because it resolves the query before the host can
|
|
529
|
+
* see it: left to `data` alone, every streaming grid would fire one pointless fetch on mount,
|
|
530
|
+
* before the host had anything to bind.
|
|
531
|
+
*/
|
|
532
|
+
hasExternalData: import("@angular/core").Signal<boolean>;
|
|
533
|
+
/** Whether an action's selection rule is satisfied right now. The server checks it again. */
|
|
534
|
+
isActionEnabled(action: CustomActionDefinition): boolean;
|
|
535
|
+
constructor();
|
|
536
|
+
/**
|
|
537
|
+
* Re-run the query, keeping the current page, sort and scroll position.
|
|
538
|
+
*
|
|
539
|
+
* Data-level on purpose: it re-seeds the fetch closure and nothing else. For a definition
|
|
540
|
+
* change — new columns, a renamed query — the inputs themselves must change; that is the
|
|
541
|
+
* expensive path. Inert when rows come from the host: there is nothing here to re-run.
|
|
542
|
+
*/
|
|
543
|
+
reload(): void;
|
|
544
|
+
private onSearchChanged;
|
|
545
|
+
/**
|
|
546
|
+
* Replaces the fetched columns only when they actually differ.
|
|
547
|
+
*
|
|
548
|
+
* Columns ship **once per result**, so every page fetch returns an identical set. Assigning it
|
|
549
|
+
* unconditionally wrote a new array of new objects into the signal each time, re-rendering every
|
|
550
|
+
* header and re-evaluating every `*bsDatatableColumn` input for no change in content.
|
|
551
|
+
*
|
|
552
|
+
* Compared by serialized value rather than by reference: the objects are freshly deserialized from
|
|
553
|
+
* JSON on every response, so reference equality is always false and would defeat the check. A
|
|
554
|
+
* dozen small objects per fetch is nothing beside the request that produced them.
|
|
555
|
+
*
|
|
556
|
+
* ⚠️ This was written believing it fixed a panel-teardown bug (#431 F7). Measured in a browser: it
|
|
557
|
+
* does not. The columns were already identical on every fetch, so the guard hits every time and the
|
|
558
|
+
* teardown had another cause entirely. Kept because avoiding a pointless re-render of every header
|
|
559
|
+
* on every page is worth having on its own — but it is an optimization, not a fix, and the F7
|
|
560
|
+
* question remains open.
|
|
561
|
+
*/
|
|
562
|
+
private setFetchedColumns;
|
|
563
|
+
/**
|
|
564
|
+
* The per-column filters currently applied (#431).
|
|
565
|
+
*
|
|
566
|
+
* Read inside `makeFetch`'s closure, like `search`, so a change refetches by producing a new fetch
|
|
567
|
+
* identity rather than by being captured.
|
|
568
|
+
*/
|
|
569
|
+
private readonly filters;
|
|
570
|
+
/**
|
|
571
|
+
* The value source behind every column's panel.
|
|
572
|
+
*
|
|
573
|
+
* ⚠️ **Referentially stable, and that is the whole point.** It reads `filters()` when the datatable
|
|
574
|
+
* *calls* it, not when it is built — so it always sees the current filters while never changing
|
|
575
|
+
* identity.
|
|
576
|
+
*
|
|
577
|
+
* This was a `computed` first, on the reasoning that it had to close over the current filters
|
|
578
|
+
* because `DistinctsRequest` carries only `{ column, search, signal }`. That was wrong, and the way
|
|
579
|
+
* it was wrong is worth keeping: a new identity reassigns `[distincts]` on the element, and the
|
|
580
|
+
* component aborts the in-flight request and bumps a generation counter — so a response already on
|
|
581
|
+
* its way is discarded as stale and the list renders empty over a perfectly good answer.
|
|
582
|
+
*
|
|
583
|
+
* Reading the signal at call time removes the race entirely and is simpler besides.
|
|
584
|
+
*
|
|
585
|
+
* The asked-for column's own filter is excluded: a panel must offer the values you could still
|
|
586
|
+
* pick, not only the ones you already picked.
|
|
587
|
+
*/
|
|
588
|
+
/**
|
|
589
|
+
* The last complete distinct list seen per column, for translating a `< none >` selection.
|
|
590
|
+
*
|
|
591
|
+
* ⚠️ Only stored when the server reported the list was NOT truncated (`hasMore === false`). The
|
|
592
|
+
* translation below is the complement of what is listed, so a partial list would exclude the wrong
|
|
593
|
+
* set — and silently, which is the failure mode this whole feature exists to remove.
|
|
594
|
+
*/
|
|
595
|
+
private readonly completeDistincts;
|
|
596
|
+
protected readonly distinctsFn: DatatableDistincts;
|
|
597
|
+
/**
|
|
598
|
+
* Translates one filter change into the wire shape and refetches.
|
|
599
|
+
*
|
|
600
|
+
* The event always arrives as the `'values'` shape because the panel only ever calls
|
|
601
|
+
* `ctx.apply(...)`; comparison mode is never declared. `inverse` is a flag on the event and two
|
|
602
|
+
* arrays on the wire — the translation is this method's whole job.
|
|
603
|
+
*/
|
|
604
|
+
protected onFilterChange(detail: FilterChangeDetail): void;
|
|
605
|
+
/**
|
|
606
|
+
* Back to page 1 and a fresh fetch identity, exactly as a new search term does.
|
|
607
|
+
*
|
|
608
|
+
* Both halves matter: the old page number means nothing against a different result set, and the
|
|
609
|
+
* datatable dedupes reloads by `(page, perPage, sort)` — none of which a filter changes — so
|
|
610
|
+
* without a new fetch identity the request is silently never made.
|
|
611
|
+
*/
|
|
612
|
+
private onFilterChanged;
|
|
613
|
+
/**
|
|
614
|
+
* Runs a custom action on the selection — or on `rowIds` when given (the row menu), which leaves
|
|
615
|
+
* the checkbox selection untouched.
|
|
616
|
+
*/
|
|
617
|
+
onCustomAction(action: CustomActionDefinition, rowIds?: string[]): Promise<void>;
|
|
618
|
+
private reportError;
|
|
619
|
+
/**
|
|
620
|
+
* A 404 is deliberately generic.
|
|
621
|
+
*
|
|
622
|
+
* `Endpoints/Queries/Get.cs` answers 404 with byte-identical bodies for "no such query" and
|
|
623
|
+
* "you may not see it", so existence is not disclosed (security audit M-3). The component
|
|
624
|
+
* therefore genuinely cannot tell them apart, and both "Not found" and "Access denied" would be
|
|
625
|
+
* a guess — one of them leaking, the other misleading.
|
|
626
|
+
*/
|
|
627
|
+
private describe;
|
|
628
|
+
private loadData;
|
|
629
|
+
/**
|
|
630
|
+
* The query's entity type.
|
|
631
|
+
*
|
|
632
|
+
* The source-name fallback is not optional garnish: a `Database.*` query need not declare
|
|
633
|
+
* `entityType`, and the sub-query grid — which matched on the declared name alone — rendered
|
|
634
|
+
* those as an empty card with no columns, no rows and no error, while the identical query
|
|
635
|
+
* rendered correctly as a page. Both grids are this one now, so there is one answer.
|
|
636
|
+
*/
|
|
637
|
+
private resolveEntityType;
|
|
638
|
+
private makeFetch;
|
|
639
|
+
private loadLookupReferenceOptions;
|
|
640
|
+
/**
|
|
641
|
+
* The underlying value a custom renderer receives, which is not the printable one.
|
|
642
|
+
*
|
|
643
|
+
* A projection is flat, so this is the cell's own value rather than a display string. It is
|
|
644
|
+
* deliberately not the attribute-shaped `rendererValue`: a query row has no nested object to
|
|
645
|
+
* fall back to, and reaching for one would hand every renderer `undefined`.
|
|
646
|
+
*/
|
|
647
|
+
rendererValueFor(item: QueryResultItem, column: QueryColumn): unknown;
|
|
648
|
+
getColumnRendererComponent(column: QueryColumn): Type<any> | null;
|
|
649
|
+
/** The renderer's optional filter-label override for this column, or null for the server text. */
|
|
650
|
+
filterLabelFor(column: QueryColumn): ((value: unknown) => string) | null;
|
|
651
|
+
getColumnRendererInputs(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any>;
|
|
652
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryGridComponent, never>;
|
|
653
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkQueryGridComponent, "spark-query-grid", never, {
|
|
654
|
+
"queryId": {
|
|
655
|
+
"alias": "queryId";
|
|
656
|
+
"required": true;
|
|
657
|
+
"isSignal": true;
|
|
658
|
+
};
|
|
659
|
+
"parentId": {
|
|
660
|
+
"alias": "parentId";
|
|
661
|
+
"required": false;
|
|
662
|
+
"isSignal": true;
|
|
663
|
+
};
|
|
664
|
+
"parentType": {
|
|
665
|
+
"alias": "parentType";
|
|
666
|
+
"required": false;
|
|
667
|
+
"isSignal": true;
|
|
668
|
+
};
|
|
669
|
+
"data": {
|
|
670
|
+
"alias": "data";
|
|
671
|
+
"required": false;
|
|
672
|
+
"isSignal": true;
|
|
673
|
+
};
|
|
674
|
+
"search": {
|
|
675
|
+
"alias": "search";
|
|
676
|
+
"required": false;
|
|
677
|
+
"isSignal": true;
|
|
678
|
+
};
|
|
679
|
+
"columns": {
|
|
680
|
+
"alias": "columns";
|
|
681
|
+
"required": false;
|
|
682
|
+
"isSignal": true;
|
|
683
|
+
};
|
|
684
|
+
"reloadToken": {
|
|
685
|
+
"alias": "reloadToken";
|
|
686
|
+
"required": false;
|
|
687
|
+
"isSignal": true;
|
|
688
|
+
};
|
|
689
|
+
"deleted": {
|
|
690
|
+
"alias": "deleted";
|
|
691
|
+
"required": false;
|
|
692
|
+
"isSignal": true;
|
|
693
|
+
};
|
|
694
|
+
"parentDeleted": {
|
|
695
|
+
"alias": "parentDeleted";
|
|
696
|
+
"required": false;
|
|
697
|
+
"isSignal": true;
|
|
698
|
+
};
|
|
699
|
+
"settings": {
|
|
700
|
+
"alias": "settings";
|
|
701
|
+
"required": false;
|
|
702
|
+
"isSignal": true;
|
|
703
|
+
};
|
|
704
|
+
"selection": {
|
|
705
|
+
"alias": "selection";
|
|
706
|
+
"required": false;
|
|
707
|
+
"isSignal": true;
|
|
708
|
+
};
|
|
709
|
+
"rowRoute": {
|
|
710
|
+
"alias": "rowRoute";
|
|
711
|
+
"required": false;
|
|
712
|
+
"isSignal": true;
|
|
713
|
+
};
|
|
714
|
+
"selectionModeSetting": {
|
|
715
|
+
"alias": "selectionModeSetting";
|
|
716
|
+
"required": false;
|
|
717
|
+
"isSignal": true;
|
|
718
|
+
};
|
|
719
|
+
}, {
|
|
720
|
+
"settings": "settingsChange";
|
|
721
|
+
"selection": "selectionChange";
|
|
722
|
+
"error": "error";
|
|
723
|
+
"rowClicked": "rowClicked";
|
|
724
|
+
"customActionExecuted": "customActionExecuted";
|
|
725
|
+
"createClicked": "createClicked";
|
|
726
|
+
}, never, never, true, never>;
|
|
481
727
|
}
|
|
482
|
-
|
|
483
728
|
/**
|
|
484
729
|
* A `<bs-card>` around a {@link SparkQueryGridComponent}: icon, caption, actions, grid.
|
|
485
730
|
*
|
|
@@ -502,61 +747,168 @@ declare class SparkQueryGridComponent {
|
|
|
502
747
|
*
|
|
503
748
|
* Content wins over a forwarded input: the closer declaration is the more specific one.
|
|
504
749
|
*/
|
|
505
|
-
declare class SparkQueryCardComponent {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
750
|
+
export declare class SparkQueryCardComponent {
|
|
751
|
+
readonly lang: SparkLanguageService;
|
|
752
|
+
queryId: import("@angular/core").InputSignal<string>;
|
|
753
|
+
parentId: import("@angular/core").InputSignal<string>;
|
|
754
|
+
parentType: import("@angular/core").InputSignal<string>;
|
|
755
|
+
reloadToken: import("@angular/core").InputSignal<unknown>;
|
|
756
|
+
data: import("@angular/core").InputSignal<QueryResultItem[] | null>;
|
|
757
|
+
/**
|
|
758
|
+
* The initial search term. The header's search box starts from it and the user takes over from
|
|
759
|
+
* there; a new value from the host replaces what was typed.
|
|
760
|
+
*/
|
|
761
|
+
search: import("@angular/core").InputSignal<string>;
|
|
762
|
+
/**
|
|
763
|
+
* Whether the header offers the search box (#460 M15, D17 addendum). On by default, as every
|
|
764
|
+
* Vidyano sub-query tab has one; a card over bound `data` never shows it, because the grid does
|
|
765
|
+
* not refetch bound rows and the box would do nothing.
|
|
766
|
+
*/
|
|
767
|
+
searchable: import("@angular/core").InputSignal<boolean>;
|
|
768
|
+
/** What the grid searches: the host's `search`, until the user types in the header box. */
|
|
769
|
+
readonly searchTerm: import("@angular/core").WritableSignal<string>;
|
|
770
|
+
protected readonly showSearch: import("@angular/core").Signal<boolean>;
|
|
771
|
+
/**
|
|
772
|
+
* Overrides the query's `selectionMode` for this card (#460, D17) — the detail page passes the
|
|
773
|
+
* sub-query entry's. `null` defers to the query (absent there = `'auto'`).
|
|
774
|
+
*/
|
|
775
|
+
selectionMode: import("@angular/core").InputSignal<SparkSelectionModeSetting | null>;
|
|
776
|
+
/**
|
|
777
|
+
* Soft-deletion mode and deleted parent (#460), forwarded to the grid. In the recycle bin — the
|
|
778
|
+
* grid lists `deleted: 'only'`, or its parent row was opened with `?deleted=only` — the card offers
|
|
779
|
+
* no New, Delete or custom action, exactly as the query-list page does. See `recycleBin`.
|
|
780
|
+
*/
|
|
781
|
+
deleted: import("@angular/core").InputSignal<SparkDeletedFilter | null | undefined>;
|
|
782
|
+
parentDeleted: import("@angular/core").InputSignal<boolean>;
|
|
783
|
+
/**
|
|
784
|
+
* Slots forwarded from a host that cannot project content — see the class comment. A card
|
|
785
|
+
* reached through hand-written markup should use the structural directives instead.
|
|
786
|
+
*/
|
|
787
|
+
iconTemplate: import("@angular/core").InputSignal<TemplateRef<any> | null>;
|
|
788
|
+
captionTemplate: import("@angular/core").InputSignal<TemplateRef<any> | null>;
|
|
789
|
+
actionsTemplate: import("@angular/core").InputSignal<TemplateRef<any> | null>;
|
|
790
|
+
error: import("@angular/core").OutputEmitterRef<HttpErrorResponse>;
|
|
791
|
+
rowClicked: import("@angular/core").OutputEmitterRef<QueryResultItem>;
|
|
792
|
+
customActionExecuted: import("@angular/core").OutputEmitterRef<{
|
|
793
|
+
action: CustomActionDefinition;
|
|
794
|
+
}>;
|
|
795
|
+
/**
|
|
796
|
+
* Forwarded to the grid. Without this the escape hatch was unreachable from a card — i.e. from
|
|
797
|
+
* every auto-rendered sub-query and program-unit query page, which is most grids.
|
|
798
|
+
*/
|
|
799
|
+
rowRoute: import("@angular/core").InputSignal<((row: QueryResultItem) => unknown[] | null) | null>;
|
|
800
|
+
colors: typeof Color;
|
|
801
|
+
private readonly iconSlots;
|
|
802
|
+
private readonly captionSlots;
|
|
803
|
+
private readonly actionSlots;
|
|
804
|
+
/**
|
|
805
|
+
* The grid, read only to surface its state — the query, the actions, the selection — to this
|
|
806
|
+
* component's own header.
|
|
807
|
+
*
|
|
808
|
+
* Optional rather than `required` on purpose. The header renders ABOVE the grid in this
|
|
809
|
+
* template, so on the first change-detection pass the view query has not resolved yet and
|
|
810
|
+
* `viewChild.required()` would throw where a plain one returns `undefined`. Everything below
|
|
811
|
+
* therefore reads it defensively; the signal updates once the view initialises and the header
|
|
812
|
+
* re-renders with the real query.
|
|
813
|
+
*
|
|
814
|
+
* A host reads grid state through a template reference variable instead, because a host may put
|
|
815
|
+
* the grid behind an `@if`, where a view query genuinely is intermittently undefined.
|
|
816
|
+
*/
|
|
817
|
+
protected readonly grid: import("@angular/core").Signal<SparkQueryGridComponent | undefined>;
|
|
818
|
+
protected readonly query: import("@angular/core").Signal<import("@mintplayer/ng-spark/models").SparkQuery | null>;
|
|
819
|
+
protected readonly iconTpl: import("@angular/core").Signal<TemplateRef<any> | null>;
|
|
820
|
+
protected readonly captionTpl: import("@angular/core").Signal<TemplateRef<any> | null>;
|
|
821
|
+
protected readonly actionsTpl: import("@angular/core").Signal<TemplateRef<any> | null>;
|
|
822
|
+
/** The caption the card renders unless a slot replaces it. */
|
|
823
|
+
protected readonly caption: import("@angular/core").Signal<string>;
|
|
824
|
+
protected readonly customActions: import("@angular/core").Signal<CustomActionDefinition[]>;
|
|
825
|
+
/**
|
|
826
|
+
* The header's buttons: New, Delete and the custom actions, from the grid (#460, M15) — the same
|
|
827
|
+
* list the query-list page renders.
|
|
828
|
+
*/
|
|
829
|
+
protected readonly toolbarActions: import("@angular/core").Signal<SparkQueryToolbarAction[]>;
|
|
830
|
+
protected actionClass(action: SparkQueryToolbarAction): string;
|
|
831
|
+
protected isEnabled(action: SparkQueryToolbarAction): boolean;
|
|
832
|
+
protected run(action: SparkQueryToolbarAction): void;
|
|
833
|
+
protected readonly selection: import("@angular/core").Signal<QueryResultItem[]>;
|
|
834
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryCardComponent, never>;
|
|
835
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkQueryCardComponent, "spark-query-card", never, {
|
|
836
|
+
"queryId": {
|
|
837
|
+
"alias": "queryId";
|
|
838
|
+
"required": true;
|
|
839
|
+
"isSignal": true;
|
|
840
|
+
};
|
|
841
|
+
"parentId": {
|
|
842
|
+
"alias": "parentId";
|
|
843
|
+
"required": false;
|
|
844
|
+
"isSignal": true;
|
|
845
|
+
};
|
|
846
|
+
"parentType": {
|
|
847
|
+
"alias": "parentType";
|
|
848
|
+
"required": false;
|
|
849
|
+
"isSignal": true;
|
|
850
|
+
};
|
|
851
|
+
"reloadToken": {
|
|
852
|
+
"alias": "reloadToken";
|
|
853
|
+
"required": false;
|
|
854
|
+
"isSignal": true;
|
|
855
|
+
};
|
|
856
|
+
"data": {
|
|
857
|
+
"alias": "data";
|
|
858
|
+
"required": false;
|
|
859
|
+
"isSignal": true;
|
|
860
|
+
};
|
|
861
|
+
"search": {
|
|
862
|
+
"alias": "search";
|
|
863
|
+
"required": false;
|
|
864
|
+
"isSignal": true;
|
|
865
|
+
};
|
|
866
|
+
"searchable": {
|
|
867
|
+
"alias": "searchable";
|
|
868
|
+
"required": false;
|
|
869
|
+
"isSignal": true;
|
|
870
|
+
};
|
|
871
|
+
"selectionMode": {
|
|
872
|
+
"alias": "selectionMode";
|
|
873
|
+
"required": false;
|
|
874
|
+
"isSignal": true;
|
|
875
|
+
};
|
|
876
|
+
"deleted": {
|
|
877
|
+
"alias": "deleted";
|
|
878
|
+
"required": false;
|
|
879
|
+
"isSignal": true;
|
|
880
|
+
};
|
|
881
|
+
"parentDeleted": {
|
|
882
|
+
"alias": "parentDeleted";
|
|
883
|
+
"required": false;
|
|
884
|
+
"isSignal": true;
|
|
885
|
+
};
|
|
886
|
+
"iconTemplate": {
|
|
887
|
+
"alias": "iconTemplate";
|
|
888
|
+
"required": false;
|
|
889
|
+
"isSignal": true;
|
|
890
|
+
};
|
|
891
|
+
"captionTemplate": {
|
|
892
|
+
"alias": "captionTemplate";
|
|
893
|
+
"required": false;
|
|
894
|
+
"isSignal": true;
|
|
895
|
+
};
|
|
896
|
+
"actionsTemplate": {
|
|
897
|
+
"alias": "actionsTemplate";
|
|
898
|
+
"required": false;
|
|
899
|
+
"isSignal": true;
|
|
900
|
+
};
|
|
901
|
+
"rowRoute": {
|
|
902
|
+
"alias": "rowRoute";
|
|
903
|
+
"required": false;
|
|
904
|
+
"isSignal": true;
|
|
905
|
+
};
|
|
906
|
+
}, {
|
|
907
|
+
"error": "error";
|
|
908
|
+
"rowClicked": "rowClicked";
|
|
909
|
+
"customActionExecuted": "customActionExecuted";
|
|
910
|
+
}, ["iconSlots", "captionSlots", "actionSlots"], never, true, never>;
|
|
558
911
|
}
|
|
559
|
-
|
|
560
912
|
/**
|
|
561
913
|
* One cell of a Spark table, wherever that table is.
|
|
562
914
|
*
|
|
@@ -585,52 +937,137 @@ declare class SparkQueryCardComponent {
|
|
|
585
937
|
* gated on `Read`), and it stays in the grid, wrapping this component. Passing both would nest
|
|
586
938
|
* anchors, which is invalid HTML; the grid therefore leaves `link` unset.
|
|
587
939
|
*/
|
|
588
|
-
declare class SparkGridCellComponent {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
940
|
+
export declare class SparkGridCellComponent {
|
|
941
|
+
private readonly renderers;
|
|
942
|
+
/** The column being rendered. Its `dataType` and `renderer` decide everything below. */
|
|
943
|
+
column: import("@angular/core").InputSignal<SparkCellColumn>;
|
|
944
|
+
/**
|
|
945
|
+
* What the caller's value pipe produced: the display text for most columns, and the raw value
|
|
946
|
+
* for `boolean` and `color`, which need the value rather than a rendering of it.
|
|
947
|
+
*/
|
|
948
|
+
display: import("@angular/core").InputSignal<unknown>;
|
|
949
|
+
/**
|
|
950
|
+
* The value handed to a declared custom renderer.
|
|
951
|
+
*
|
|
952
|
+
* Separate from {@link display} because they are not the same thing: a renderer receives the
|
|
953
|
+
* underlying value — for AsDetail, the nested object itself — while `display` has already been
|
|
954
|
+
* flattened to something printable.
|
|
955
|
+
*/
|
|
956
|
+
rendererValue: import("@angular/core").InputSignal<unknown>;
|
|
957
|
+
/** The row, passed through to a custom renderer as `item`. */
|
|
958
|
+
item: import("@angular/core").InputSignal<unknown>;
|
|
959
|
+
/**
|
|
960
|
+
* Pre-resolved chips for a reference-array column, or empty when the column is not one.
|
|
961
|
+
*
|
|
962
|
+
* Resolved by the caller because the label source differs: a query row carries a per-id
|
|
963
|
+
* breadcrumb map, while an AsDetail row's `__sparkBreadcrumbs` is keyed by column name only and
|
|
964
|
+
* so cannot label the members of an array. Rather than render a row of raw ids, an AsDetail
|
|
965
|
+
* caller passes nothing and the cell falls through to text.
|
|
966
|
+
*/
|
|
967
|
+
chips: import("@angular/core").InputSignal<ReferenceChip[]>;
|
|
968
|
+
/** Route for a cell whose value references another entity. See the class comment. */
|
|
969
|
+
link: import("@angular/core").InputSignal<unknown[] | null>;
|
|
970
|
+
protected readonly rendererComponent: import("@angular/core").Signal<import("@angular/core").Type<any> | null>;
|
|
971
|
+
protected readonly rendererInputs: import("@angular/core").Signal<Record<string, any>>;
|
|
972
|
+
/** Null and undefined are distinct from `false` here — see the template. */
|
|
973
|
+
protected readonly isUnsetBoolean: import("@angular/core").Signal<boolean>;
|
|
974
|
+
/**
|
|
975
|
+
* {@link display} when it really is a `Date`, and `null` otherwise.
|
|
976
|
+
*
|
|
977
|
+
* Angular's `DatePipe` does not degrade on a non-date: it **throws**
|
|
978
|
+
* `NG02100: InvalidPipeArgument`, which would take down the whole cell. Both cell pipes
|
|
979
|
+
* deliberately fall back to the raw text for an unparseable date rather than hiding the stored
|
|
980
|
+
* value, so that text reaches this component and must not be piped. A template cannot express
|
|
981
|
+
* `instanceof`, hence the computed.
|
|
982
|
+
*/
|
|
983
|
+
protected readonly dateValue: import("@angular/core").Signal<Date | null>;
|
|
984
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkGridCellComponent, never>;
|
|
985
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkGridCellComponent, "spark-grid-cell", never, {
|
|
986
|
+
"column": {
|
|
987
|
+
"alias": "column";
|
|
988
|
+
"required": true;
|
|
989
|
+
"isSignal": true;
|
|
990
|
+
};
|
|
991
|
+
"display": {
|
|
992
|
+
"alias": "display";
|
|
993
|
+
"required": false;
|
|
994
|
+
"isSignal": true;
|
|
995
|
+
};
|
|
996
|
+
"rendererValue": {
|
|
997
|
+
"alias": "rendererValue";
|
|
998
|
+
"required": false;
|
|
999
|
+
"isSignal": true;
|
|
1000
|
+
};
|
|
1001
|
+
"item": {
|
|
1002
|
+
"alias": "item";
|
|
1003
|
+
"required": false;
|
|
1004
|
+
"isSignal": true;
|
|
1005
|
+
};
|
|
1006
|
+
"chips": {
|
|
1007
|
+
"alias": "chips";
|
|
1008
|
+
"required": false;
|
|
1009
|
+
"isSignal": true;
|
|
1010
|
+
};
|
|
1011
|
+
"link": {
|
|
1012
|
+
"alias": "link";
|
|
1013
|
+
"required": false;
|
|
1014
|
+
"isSignal": true;
|
|
1015
|
+
};
|
|
1016
|
+
}, {}, never, never, true, never>;
|
|
634
1017
|
}
|
|
635
|
-
|
|
636
|
-
export
|
|
1018
|
+
/** How long typing must pause before the term is published, in milliseconds. */
|
|
1019
|
+
export declare const SPARK_SEARCH_DEBOUNCE_MS = 300;
|
|
1020
|
+
/**
|
|
1021
|
+
* The query search box: a magnifier, the input and a clear button (#460 M15, D17 addendum).
|
|
1022
|
+
*
|
|
1023
|
+
* One component for both surfaces that search a query — the query-list page above its grid and the
|
|
1024
|
+
* `<spark-query-card>` header next to its actions, as Vidyano's sub-query tabs have it — so they
|
|
1025
|
+
* behave identically: the same debounce, the same clear button, the same placeholder.
|
|
1026
|
+
*
|
|
1027
|
+
* Two-way bound through `term`, which is what a grid's `search` input takes:
|
|
1028
|
+
*
|
|
1029
|
+
* ```html
|
|
1030
|
+
* <spark-search-box [(term)]="searchTerm" />
|
|
1031
|
+
* <spark-query-grid [search]="searchTerm()" … />
|
|
1032
|
+
* ```
|
|
1033
|
+
*
|
|
1034
|
+
* Typing publishes the term once it has paused for {@link SPARK_SEARCH_DEBOUNCE_MS}, so a word is
|
|
1035
|
+
* one query rather than one per keystroke. Clearing (the ✕ button, or Escape) publishes at once. A
|
|
1036
|
+
* `term` set from outside — a host resetting it — replaces what the box shows.
|
|
1037
|
+
*/
|
|
1038
|
+
export declare class SparkSearchBoxComponent {
|
|
1039
|
+
/** The published search term. Debounced while typing; immediate on clear. */
|
|
1040
|
+
readonly term: import("@angular/core").ModelSignal<string>;
|
|
1041
|
+
/** The input group's size: `sm` for a card header, the default for a page. */
|
|
1042
|
+
readonly size: import("@angular/core").InputSignal<"sm" | "md" | "lg">;
|
|
1043
|
+
/** Overrides {@link SPARK_SEARCH_DEBOUNCE_MS}; `0` publishes on every keystroke. */
|
|
1044
|
+
readonly debounce: import("@angular/core").InputSignal<number>;
|
|
1045
|
+
/** What the input shows, which runs ahead of `term` while the debounce is pending. */
|
|
1046
|
+
protected readonly text: import("@angular/core").WritableSignal<string>;
|
|
1047
|
+
private timer;
|
|
1048
|
+
constructor();
|
|
1049
|
+
protected onInput(value: string): void;
|
|
1050
|
+
/** Empties the box and publishes the empty term at once. */
|
|
1051
|
+
clear(): void;
|
|
1052
|
+
private cancelPending;
|
|
1053
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkSearchBoxComponent, never>;
|
|
1054
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkSearchBoxComponent, "spark-search-box", never, {
|
|
1055
|
+
"term": {
|
|
1056
|
+
"alias": "term";
|
|
1057
|
+
"required": false;
|
|
1058
|
+
"isSignal": true;
|
|
1059
|
+
};
|
|
1060
|
+
"size": {
|
|
1061
|
+
"alias": "size";
|
|
1062
|
+
"required": false;
|
|
1063
|
+
"isSignal": true;
|
|
1064
|
+
};
|
|
1065
|
+
"debounce": {
|
|
1066
|
+
"alias": "debounce";
|
|
1067
|
+
"required": false;
|
|
1068
|
+
"isSignal": true;
|
|
1069
|
+
};
|
|
1070
|
+
}, {
|
|
1071
|
+
"term": "termChange";
|
|
1072
|
+
}, never, never, true, never>;
|
|
1073
|
+
}
|