@mintplayer/ng-spark 22.19.0 → 22.21.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.
@@ -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
- isSortable?: boolean;
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 };
@@ -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
- sortColumns?: SortColumn[];
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
- skip?: number;
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 };