@mintplayer/ng-spark 22.18.0 → 22.20.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/fesm2022/mintplayer-ng-spark-column-filter.mjs +138 -0
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-grid.mjs +122 -4
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +19 -2
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +116 -16
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +23 -0
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/package.json +6 -2
- package/types/mintplayer-ng-spark-column-filter.d.ts +77 -0
- package/types/mintplayer-ng-spark-grid.d.ts +65 -1
- package/types/mintplayer-ng-spark-models.d.ts +64 -2
- package/types/mintplayer-ng-spark-po-edit.d.ts +16 -0
- package/types/mintplayer-ng-spark-po-form.d.ts +59 -5
- package/types/mintplayer-ng-spark-renderers.d.ts +13 -0
- package/types/mintplayer-ng-spark-services.d.ts +35 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DatatableSettings, BsDatatableFetch } from '@mintplayer/ng-bootstrap/datatable';
|
|
1
|
+
import { DatatableSettings, BsDatatableFetch, DatatableDistincts, FilterChangeDetail } from '@mintplayer/ng-bootstrap/datatable';
|
|
2
2
|
import * as _mintplayer_ng_spark_models from '@mintplayer/ng-spark/models';
|
|
3
3
|
import { SparkQuery, EntityType, EntityAttributeDefinition, SparkCellColumn, QueryResultItem, QueryColumn, LookupReference, CustomActionDefinition, PersistentObject } from '@mintplayer/ng-spark/models';
|
|
4
4
|
import * as _angular_core from '@angular/core';
|
|
@@ -46,6 +46,8 @@ declare class SparkGridRenderers {
|
|
|
46
46
|
private readonly sparkService;
|
|
47
47
|
/** The registered column component for a column, or null to fall back to the default cell. */
|
|
48
48
|
columnComponentFor(column: SparkCellColumn): Type<any> | null;
|
|
49
|
+
/** The registered filter-label function for a column, or null to use the server-computed text. */
|
|
50
|
+
filterLabelFor(column: SparkCellColumn): ((value: unknown) => string) | null;
|
|
49
51
|
/**
|
|
50
52
|
* Inputs for a query-grid cell renderer, filtered to what the component actually declares —
|
|
51
53
|
* `NgComponentOutlet` throws on an input the target does not have, which is what lets every
|
|
@@ -371,6 +373,66 @@ declare class SparkQueryGridComponent {
|
|
|
371
373
|
*/
|
|
372
374
|
reload(): void;
|
|
373
375
|
private onSearchChanged;
|
|
376
|
+
/**
|
|
377
|
+
* Replaces the fetched columns only when they actually differ.
|
|
378
|
+
*
|
|
379
|
+
* Columns ship **once per result**, so every page fetch returns an identical set. Assigning it
|
|
380
|
+
* unconditionally wrote a new array of new objects into the signal each time, re-rendering every
|
|
381
|
+
* header and re-evaluating every `*bsDatatableColumn` input for no change in content.
|
|
382
|
+
*
|
|
383
|
+
* Compared by serialized value rather than by reference: the objects are freshly deserialized from
|
|
384
|
+
* JSON on every response, so reference equality is always false and would defeat the check. A
|
|
385
|
+
* dozen small objects per fetch is nothing beside the request that produced them.
|
|
386
|
+
*
|
|
387
|
+
* ⚠️ This was written believing it fixed a panel-teardown bug (#431 F7). Measured in a browser: it
|
|
388
|
+
* does not. The columns were already identical on every fetch, so the guard hits every time and the
|
|
389
|
+
* teardown had another cause entirely. Kept because avoiding a pointless re-render of every header
|
|
390
|
+
* on every page is worth having on its own — but it is an optimization, not a fix, and the F7
|
|
391
|
+
* question remains open.
|
|
392
|
+
*/
|
|
393
|
+
private setFetchedColumns;
|
|
394
|
+
/**
|
|
395
|
+
* The per-column filters currently applied (#431).
|
|
396
|
+
*
|
|
397
|
+
* Read inside `makeFetch`'s closure, like `search`, so a change refetches by producing a new fetch
|
|
398
|
+
* identity rather than by being captured.
|
|
399
|
+
*/
|
|
400
|
+
private readonly filters;
|
|
401
|
+
/**
|
|
402
|
+
* The value source behind every column's panel.
|
|
403
|
+
*
|
|
404
|
+
* ⚠️ **Referentially stable, and that is the whole point.** It reads `filters()` when the datatable
|
|
405
|
+
* *calls* it, not when it is built — so it always sees the current filters while never changing
|
|
406
|
+
* identity.
|
|
407
|
+
*
|
|
408
|
+
* This was a `computed` first, on the reasoning that it had to close over the current filters
|
|
409
|
+
* because `DistinctsRequest` carries only `{ column, search, signal }`. That was wrong, and the way
|
|
410
|
+
* it was wrong is worth keeping: a new identity reassigns `[distincts]` on the element, and the
|
|
411
|
+
* component aborts the in-flight request and bumps a generation counter — so a response already on
|
|
412
|
+
* its way is discarded as stale and the list renders empty over a perfectly good answer.
|
|
413
|
+
*
|
|
414
|
+
* Reading the signal at call time removes the race entirely and is simpler besides.
|
|
415
|
+
*
|
|
416
|
+
* The asked-for column's own filter is excluded: a panel must offer the values you could still
|
|
417
|
+
* pick, not only the ones you already picked.
|
|
418
|
+
*/
|
|
419
|
+
protected readonly distinctsFn: DatatableDistincts;
|
|
420
|
+
/**
|
|
421
|
+
* Translates one filter change into the wire shape and refetches.
|
|
422
|
+
*
|
|
423
|
+
* The event always arrives as the `'values'` shape because the panel only ever calls
|
|
424
|
+
* `ctx.apply(...)`; comparison mode is never declared. `inverse` is a flag on the event and two
|
|
425
|
+
* arrays on the wire — the translation is this method's whole job.
|
|
426
|
+
*/
|
|
427
|
+
protected onFilterChange(detail: FilterChangeDetail): void;
|
|
428
|
+
/**
|
|
429
|
+
* Back to page 1 and a fresh fetch identity, exactly as a new search term does.
|
|
430
|
+
*
|
|
431
|
+
* Both halves matter: the old page number means nothing against a different result set, and the
|
|
432
|
+
* datatable dedupes reloads by `(page, perPage, sort)` — none of which a filter changes — so
|
|
433
|
+
* without a new fetch identity the request is silently never made.
|
|
434
|
+
*/
|
|
435
|
+
private onFilterChanged;
|
|
374
436
|
onCustomAction(action: CustomActionDefinition): Promise<void>;
|
|
375
437
|
private reportError;
|
|
376
438
|
/**
|
|
@@ -403,6 +465,8 @@ declare class SparkQueryGridComponent {
|
|
|
403
465
|
*/
|
|
404
466
|
rendererValueFor(item: QueryResultItem, column: QueryColumn): unknown;
|
|
405
467
|
getColumnRendererComponent(column: QueryColumn): Type<any> | null;
|
|
468
|
+
/** The renderer's optional filter-label override for this column, or null for the server text. */
|
|
469
|
+
filterLabelFor(column: QueryColumn): ((value: unknown) => string) | null;
|
|
406
470
|
getColumnRendererInputs(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any>;
|
|
407
471
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkQueryGridComponent, never>;
|
|
408
472
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkQueryGridComponent, "spark-query-grid", never, { "queryId": { "alias": "queryId"; "required": true; "isSignal": true; }; "parentId": { "alias": "parentId"; "required": false; "isSignal": true; }; "parentType": { "alias": "parentType"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "search": { "alias": "search"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "reloadToken": { "alias": "reloadToken"; "required": false; "isSignal": true; }; "settings": { "alias": "settings"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "rowRoute": { "alias": "rowRoute"; "required": false; "isSignal": true; }; }, { "settings": "settingsChange"; "selection": "selectionChange"; "error": "error"; "rowClicked": "rowClicked"; "customActionExecuted": "customActionExecuted"; }, never, never, true, never>;
|
|
@@ -352,7 +352,26 @@ interface SparkCellColumn {
|
|
|
352
352
|
/** One column of a query result, sent once rather than repeated on every row. */
|
|
353
353
|
interface QueryColumn extends SparkCellColumn {
|
|
354
354
|
order: number;
|
|
355
|
-
|
|
355
|
+
/**
|
|
356
|
+
* Whether the grid offers a sort affordance for this column. Resolved server-side from the query's
|
|
357
|
+
* override then the attribute, so it arrives already decided.
|
|
358
|
+
*
|
|
359
|
+
* This replaced an `isSortable` that carried the server's AsDetail *drag-reorder* flag — a
|
|
360
|
+
* different concept that was `false` for every scalar column while the grid hard-coded every
|
|
361
|
+
* header sortable anyway. Neither side read it. The attribute-level `isSortable` on `EntityType`
|
|
362
|
+
* is the drag-reorder flag and stays.
|
|
363
|
+
*
|
|
364
|
+
* Absent means sortable, matching `isVisible`: a server predating the field still draws arrows.
|
|
365
|
+
*/
|
|
366
|
+
canSort?: boolean;
|
|
367
|
+
/** Whether the grid draws a filter cell for this column. Absent means filterable. */
|
|
368
|
+
canFilter?: boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Whether this column's distinct values may be listed. When `false` and `canFilter` is true the
|
|
371
|
+
* panel offers a free-text filter instead of a value list — listing a column's values is a much
|
|
372
|
+
* stronger disclosure than filtering by one already known.
|
|
373
|
+
*/
|
|
374
|
+
canListDistincts?: boolean;
|
|
356
375
|
/**
|
|
357
376
|
* Whether the grid draws this column. `false` means the row carries the value but no column is
|
|
358
377
|
* rendered — for a renderer that needs a sibling value (a lock glyph beside a name) without
|
|
@@ -429,6 +448,49 @@ declare function valueFor(item: SparkRow | null | undefined, columnName: string)
|
|
|
429
448
|
declare function isQueryRow(row: SparkRow | null | undefined): row is QueryResultItem;
|
|
430
449
|
/** Whether this row is a full persistent object. Discriminated on elements, as above. */
|
|
431
450
|
declare function isPersistentObject(row: SparkRow | null | undefined): row is PersistentObject;
|
|
451
|
+
/**
|
|
452
|
+
* One column's value filter (#431): the values a caller picked, or the values they excluded.
|
|
453
|
+
*
|
|
454
|
+
* **Values, never labels.** Each entry is the raw stored value — the same `value` the distinct
|
|
455
|
+
* endpoint returned, never the `label` beside it. A reference column's values are document ids while
|
|
456
|
+
* its labels are resolved breadcrumb text, and two rows can legitimately render the same text, so
|
|
457
|
+
* matching on labels would be both wrong and ambiguous.
|
|
458
|
+
*
|
|
459
|
+
* `includes` and `excludes` are the two halves of the inverse toggle rather than a flag: the panel
|
|
460
|
+
* moves values between them. `null` is a real, selectable value meaning "no value"; an empty or
|
|
461
|
+
* absent array is the absent filter.
|
|
462
|
+
*/
|
|
463
|
+
interface QueryColumnFilter {
|
|
464
|
+
name: string;
|
|
465
|
+
includes?: unknown[];
|
|
466
|
+
excludes?: unknown[];
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* One selectable entry in a column's filter panel.
|
|
470
|
+
*
|
|
471
|
+
* Structurally identical to the datatable's own `DistinctValue`, deliberately — it is what lets the
|
|
472
|
+
* HTTP response be handed straight to `[distincts]` with no mapper in between.
|
|
473
|
+
*/
|
|
474
|
+
interface DistinctValue {
|
|
475
|
+
/** The raw stored value. `null` is a real entry meaning "no value", not an absent one. */
|
|
476
|
+
value: unknown;
|
|
477
|
+
/** What the user reads. Never matched on. */
|
|
478
|
+
label: string;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* A column's distinct values.
|
|
482
|
+
*
|
|
483
|
+
* `remaining` is always empty from this server: the datatable snapshots the list when a selection is
|
|
484
|
+
* first made and derives both buckets itself by diffing. The server answers "what matches now".
|
|
485
|
+
*
|
|
486
|
+
* `hasMore` reports that the cap truncated the list, and the panel re-queries only when it is set or
|
|
487
|
+
* the search term widens — so a dishonest `false` strands a user typing past the cap.
|
|
488
|
+
*/
|
|
489
|
+
interface DistinctValuesResult {
|
|
490
|
+
matching: DistinctValue[];
|
|
491
|
+
remaining: DistinctValue[];
|
|
492
|
+
hasMore: boolean;
|
|
493
|
+
}
|
|
432
494
|
|
|
433
495
|
interface ProgramUnit {
|
|
434
496
|
id: string;
|
|
@@ -882,4 +944,4 @@ interface EvaluableAttribute {
|
|
|
882
944
|
declare function evaluateRules(attr: EvaluableAttribute, value: any): RuleFailure[];
|
|
883
945
|
|
|
884
946
|
export { AS_DETAIL_BREADCRUMBS_KEY, AS_DETAIL_ORIGINAL_DATES_KEY, AS_DETAIL_ROW_KEY, AS_DETAIL_SELF_BREADCRUMB_KEY, ELookupDisplayType, EReferenceDisplayType, ShowedOn, applyOverlay, currentLanguage, dictToNestedPo, evaluateRules, filterQueryActions, fromDateInput, fromDateInputValue, fromDateTimeLocalInput, hasShowedOnFlag, isDateDataType, isPersistentObject, isQueryRow, isReservedAsDetailKey, mergeRefreshValues, nestedPoToDict, nestedPoToDisplayRow, overlayFromResponse, parseSelectionRule, parseWireDate, resolveTranslation, resolvedBreadcrumb, selectionModeFor, selfBreadcrumb, toDateInput, toDateInputValue, toDateTimeLocalInput, valueFor, wireDatesEqual };
|
|
885
|
-
export type { AttributeGroup, AttributeOverlay, AttributeTab, CustomActionDefinition, EntityAttributeDefinition, EntityPermissions, EntityType, EntityTypeResolver, EvaluableAttribute, LookupReference, LookupReferenceListItem, LookupReferenceValue, PersistentObject, PersistentObjectAttribute, PersistentObjectPermissions, ProgramUnit, ProgramUnitGroup, ProgramUnitsConfiguration, QueryColumn, QueryResult, QueryResultItem, QueryResultItemValue, RefreshOverlay, RefreshedOption, RetryActionPayload, RetryActionResult, RuleFailure, SparkCellColumn, SparkQuery, SparkQueryRenderMode, SparkQuerySortColumn, SparkRow, SparkSelectionMode, StreamingErrorMessage, StreamingMessage, StreamingPatchItem, StreamingPatchMessage, StreamingSnapshotMessage, TranslatedString, ValidationError, ValidationErrorResponse, ValidationRule };
|
|
947
|
+
export type { AttributeGroup, AttributeOverlay, AttributeTab, CustomActionDefinition, DistinctValue, DistinctValuesResult, EntityAttributeDefinition, EntityPermissions, EntityType, EntityTypeResolver, EvaluableAttribute, LookupReference, LookupReferenceListItem, LookupReferenceValue, PersistentObject, PersistentObjectAttribute, PersistentObjectPermissions, ProgramUnit, ProgramUnitGroup, ProgramUnitsConfiguration, QueryColumn, QueryColumnFilter, QueryResult, QueryResultItem, QueryResultItemValue, RefreshOverlay, RefreshedOption, RetryActionPayload, RetryActionResult, RuleFailure, SparkCellColumn, SparkQuery, SparkQueryRenderMode, SparkQuerySortColumn, SparkRow, SparkSelectionMode, StreamingErrorMessage, StreamingMessage, StreamingPatchItem, StreamingPatchMessage, StreamingSnapshotMessage, TranslatedString, ValidationError, ValidationErrorResponse, ValidationRule };
|
|
@@ -28,6 +28,22 @@ declare class SparkPoEditComponent {
|
|
|
28
28
|
constructor();
|
|
29
29
|
private onParamsChange;
|
|
30
30
|
initFormData(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Resolves a nested AsDetail type by CLR name, for rebuilding the nested PO wire shape on save.
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ <b>`detailTypes` first, catalogue second.</b> The catalogue from `/spark/types` is
|
|
35
|
+
* <b>Query-gated</b>, and an AsDetail row type usually has no rights of its own — nobody grants
|
|
36
|
+
* `Query/GateSettings`, because a gate is edited through the Repository that owns it. So the
|
|
37
|
+
* catalogue does not contain it, the resolver returned undefined, and the save quietly took the
|
|
38
|
+
* scalar branch: the attribute went out as a raw dict under `value` instead of a nested PO under
|
|
39
|
+
* `object`, the server could not map it, and `EntityMapper`'s conversion `catch` swallowed the
|
|
40
|
+
* failure. The save reported success and wrote nothing.
|
|
41
|
+
* <para>
|
|
42
|
+
* `detailTypes` is the parent's own copy of its row types, carried on the type definition for
|
|
43
|
+
* exactly this reason (#385 fixed the rendering half; this is the save half). It is gated on the
|
|
44
|
+
* parent's right, which is the right that governs editing the row anyway.
|
|
45
|
+
* </para>
|
|
46
|
+
*/
|
|
31
47
|
private resolveEntityType;
|
|
32
48
|
/**
|
|
33
49
|
* The attributes this page will read values from when it builds the save.
|
|
@@ -56,6 +56,17 @@ declare class RefreshCoordinator {
|
|
|
56
56
|
trigger(attributeName: string): Promise<void>;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* A refresh a form embedded in another form is asking its host to issue on its behalf.
|
|
61
|
+
*
|
|
62
|
+
* `immediate` mirrors the distinction the host's own editors make: a discrete editor fires on
|
|
63
|
+
* change, free text only marks itself pending and fires on blur.
|
|
64
|
+
*/
|
|
65
|
+
interface NestedTriggerRequest {
|
|
66
|
+
/** The full path the server addresses, e.g. `Gate.ProjectMode`. */
|
|
67
|
+
path: string;
|
|
68
|
+
immediate: boolean;
|
|
69
|
+
}
|
|
59
70
|
declare class SparkPoFormComponent {
|
|
60
71
|
private readonly sparkService;
|
|
61
72
|
private readonly translations;
|
|
@@ -76,6 +87,18 @@ declare class SparkPoFormComponent {
|
|
|
76
87
|
objectTypeId: _angular_core.InputSignal<string | undefined>;
|
|
77
88
|
/** The id of the object being edited; absent for a create. */
|
|
78
89
|
objectId: _angular_core.InputSignal<string | undefined>;
|
|
90
|
+
/**
|
|
91
|
+
* Set when this form renders a single embedded AsDetail object inside a host form: the name of
|
|
92
|
+
* the attribute holding it, e.g. `"Gate"`. Presence of a prefix switches the form from issuing
|
|
93
|
+
* its own refreshes to reporting them upward, because an embedded object is not something the
|
|
94
|
+
* server can be asked about on its own — the request must describe, and be authorized against,
|
|
95
|
+
* the object that owns it.
|
|
96
|
+
*/
|
|
97
|
+
triggerPathPrefix: _angular_core.InputSignal<string | null>;
|
|
98
|
+
/** Raised instead of self-issuing when {@link triggerPathPrefix} is set. */
|
|
99
|
+
nestedTriggerRequested: _angular_core.OutputEmitterRef<NestedTriggerRequest>;
|
|
100
|
+
/** Blur counterpart, flushing a trigger the host only marked pending. */
|
|
101
|
+
nestedTriggerBlurred: _angular_core.OutputEmitterRef<string>;
|
|
79
102
|
/**
|
|
80
103
|
* What the last refresh changed about each attribute's presentation, keyed by attribute name.
|
|
81
104
|
*
|
|
@@ -176,9 +199,8 @@ declare class SparkPoFormComponent {
|
|
|
176
199
|
/**
|
|
177
200
|
* The single funnel every scalar / boolean / inline-cell edit passes through.
|
|
178
201
|
*
|
|
179
|
-
* `attr` is optional
|
|
180
|
-
*
|
|
181
|
-
* no refresh can fire.
|
|
202
|
+
* `attr` is optional because some editors have nothing useful to say about which attribute moved.
|
|
203
|
+
* A caller that knows should always say so — without it no refresh can fire.
|
|
182
204
|
*/
|
|
183
205
|
onFieldChange(attr?: EntityAttributeDefinition): void;
|
|
184
206
|
/**
|
|
@@ -187,8 +209,27 @@ declare class SparkPoFormComponent {
|
|
|
187
209
|
* addressing scheme being invented for it.
|
|
188
210
|
*/
|
|
189
211
|
onInlineCellChange(attr: EntityAttributeDefinition, rowIndex: number, col: EntityAttributeDefinition): void;
|
|
190
|
-
/**
|
|
212
|
+
/**
|
|
213
|
+
* Which embedded target the in-flight refresh belongs to, if any.
|
|
214
|
+
*
|
|
215
|
+
* ⚠️ Tagged, not a nullable `rowIndex`. The two arms write to different places — a row inside
|
|
216
|
+
* `formData`, versus the modal's working copy in `asDetailFormData` — and an index that happens
|
|
217
|
+
* to be absent is not the same statement as "this attribute holds one object". With a nullable
|
|
218
|
+
* index, a row refresh carrying a bad index would fall silently into the object arm.
|
|
219
|
+
*/
|
|
191
220
|
private pendingNestedTrigger;
|
|
221
|
+
/**
|
|
222
|
+
* A trigger inside a single embedded AsDetail object, raised by the modal's recursive form.
|
|
223
|
+
*
|
|
224
|
+
* The child form does not issue the request itself, for two reasons that both bite. Its
|
|
225
|
+
* `entityType` is the embedded type, so a payload built there describes `GateSettings` while the
|
|
226
|
+
* request must describe the Repository that owns it. And nested AsDetail types carry no rights of
|
|
227
|
+
* their own — the server authorizes a nested refresh on the OWNING type — so a child-issued
|
|
228
|
+
* request would be asking the wrong question of security.json.
|
|
229
|
+
*/
|
|
230
|
+
onEmbeddedTrigger(attributeName: string, event: NestedTriggerRequest): void;
|
|
231
|
+
/** Blur counterpart of {@link onEmbeddedTrigger}, for the child's free-text editors. */
|
|
232
|
+
onEmbeddedTriggerBlur(path: string): void;
|
|
192
233
|
/**
|
|
193
234
|
* Applies a refresh that ran against a detail row: the row's own values, and the column metadata
|
|
194
235
|
* for the grid it lives in.
|
|
@@ -204,6 +245,8 @@ declare class SparkPoFormComponent {
|
|
|
204
245
|
/** Blur handler for free-text editors — sends the refresh their keystrokes only marked pending. */
|
|
205
246
|
onFieldBlur(attr: EntityAttributeDefinition): void;
|
|
206
247
|
private noteChange;
|
|
248
|
+
/** `Gate.ProjectMode` — the index-free counterpart of the inline grid's `Jobs[1].Kind`. */
|
|
249
|
+
private nestedTriggerPath;
|
|
207
250
|
private canRefresh;
|
|
208
251
|
/**
|
|
209
252
|
* Per-instance, never a service: the retry-action modal renders its own `spark-po-form`, and a
|
|
@@ -212,6 +255,16 @@ declare class SparkPoFormComponent {
|
|
|
212
255
|
*/
|
|
213
256
|
protected readonly refreshCoordinator: RefreshCoordinator;
|
|
214
257
|
private buildRefreshPayload;
|
|
258
|
+
/**
|
|
259
|
+
* The values to post, with the open modal's working copy substituted for the attribute it edits.
|
|
260
|
+
*
|
|
261
|
+
* ⚠️ Without this the server receives the embedded object as it was when the modal opened — `{}`
|
|
262
|
+
* for a gate that has never been set — and the hook decides against values the user cannot see it
|
|
263
|
+
* ignoring. `formData` deliberately does not hold the in-progress edit (cancelling the modal has
|
|
264
|
+
* to discard it), so the refresh has to reach into `asDetailFormData` instead. Only the attribute
|
|
265
|
+
* under edit is substituted; everything else is the form's own state.
|
|
266
|
+
*/
|
|
267
|
+
private embeddedValues;
|
|
215
268
|
/**
|
|
216
269
|
* Folds replaced option lists into the signals the editors already read, so a refreshed dropdown
|
|
217
270
|
* renders through the same path as a loaded one.
|
|
@@ -278,7 +331,7 @@ declare class SparkPoFormComponent {
|
|
|
278
331
|
removeArrayItem(attr: EntityAttributeDefinition, index: number): Promise<void>;
|
|
279
332
|
onAsDetailReorder(attr: EntityAttributeDefinition, event: CdkDragDrop<Record<string, any>[]>): void;
|
|
280
333
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkPoFormComponent, never>;
|
|
281
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkPoFormComponent, "spark-po-form", never, { "entityType": { "alias": "entityType"; "required": false; "isSignal": true; }; "formData": { "alias": "formData"; "required": false; "isSignal": true; }; "validationErrors": { "alias": "validationErrors"; "required": false; "isSignal": true; }; "showButtons": { "alias": "showButtons"; "required": false; "isSignal": true; }; "isSaving": { "alias": "isSaving"; "required": false; "isSignal": true; }; "parentId": { "alias": "parentId"; "required": false; "isSignal": true; }; "parentType": { "alias": "parentType"; "required": false; "isSignal": true; }; "objectTypeId": { "alias": "objectTypeId"; "required": false; "isSignal": true; }; "objectId": { "alias": "objectId"; "required": false; "isSignal": true; }; "refreshOverlay": { "alias": "refreshOverlay"; "required": false; "isSignal": true; }; }, { "formData": "formDataChange"; "save": "save"; "cancel": "cancel"; "refreshOverlay": "refreshOverlayChange"; }, never, never, true, never>;
|
|
334
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkPoFormComponent, "spark-po-form", never, { "entityType": { "alias": "entityType"; "required": false; "isSignal": true; }; "formData": { "alias": "formData"; "required": false; "isSignal": true; }; "validationErrors": { "alias": "validationErrors"; "required": false; "isSignal": true; }; "showButtons": { "alias": "showButtons"; "required": false; "isSignal": true; }; "isSaving": { "alias": "isSaving"; "required": false; "isSignal": true; }; "parentId": { "alias": "parentId"; "required": false; "isSignal": true; }; "parentType": { "alias": "parentType"; "required": false; "isSignal": true; }; "objectTypeId": { "alias": "objectTypeId"; "required": false; "isSignal": true; }; "objectId": { "alias": "objectId"; "required": false; "isSignal": true; }; "triggerPathPrefix": { "alias": "triggerPathPrefix"; "required": false; "isSignal": true; }; "refreshOverlay": { "alias": "refreshOverlay"; "required": false; "isSignal": true; }; }, { "formData": "formDataChange"; "save": "save"; "cancel": "cancel"; "nestedTriggerRequested": "nestedTriggerRequested"; "nestedTriggerBlurred": "nestedTriggerBlurred"; "refreshOverlay": "refreshOverlayChange"; }, never, never, true, never>;
|
|
282
335
|
}
|
|
283
336
|
|
|
284
337
|
/**
|
|
@@ -357,3 +410,4 @@ declare class SparkLookupPickerComponent {
|
|
|
357
410
|
}
|
|
358
411
|
|
|
359
412
|
export { SparkLookupPickerComponent, SparkPoFormComponent, SparkReferencePickerComponent };
|
|
413
|
+
export type { NestedTriggerRequest };
|
|
@@ -101,6 +101,19 @@ interface SparkAttributeRendererRegistration {
|
|
|
101
101
|
columnComponent?: Type<any> | null;
|
|
102
102
|
/** Optional component for create/edit forms. Must implement SparkAttributeEditRenderer. When omitted, the default input is used. */
|
|
103
103
|
editComponent?: Type<any>;
|
|
104
|
+
/**
|
|
105
|
+
* Relabels this column's values in a filter panel (#431).
|
|
106
|
+
*
|
|
107
|
+
* A renderer is a component that paints arbitrary DOM, and a distinct value has no row, so it
|
|
108
|
+
* cannot be instantiated to produce text for a filter list. The label therefore defaults to the
|
|
109
|
+
* server-computed cell text: a status rendered as a coloured pill lists `Active`, a rating
|
|
110
|
+
* rendered as stars lists `3`. This is the escape for when that is too raw — a value stored as
|
|
111
|
+
* `2` whose cell reads "High priority".
|
|
112
|
+
*
|
|
113
|
+
* ⚠️ A **pure function**: no DOM, no component instantiation, no row context. There is no row to
|
|
114
|
+
* give it, which is the whole reason the renderer itself cannot be used here.
|
|
115
|
+
*/
|
|
116
|
+
filterLabel?: (value: unknown) => string;
|
|
104
117
|
}
|
|
105
118
|
declare const SPARK_ATTRIBUTE_RENDERERS: InjectionToken<SparkAttributeRendererRegistration[]>;
|
|
106
119
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { RetryActionPayload, RetryActionResult, TranslatedString, StreamingMessage, EntityType, EntityPermissions, SparkQuery, QueryResult, ProgramUnitsConfiguration, PersistentObject, CustomActionDefinition, LookupReferenceListItem, LookupReference, LookupReferenceValue } from '@mintplayer/ng-spark/models';
|
|
2
|
+
import { RetryActionPayload, RetryActionResult, TranslatedString, StreamingMessage, QueryColumnFilter, EntityType, EntityPermissions, SparkQuery, QueryResult, DistinctValuesResult, ProgramUnitsConfiguration, PersistentObject, CustomActionDefinition, LookupReferenceListItem, LookupReference, LookupReferenceValue } from '@mintplayer/ng-spark/models';
|
|
3
3
|
import { Observable } from 'rxjs';
|
|
4
4
|
import { SortColumn } from '@mintplayer/pagination';
|
|
5
5
|
import { SafeHtml } from '@angular/platform-browser';
|
|
@@ -96,14 +96,23 @@ declare class SparkService {
|
|
|
96
96
|
* lifetime; the service is scoped to the app, so a permission change lands on the next load.
|
|
97
97
|
*/
|
|
98
98
|
getQueryByName(name: string): Promise<SparkQuery | undefined>;
|
|
99
|
-
executeQuery(queryId: string, options?:
|
|
100
|
-
|
|
99
|
+
executeQuery(queryId: string, options?: ExecuteQueryOptions): Promise<QueryResult>;
|
|
100
|
+
/**
|
|
101
|
+
* The distinct values behind one column's filter panel (#431).
|
|
102
|
+
*
|
|
103
|
+
* `columns` carries the OTHER columns' current filters, so the values returned are the ones still
|
|
104
|
+
* reachable — offering a value that empties the grid the moment it is picked is worse than
|
|
105
|
+
* omitting it.
|
|
106
|
+
*
|
|
107
|
+
* An empty result means either "nothing matches" or "you may not enumerate this column". The two
|
|
108
|
+
* are deliberately indistinguishable, so there is nothing for a caller to branch on.
|
|
109
|
+
*/
|
|
110
|
+
getDistinctValues(queryId: string, column: string, options?: {
|
|
111
|
+
search?: string;
|
|
112
|
+
columns?: QueryColumnFilter[];
|
|
101
113
|
parentId?: string;
|
|
102
114
|
parentType?: string;
|
|
103
|
-
|
|
104
|
-
take?: number;
|
|
105
|
-
search?: string;
|
|
106
|
-
}): Promise<QueryResult>;
|
|
115
|
+
}): Promise<DistinctValuesResult>;
|
|
107
116
|
/**
|
|
108
117
|
* Runs a query identified by name.
|
|
109
118
|
*
|
|
@@ -112,14 +121,7 @@ declare class SparkService {
|
|
|
112
121
|
* that the list was cut. A picker that omits the option you are looking for, and says nothing, is
|
|
113
122
|
* worse than one that fails.
|
|
114
123
|
*/
|
|
115
|
-
executeQueryByName(queryName: string, options?:
|
|
116
|
-
parentId?: string;
|
|
117
|
-
parentType?: string;
|
|
118
|
-
skip?: number;
|
|
119
|
-
take?: number;
|
|
120
|
-
search?: string;
|
|
121
|
-
sortColumns?: SortColumn[];
|
|
122
|
-
}): Promise<QueryResult>;
|
|
124
|
+
executeQueryByName(queryName: string, options?: ExecuteQueryOptions): Promise<QueryResult>;
|
|
123
125
|
getProgramUnits(): Promise<ProgramUnitsConfiguration>;
|
|
124
126
|
get(type: string, id: string): Promise<PersistentObject>;
|
|
125
127
|
create(type: string, data: Partial<PersistentObject>): Promise<PersistentObject>;
|
|
@@ -196,6 +198,23 @@ declare class SparkService {
|
|
|
196
198
|
static ɵfac: i0.ɵɵFactoryDeclaration<SparkService, never>;
|
|
197
199
|
static ɵprov: i0.ɵɵInjectableDeclaration<SparkService>;
|
|
198
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* The options every query execution takes.
|
|
203
|
+
*
|
|
204
|
+
* Extracted because `executeQueryByName` forwards to `executeQuery`, and while both spelled their
|
|
205
|
+
* options as separate inline literals a field added to one silently failed to forward from the
|
|
206
|
+
* other — which is how skip/take/search were once dropped for every reference picker.
|
|
207
|
+
*/
|
|
208
|
+
interface ExecuteQueryOptions {
|
|
209
|
+
sortColumns?: SortColumn[];
|
|
210
|
+
parentId?: string;
|
|
211
|
+
parentType?: string;
|
|
212
|
+
skip?: number;
|
|
213
|
+
take?: number;
|
|
214
|
+
search?: string;
|
|
215
|
+
/** Per-column value filters (#431). Columns AND together; values within a column OR. */
|
|
216
|
+
columns?: QueryColumnFilter[];
|
|
217
|
+
}
|
|
199
218
|
|
|
200
219
|
/**
|
|
201
220
|
* R2-M12: SVG icon registry. The registry no longer accepts a raw string —
|
|
@@ -319,4 +338,4 @@ declare const sparkTimezoneInterceptor: HttpInterceptorFn;
|
|
|
319
338
|
declare function withSparkTimezone(): HttpFeature<HttpFeatureKind>[];
|
|
320
339
|
|
|
321
340
|
export { RetryActionService, SPARK_TIMEZONE_HEADER, SparkIconRegistry, SparkLanguageService, SparkQueryActionsService, SparkService, SparkStreamingService, resolveBrowserTimeZone, sparkTimezoneInterceptor, withSparkTimezone };
|
|
322
|
-
export type { DeleteRowOptions, NewObjectOptions };
|
|
341
|
+
export type { DeleteRowOptions, ExecuteQueryOptions, NewObjectOptions };
|