@mintplayer/ng-spark 22.12.0 → 22.13.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-grid.mjs +16 -2
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +73 -0
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/package.json +1 -1
- package/types/mintplayer-ng-spark-grid.d.ts +10 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +38 -2
|
@@ -333,12 +333,26 @@ class SparkGridCellComponent {
|
|
|
333
333
|
/** Null and undefined are distinct from `false` here — see the template. */
|
|
334
334
|
isUnsetBoolean = computed(() => this.display() == null, /* @ts-ignore */
|
|
335
335
|
...(ngDevMode ? [{ debugName: "isUnsetBoolean" }] : /* istanbul ignore next */ []));
|
|
336
|
+
/**
|
|
337
|
+
* {@link display} when it really is a `Date`, and `null` otherwise.
|
|
338
|
+
*
|
|
339
|
+
* Angular's `DatePipe` does not degrade on a non-date: it **throws**
|
|
340
|
+
* `NG02100: InvalidPipeArgument`, which would take down the whole cell. Both cell pipes
|
|
341
|
+
* deliberately fall back to the raw text for an unparseable date rather than hiding the stored
|
|
342
|
+
* value, so that text reaches this component and must not be piped. A template cannot express
|
|
343
|
+
* `instanceof`, hence the computed.
|
|
344
|
+
*/
|
|
345
|
+
dateValue = computed(() => {
|
|
346
|
+
const value = this.display();
|
|
347
|
+
return value instanceof Date && !Number.isNaN(value.getTime()) ? value : null;
|
|
348
|
+
}, /* @ts-ignore */
|
|
349
|
+
...(ngDevMode ? [{ debugName: "dateValue" }] : /* istanbul ignore next */ []));
|
|
336
350
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkGridCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
337
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkGridCellComponent, isStandalone: true, selector: "spark-grid-cell", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, rendererValue: { classPropertyName: "rendererValue", publicName: "rendererValue", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, chips: { classPropertyName: "chips", publicName: "chips", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (rendererComponent(); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: rendererInputs()\"></ng-container>\n} @else if (column().dataType === 'boolean') {\n <!-- [indeterminate] matters: without it a null boolean renders as an unchecked box, which reads\n as an explicit `false`. One of the three copies of this cell bound it and the others had\n drifted, so the same column said different things on a detail page and in a grid. -->\n <input type=\"checkbox\"\n [checked]=\"display() === true\"\n [indeterminate]=\"isUnsetBoolean()\"\n disabled\n onclick=\"return false;\">\n} @else if (column().dataType === 'color') {\n @if (display(); as colorVal) {\n <!-- Shares `.spark-color-swatch` with the detail page, which is where the sizing already\n lived. It used to be inline here because the grid rendered inside <mp-datatable>'s\n shadow root, where neither this component's scoped rules nor Bootstrap's arrived;\n ng-bootstrap 22.18.0 moved the datatable to the light DOM, so the class reaches it. -->\n <span class=\"spark-color-swatch d-inline-block align-middle border rounded\"\n [style.background-color]=\"colorVal\"></span>\n }\n} @else if (column().dataType === 'image') {\n @if (display(); as src) {\n <!-- `alt` is empty on purpose \u2014 the cell is decorative next to the row's own labelled\n columns, and a filename read aloud is worse than nothing. -->\n <img [src]=\"src\" alt=\"\" loading=\"lazy\" class=\"spark-grid-image align-middle rounded\">\n }\n} @else if (column().dataType === 'url') {\n @if (display(); as href) {\n <!-- rel is not optional with target=_blank: without noopener the opened page gets a handle on\n this one through window.opener, and these hrefs are data. -->\n <a [href]=\"href\" target=\"_blank\" rel=\"noopener noreferrer\">{{ href }}</a>\n }\n} @else if (chips().length) {\n <span class=\"d-inline-flex flex-wrap gap-1\">\n @for (chip of chips(); track chip.id) {\n <span class=\"spark-chip\">{{ chip.label }}</span>\n }\n </span>\n} @else if (link(); as route) {\n <a [routerLink]=\"route\">{{ display() }}</a>\n} @else {\n {{ display() }}\n}\n", styles: [".spark-chip{display:inline-block;padding:.35em .9em;font-size:.8125em;font-weight:600;line-height:1.4;white-space:nowrap;text-align:center;vertical-align:baseline;color:var(--bs-body-color);background-color:var(--bs-secondary-bg);border:1px solid var(--bs-border-color);border-radius:50rem;text-decoration:none}a.spark-chip:hover,a.spark-chip:focus-visible{background-color:var(--bs-tertiary-bg)}.spark-color-swatch{width:1.5em;height:1.5em}.spark-grid-image{max-height:2.5em;max-width:100%;object-fit:contain}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
351
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkGridCellComponent, isStandalone: true, selector: "spark-grid-cell", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, rendererValue: { classPropertyName: "rendererValue", publicName: "rendererValue", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, chips: { classPropertyName: "chips", publicName: "chips", isSignal: true, isRequired: false, transformFunction: null }, link: { classPropertyName: "link", publicName: "link", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (rendererComponent(); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: rendererInputs()\"></ng-container>\n} @else if (column().dataType === 'boolean') {\n <!-- [indeterminate] matters: without it a null boolean renders as an unchecked box, which reads\n as an explicit `false`. One of the three copies of this cell bound it and the others had\n drifted, so the same column said different things on a detail page and in a grid. -->\n <input type=\"checkbox\"\n [checked]=\"display() === true\"\n [indeterminate]=\"isUnsetBoolean()\"\n disabled\n onclick=\"return false;\">\n} @else if (column().dataType === 'date' || column().dataType === 'datetime') {\n <!--\n Formatted in ONE place for both grids. Before this, a date column printed whatever its pipe\n produced, which was the raw ISO string \u2014 `2026-09-07T13:25:57.3119825Z` in a table cell. Both\n cell pipes now hand over a real Date, and `date:` accepts a string too, so an unparseable value\n that fell back to text still renders as that text rather than blank.\n -->\n @if (dateValue(); as when) {\n {{ when | date:(column().dataType === 'date' ? 'mediumDate' : 'short') }}\n } @else {\n {{ display() }}\n }\n} @else if (column().dataType === 'color') {\n @if (display(); as colorVal) {\n <!-- Shares `.spark-color-swatch` with the detail page, which is where the sizing already\n lived. It used to be inline here because the grid rendered inside <mp-datatable>'s\n shadow root, where neither this component's scoped rules nor Bootstrap's arrived;\n ng-bootstrap 22.18.0 moved the datatable to the light DOM, so the class reaches it. -->\n <span class=\"spark-color-swatch d-inline-block align-middle border rounded\"\n [style.background-color]=\"colorVal\"></span>\n }\n} @else if (column().dataType === 'image') {\n @if (display(); as src) {\n <!-- `alt` is empty on purpose \u2014 the cell is decorative next to the row's own labelled\n columns, and a filename read aloud is worse than nothing. -->\n <img [src]=\"src\" alt=\"\" loading=\"lazy\" class=\"spark-grid-image align-middle rounded\">\n }\n} @else if (column().dataType === 'url') {\n @if (display(); as href) {\n <!-- rel is not optional with target=_blank: without noopener the opened page gets a handle on\n this one through window.opener, and these hrefs are data. -->\n <a [href]=\"href\" target=\"_blank\" rel=\"noopener noreferrer\">{{ href }}</a>\n }\n} @else if (chips().length) {\n <span class=\"d-inline-flex flex-wrap gap-1\">\n @for (chip of chips(); track chip.id) {\n <span class=\"spark-chip\">{{ chip.label }}</span>\n }\n </span>\n} @else if (link(); as route) {\n <a [routerLink]=\"route\">{{ display() }}</a>\n} @else {\n {{ display() }}\n}\n", styles: [".spark-chip{display:inline-block;padding:.35em .9em;font-size:.8125em;font-weight:600;line-height:1.4;white-space:nowrap;text-align:center;vertical-align:baseline;color:var(--bs-body-color);background-color:var(--bs-secondary-bg);border:1px solid var(--bs-border-color);border-radius:50rem;text-decoration:none}a.spark-chip:hover,a.spark-chip:focus-visible{background-color:var(--bs-tertiary-bg)}.spark-color-swatch{width:1.5em;height:1.5em}.spark-grid-image{max-height:2.5em;max-width:100%;object-fit:contain}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
338
352
|
}
|
|
339
353
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkGridCellComponent, decorators: [{
|
|
340
354
|
type: Component,
|
|
341
|
-
args: [{ selector: 'spark-grid-cell', imports: [CommonModule, NgComponentOutlet, RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (rendererComponent(); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: rendererInputs()\"></ng-container>\n} @else if (column().dataType === 'boolean') {\n <!-- [indeterminate] matters: without it a null boolean renders as an unchecked box, which reads\n as an explicit `false`. One of the three copies of this cell bound it and the others had\n drifted, so the same column said different things on a detail page and in a grid. -->\n <input type=\"checkbox\"\n [checked]=\"display() === true\"\n [indeterminate]=\"isUnsetBoolean()\"\n disabled\n onclick=\"return false;\">\n} @else if (column().dataType === 'color') {\n @if (display(); as colorVal) {\n <!-- Shares `.spark-color-swatch` with the detail page, which is where the sizing already\n lived. It used to be inline here because the grid rendered inside <mp-datatable>'s\n shadow root, where neither this component's scoped rules nor Bootstrap's arrived;\n ng-bootstrap 22.18.0 moved the datatable to the light DOM, so the class reaches it. -->\n <span class=\"spark-color-swatch d-inline-block align-middle border rounded\"\n [style.background-color]=\"colorVal\"></span>\n }\n} @else if (column().dataType === 'image') {\n @if (display(); as src) {\n <!-- `alt` is empty on purpose \u2014 the cell is decorative next to the row's own labelled\n columns, and a filename read aloud is worse than nothing. -->\n <img [src]=\"src\" alt=\"\" loading=\"lazy\" class=\"spark-grid-image align-middle rounded\">\n }\n} @else if (column().dataType === 'url') {\n @if (display(); as href) {\n <!-- rel is not optional with target=_blank: without noopener the opened page gets a handle on\n this one through window.opener, and these hrefs are data. -->\n <a [href]=\"href\" target=\"_blank\" rel=\"noopener noreferrer\">{{ href }}</a>\n }\n} @else if (chips().length) {\n <span class=\"d-inline-flex flex-wrap gap-1\">\n @for (chip of chips(); track chip.id) {\n <span class=\"spark-chip\">{{ chip.label }}</span>\n }\n </span>\n} @else if (link(); as route) {\n <a [routerLink]=\"route\">{{ display() }}</a>\n} @else {\n {{ display() }}\n}\n", styles: [".spark-chip{display:inline-block;padding:.35em .9em;font-size:.8125em;font-weight:600;line-height:1.4;white-space:nowrap;text-align:center;vertical-align:baseline;color:var(--bs-body-color);background-color:var(--bs-secondary-bg);border:1px solid var(--bs-border-color);border-radius:50rem;text-decoration:none}a.spark-chip:hover,a.spark-chip:focus-visible{background-color:var(--bs-tertiary-bg)}.spark-color-swatch{width:1.5em;height:1.5em}.spark-grid-image{max-height:2.5em;max-width:100%;object-fit:contain}\n"] }]
|
|
355
|
+
args: [{ selector: 'spark-grid-cell', imports: [CommonModule, NgComponentOutlet, RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (rendererComponent(); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: rendererInputs()\"></ng-container>\n} @else if (column().dataType === 'boolean') {\n <!-- [indeterminate] matters: without it a null boolean renders as an unchecked box, which reads\n as an explicit `false`. One of the three copies of this cell bound it and the others had\n drifted, so the same column said different things on a detail page and in a grid. -->\n <input type=\"checkbox\"\n [checked]=\"display() === true\"\n [indeterminate]=\"isUnsetBoolean()\"\n disabled\n onclick=\"return false;\">\n} @else if (column().dataType === 'date' || column().dataType === 'datetime') {\n <!--\n Formatted in ONE place for both grids. Before this, a date column printed whatever its pipe\n produced, which was the raw ISO string \u2014 `2026-09-07T13:25:57.3119825Z` in a table cell. Both\n cell pipes now hand over a real Date, and `date:` accepts a string too, so an unparseable value\n that fell back to text still renders as that text rather than blank.\n -->\n @if (dateValue(); as when) {\n {{ when | date:(column().dataType === 'date' ? 'mediumDate' : 'short') }}\n } @else {\n {{ display() }}\n }\n} @else if (column().dataType === 'color') {\n @if (display(); as colorVal) {\n <!-- Shares `.spark-color-swatch` with the detail page, which is where the sizing already\n lived. It used to be inline here because the grid rendered inside <mp-datatable>'s\n shadow root, where neither this component's scoped rules nor Bootstrap's arrived;\n ng-bootstrap 22.18.0 moved the datatable to the light DOM, so the class reaches it. -->\n <span class=\"spark-color-swatch d-inline-block align-middle border rounded\"\n [style.background-color]=\"colorVal\"></span>\n }\n} @else if (column().dataType === 'image') {\n @if (display(); as src) {\n <!-- `alt` is empty on purpose \u2014 the cell is decorative next to the row's own labelled\n columns, and a filename read aloud is worse than nothing. -->\n <img [src]=\"src\" alt=\"\" loading=\"lazy\" class=\"spark-grid-image align-middle rounded\">\n }\n} @else if (column().dataType === 'url') {\n @if (display(); as href) {\n <!-- rel is not optional with target=_blank: without noopener the opened page gets a handle on\n this one through window.opener, and these hrefs are data. -->\n <a [href]=\"href\" target=\"_blank\" rel=\"noopener noreferrer\">{{ href }}</a>\n }\n} @else if (chips().length) {\n <span class=\"d-inline-flex flex-wrap gap-1\">\n @for (chip of chips(); track chip.id) {\n <span class=\"spark-chip\">{{ chip.label }}</span>\n }\n </span>\n} @else if (link(); as route) {\n <a [routerLink]=\"route\">{{ display() }}</a>\n} @else {\n {{ display() }}\n}\n", styles: [".spark-chip{display:inline-block;padding:.35em .9em;font-size:.8125em;font-weight:600;line-height:1.4;white-space:nowrap;text-align:center;vertical-align:baseline;color:var(--bs-body-color);background-color:var(--bs-secondary-bg);border:1px solid var(--bs-border-color);border-radius:50rem;text-decoration:none}a.spark-chip:hover,a.spark-chip:focus-visible{background-color:var(--bs-tertiary-bg)}.spark-color-swatch{width:1.5em;height:1.5em}.spark-grid-image{max-height:2.5em;max-width:100%;object-fit:contain}\n"] }]
|
|
342
356
|
}], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], rendererValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "rendererValue", required: false }] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], chips: [{ type: i0.Input, args: [{ isSignal: true, alias: "chips", required: false }] }], link: [{ type: i0.Input, args: [{ isSignal: true, alias: "link", required: false }] }] } });
|
|
343
357
|
|
|
344
358
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-grid.mjs","sources":["../../grid/src/spark-grid-columns.ts","../../grid/src/spark-grid-renderers.ts","../../grid/src/spark-query-slots.ts","../../grid/src/spark-grid-cell.component.ts","../../grid/src/spark-grid-cell.component.html","../../grid/src/spark-query-grid.component.ts","../../grid/src/spark-query-grid.component.html","../../grid/src/spark-query-card.component.ts","../../grid/src/spark-query-card.component.html","../../grid/mintplayer-ng-spark-grid.ts"],"sourcesContent":["import { DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';\nimport { SortColumn } from '@mintplayer/pagination';\nimport {\n EntityAttributeDefinition,\n EntityType,\n ShowedOn,\n SparkQuery,\n hasShowedOnFlag,\n} from '@mintplayer/ng-spark/models';\n\n/** Page sizes offered by every Spark grid. */\nexport const SPARK_GRID_PAGE_SIZES = [10, 25, 50];\n\n/**\n * The attributes a grid shows, in display order.\n *\n * Shared so the two grids cannot disagree about what \"visible\" means — they each had their own\n * copy of this expression, which is the kind of thing that stays identical right up until it\n * doesn't.\n */\nexport function visibleGridAttributes(entityType: EntityType | null): EntityAttributeDefinition[] {\n return entityType?.attributes\n .filter(a => a.isVisible && hasShowedOnFlag(a.showedOn, ShowedOn.Query))\n .sort((a, b) => a.order - b.order) ?? [];\n}\n\n/**\n * Initial datatable settings for a query, seeded with the query's declared sort.\n *\n * The datatable owns paging and sorting from here on and calls the fetch callback per page; this\n * only decides where it starts.\n */\nexport function initialGridSettings(query: SparkQuery | null): DatatableSettings {\n // Nullable because one caller resolves its query from a route param and may not have one yet;\n // an unsorted grid is the right fallback, not a crash.\n const sortColumns: SortColumn[] = (query?.sortColumns || []).map(sc => ({\n property: sc.property,\n direction: sc.direction === 'desc' ? 'descending' as const : 'ascending' as const,\n }));\n\n return new DatatableSettings({\n perPage: { values: SPARK_GRID_PAGE_SIZES, selected: SPARK_GRID_PAGE_SIZES[0] },\n page: { values: [1], selected: 1 },\n sortColumns,\n });\n}\n\n/** Whether a query renders as a virtual-scrolling grid rather than a paged one. */\nexport function isVirtualScrollingQuery(query: SparkQuery | null): boolean {\n return query?.renderMode === 'VirtualScrolling';\n}\n","import { inject, Injectable, Type } from '@angular/core';\nimport {\n EntityAttributeDefinition,\n LookupReference,\n QueryColumn,\n QueryResultItem,\n SparkCellColumn,\n valueFor,\n} from '@mintplayer/ng-spark/models';\nimport { SPARK_ATTRIBUTE_RENDERERS, cellValue, withDeclaredInputs } from '@mintplayer/ng-spark/renderers';\nimport { SparkService } from '@mintplayer/ng-spark/services';\n\n/**\n * Renderer lookup and lookup-reference loading for a Spark grid.\n *\n * This was extracted when `spark-query-list` and `spark-sub-query` were two components holding\n * byte-identical copies of it — around 120 lines between them. That duplication was not a\n * tidiness complaint: it produced drift. The two copies disagreed about `[indeterminate]`, about\n * resetting permission state, about whether a fetch failure surfaces or is swallowed, and about\n * virtual-scroll sizing — four user-visible bugs, each fixed on one side and not the other.\n *\n * There is now one grid, {@link SparkQueryGridComponent}, so the drift cannot recur. This stays\n * separate because it is stateless service-shaped logic rather than view state, and because it is\n * what a custom grid would need in order to render Spark cells at all.\n */\n@Injectable({ providedIn: 'root' })\nexport class SparkGridRenderers {\n private readonly registry = inject(SPARK_ATTRIBUTE_RENDERERS);\n private readonly sparkService = inject(SparkService);\n\n /** The registered column component for a column, or null to fall back to the default cell. */\n columnComponentFor(column: SparkCellColumn): Type<any> | null {\n if (!column.renderer) return null;\n return this.registry.find(r => r.name === column.renderer)?.columnComponent ?? null;\n }\n\n /**\n * Inputs for a query-grid cell renderer, filtered to what the component actually declares —\n * `NgComponentOutlet` throws on an input the target does not have, which is what lets every\n * member of the renderer contract be optional.\n */\n columnInputsFor(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any> {\n return this.cellInputsFor(component, cellValue(valueFor(item, column.name)), column, item);\n }\n\n /**\n * The same contract for a row that is not a query result — an AsDetail sub-table row, which is\n * a plain dictionary of embedded values with no id and no column metadata of its own, so its\n * value cannot be read the way {@link columnInputsFor} reads one.\n *\n * Only the extraction differs; the renderer contract is identical, and stating it once is what\n * stops the two from drifting the way the cell markup already had.\n */\n cellInputsFor(component: Type<any>, value: unknown, column: SparkCellColumn, item: unknown): Record<string, any> {\n return withDeclaredInputs(component, {\n value,\n column,\n options: column.rendererOptions,\n item,\n });\n }\n\n /**\n * Loads every lookup reference the visible columns need, in one pass.\n *\n * Returns an empty map rather than throwing when there are none, so callers never branch on it.\n */\n async loadLookupOptions(columns: readonly (SparkCellColumn | EntityAttributeDefinition)[]): Promise<Record<string, LookupReference>> {\n const lookupColumns = columns.filter(c => c.lookupReferenceType);\n if (lookupColumns.length === 0) return {};\n\n const names = [...new Set(lookupColumns.map(c => c.lookupReferenceType!))];\n const entries = await Promise.all(\n names.map(async name => [name, await this.sparkService.getLookupReference(name)] as const),\n );\n return entries.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {} as Record<string, LookupReference>);\n }\n}\n","import { Directive, inject, input, TemplateRef } from '@angular/core';\nimport { CustomActionDefinition, PersistentObject, SparkQuery } from '@mintplayer/ng-spark/models';\n\n/**\n * Header slots for `<spark-query-card>`.\n *\n * Each directive marks a template that REPLACES one region of the card header. Supplying one\n * leaves the other two alone — that is the whole point of having three rather than the single\n * whole-header template they replace, where changing the icon meant re-implementing the caption\n * and the action bar as well.\n *\n * An omitted slot is not an empty slot: the card renders its default. This is what keeps the\n * auto-rendered sub-query working. A sub-query is rendered from `EntityTypeDefinition.Queries`\n * with no host to project into, so a mechanism that only ever REPLACED chrome would leave that\n * call site with nothing — which is why an earlier design had the query declare its own chrome\n * server-side. Overriding a default needs no host; replacing one does.\n *\n * The two ends of that are visible in the defaults themselves. Neither `SparkQuery` nor\n * `EntityType` carries an icon, so the server has nothing to say and the slot is the only\n * source. Actions are the mirror image: the server declares them per type, so the default is\n * the real answer and the slot is a rare override.\n *\n * Naming follows ng-bootstrap's `*bsDatatableColumn` convention — prefix, component, slot —\n * with `spark`, since these are ng-spark directives and `bs` is another package's prefix. These\n * are the first attribute directives in ng-spark; every existing selector is an element.\n *\n * ## Targeting one query\n *\n * Each slot takes an optional query alias or id as its value. A detail page renders one card per\n * entry in `EntityTypeDefinition.Queries`, so a host that supplies a bare slot would decorate\n * every one of them identically — rarely what is wanted. A targeted slot applies to that query;\n * an untargeted one is the fallback for the rest.\n *\n * ```html\n * <span *sparkQueryIcon=\"'cars'\"><spark-icon name=\"car-front\" /></span>\n * <span *sparkQueryIcon><spark-icon name=\"table\" /></span>\n * ```\n *\n * Matching is case-insensitive, against the query's alias and then its id. This is the\n * `bsPriorityNavItem` shape: a value input aliased to the selector, collected with\n * `contentChildren`.\n */\n\n/** Resolves a slot list to the one that applies to a query: targeted first, then untargeted. */\nexport function slotFor<T extends { forQuery: () => string }>(\n slots: readonly T[],\n query: SparkQuery | null,\n): T | null {\n if (!slots.length) return null;\n\n const matches = (target: string) =>\n !!target && (\n target.localeCompare(query?.alias ?? '', undefined, { sensitivity: 'accent' }) === 0 ||\n target.localeCompare(query?.id ?? '', undefined, { sensitivity: 'accent' }) === 0);\n\n // A targeted slot wins over the catch-all even when it is declared later: \"this one query\"\n // is the more specific statement, and declaration order in a template is not a priority.\n return slots.find(s => matches(s.forQuery())) ?? slots.find(s => !s.forQuery()) ?? null;\n}\n\n/**\n * The icon at the header's leading edge. No default: nothing in the model describes one.\n *\n * ```html\n * <spark-query-card [queryId]=\"'cars'\">\n * <spark-icon *sparkQueryIcon name=\"car-front\" />\n * </spark-query-card>\n * ```\n */\n@Directive({ selector: '[sparkQueryIcon]' })\nexport class SparkQueryIconDirective {\n readonly templateRef = inject<TemplateRef<SparkQuerySlotContext>>(TemplateRef);\n\n /** Query alias or id this slot applies to. Empty targets every query on the page. */\n readonly forQuery = input('', { alias: 'sparkQueryIcon' });\n\n static ngTemplateContextGuard(\n _dir: SparkQueryIconDirective,\n ctx: unknown,\n ): ctx is SparkQuerySlotContext {\n return true;\n }\n}\n\n/**\n * The header caption. Defaults to the query's translated description, falling back to its name.\n *\n * The context carries that resolved default as `$implicit`, so a host can decorate it — add a\n * count, a badge — without re-resolving the translation itself.\n */\n@Directive({ selector: '[sparkQueryCaption]' })\nexport class SparkQueryCaptionDirective {\n readonly templateRef = inject<TemplateRef<SparkQueryCaptionContext>>(TemplateRef);\n\n readonly forQuery = input('', { alias: 'sparkQueryCaption' });\n\n static ngTemplateContextGuard(\n _dir: SparkQueryCaptionDirective,\n ctx: unknown,\n ): ctx is SparkQueryCaptionContext {\n return true;\n }\n}\n\n/**\n * The buttons at the header's trailing edge. Defaults to the server-declared custom actions.\n *\n * The context carries those actions and the current selection, so a host that wants its own\n * buttons ALONGSIDE the server's can render both rather than choosing. Without that, overriding\n * this slot to add one button would silently drop every action the type declares — and the\n * server's actions are the ones carrying `selectionRule` and the permission filter.\n *\n * ```html\n * <ng-container *sparkQueryActions=\"let actions; selection as rows\">\n * <button (click)=\"export(rows)\">Export</button>\n * </ng-container>\n * ```\n */\n@Directive({ selector: '[sparkQueryActions]' })\nexport class SparkQueryActionsDirective {\n readonly templateRef = inject<TemplateRef<SparkQueryActionsContext>>(TemplateRef);\n\n readonly forQuery = input('', { alias: 'sparkQueryActions' });\n\n static ngTemplateContextGuard(\n _dir: SparkQueryActionsDirective,\n ctx: unknown,\n ): ctx is SparkQueryActionsContext {\n return true;\n }\n}\n\n/** Context for the icon slot: the query whose card is being rendered. */\nexport class SparkQuerySlotContext {\n $implicit: SparkQuery | null = null;\n}\n\nexport class SparkQueryCaptionContext {\n /** The caption the card would have rendered: description, or the query name. */\n $implicit = '';\n query: SparkQuery | null = null;\n}\n\nexport class SparkQueryActionsContext {\n /** The custom actions the card would have rendered, already filtered for this query. */\n $implicit: CustomActionDefinition[] = [];\n /** Rows currently ticked. Empty unless an action is selection-gated. */\n selection: PersistentObject[] = [];\n query: SparkQuery | null = null;\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport { CommonModule, NgComponentOutlet } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { EntityAttributeDefinition, SparkCellColumn } from '@mintplayer/ng-spark/models';\nimport { ReferenceChip } from '@mintplayer/ng-spark/pipes';\nimport { SparkGridRenderers } from './spark-grid-renderers';\n\n/**\n * One cell of a Spark table, wherever that table is.\n *\n * ## Why this exists\n *\n * The cell markup was written out three times: twice in the query grids (since merged into\n * {@link SparkQueryGridComponent}) and once more in the AsDetail table on the PO detail page. The\n * third copy was never counted, and it had already drifted — a `boolean` column rendered the text\n * `\"true\"` there while the grid rendered a checkbox, a `color` rendered its hex string rather than\n * a swatch, and a custom renderer was dispatched by a second, hand-copied lookup.\n *\n * ## What it does and does not own\n *\n * It owns **presentation**: which control a `dataType` becomes, and dispatching a declared custom\n * renderer. It does not own **value resolution**, and deliberately so — the two callers read from\n * genuinely different row models. A query row is a `PersistentObject` with an attribute list and\n * an id; an AsDetail row is a plain dictionary of embedded values with neither. Trying to unify\n * that would put a second row-access path inside this component and buy nothing.\n *\n * So the caller resolves the value with whichever pipe fits its row model, and passes the result.\n *\n * ## The two links are not the same link, and only one is here\n *\n * `link` is for a cell whose own value points at another entity — an AsDetail reference column.\n * The query grid's first-column link is a different rule (it points at the row's own detail page,\n * gated on `Read`), and it stays in the grid, wrapping this component. Passing both would nest\n * anchors, which is invalid HTML; the grid therefore leaves `link` unset.\n */\n@Component({\n selector: 'spark-grid-cell',\n imports: [CommonModule, NgComponentOutlet, RouterModule],\n templateUrl: './spark-grid-cell.component.html',\n styleUrl: './spark-grid-cell.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkGridCellComponent {\n private readonly renderers = inject(SparkGridRenderers);\n\n /** The column being rendered. Its `dataType` and `renderer` decide everything below. */\n column = input.required<SparkCellColumn>();\n\n /**\n * What the caller's value pipe produced: the display text for most columns, and the raw value\n * for `boolean` and `color`, which need the value rather than a rendering of it.\n */\n display = input<unknown>(null);\n\n /**\n * The value handed to a declared custom renderer.\n *\n * Separate from {@link display} because they are not the same thing: a renderer receives the\n * underlying value — for AsDetail, the nested object itself — while `display` has already been\n * flattened to something printable.\n */\n rendererValue = input<unknown>(null);\n\n /** The row, passed through to a custom renderer as `item`. */\n item = input<unknown>(null);\n\n /**\n * Pre-resolved chips for a reference-array column, or empty when the column is not one.\n *\n * Resolved by the caller because the label source differs: a query row carries a per-id\n * breadcrumb map, while an AsDetail row's `__sparkBreadcrumbs` is keyed by column name only and\n * so cannot label the members of an array. Rather than render a row of raw ids, an AsDetail\n * caller passes nothing and the cell falls through to text.\n */\n chips = input<ReferenceChip[]>([]);\n\n /** Route for a cell whose value references another entity. See the class comment. */\n link = input<unknown[] | null>(null);\n\n protected readonly rendererComponent = computed(() => this.renderers.columnComponentFor(this.column()));\n\n protected readonly rendererInputs = computed(() => {\n const component = this.rendererComponent();\n return component\n ? this.renderers.cellInputsFor(component, this.rendererValue(), this.column(), this.item())\n : {};\n });\n\n /** Null and undefined are distinct from `false` here — see the template. */\n protected readonly isUnsetBoolean = computed(() => this.display() == null);\n}\n","@if (rendererComponent(); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: rendererInputs()\"></ng-container>\n} @else if (column().dataType === 'boolean') {\n <!-- [indeterminate] matters: without it a null boolean renders as an unchecked box, which reads\n as an explicit `false`. One of the three copies of this cell bound it and the others had\n drifted, so the same column said different things on a detail page and in a grid. -->\n <input type=\"checkbox\"\n [checked]=\"display() === true\"\n [indeterminate]=\"isUnsetBoolean()\"\n disabled\n onclick=\"return false;\">\n} @else if (column().dataType === 'color') {\n @if (display(); as colorVal) {\n <!-- Shares `.spark-color-swatch` with the detail page, which is where the sizing already\n lived. It used to be inline here because the grid rendered inside <mp-datatable>'s\n shadow root, where neither this component's scoped rules nor Bootstrap's arrived;\n ng-bootstrap 22.18.0 moved the datatable to the light DOM, so the class reaches it. -->\n <span class=\"spark-color-swatch d-inline-block align-middle border rounded\"\n [style.background-color]=\"colorVal\"></span>\n }\n} @else if (column().dataType === 'image') {\n @if (display(); as src) {\n <!-- `alt` is empty on purpose — the cell is decorative next to the row's own labelled\n columns, and a filename read aloud is worse than nothing. -->\n <img [src]=\"src\" alt=\"\" loading=\"lazy\" class=\"spark-grid-image align-middle rounded\">\n }\n} @else if (column().dataType === 'url') {\n @if (display(); as href) {\n <!-- rel is not optional with target=_blank: without noopener the opened page gets a handle on\n this one through window.opener, and these hrefs are data. -->\n <a [href]=\"href\" target=\"_blank\" rel=\"noopener noreferrer\">{{ href }}</a>\n }\n} @else if (chips().length) {\n <span class=\"d-inline-flex flex-wrap gap-1\">\n @for (chip of chips(); track chip.id) {\n <span class=\"spark-chip\">{{ chip.label }}</span>\n }\n </span>\n} @else if (link(); as route) {\n <a [routerLink]=\"route\">{{ display() }}</a>\n} @else {\n {{ display() }}\n}\n","import { ChangeDetectionStrategy, Component, computed, effect, inject, input, model, output, signal, untracked, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { RouterModule } from '@angular/router';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, DatatableSettings, type BsDatatableFetch } from '@mintplayer/ng-bootstrap/datatable';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SparkQueryRefreshService } from '@mintplayer/ng-spark/client-operations';\nimport { cellValue } from '@mintplayer/ng-spark/renderers';\nimport { QueryCellValuePipe, QueryReferenceChipsPipe, ResolveTranslationPipe, TranslateKeyPipe } from '@mintplayer/ng-spark/pipes';\nimport { SparkAttributeDescriptionComponent } from '@mintplayer/ng-spark/attribute-description';\nimport { SparkLanguageService, SparkService } from '@mintplayer/ng-spark/services';\nimport {\n CustomActionDefinition,\n EntityAttributeDefinition,\n EntityType,\n LookupReference,\n QueryColumn,\n QueryResultItem,\n SparkQuery,\n filterQueryActions,\n parseSelectionRule,\n selectionModeFor,\n valueFor,\n} from '@mintplayer/ng-spark/models';\nimport { SPARK_GRID_PAGE_SIZES, initialGridSettings, isVirtualScrollingQuery } from './spark-grid-columns';\nimport { SparkGridRenderers } from './spark-grid-renderers';\nimport { SparkGridCellComponent } from './spark-grid-cell.component';\n\n/**\n * The one Spark grid: a `<bs-datatable>` rendering a query or a sub-query.\n *\n * This replaces two components that were the same grid written twice — and, counting\n * `spark-query-list`'s streaming and paged branches, the `<bs-datatable>` element itself written\n * three times. The duplication had already produced four user-visible bugs, each fixed on one\n * side and not the other: `[indeterminate]` on null booleans, permission state surviving a failed\n * reload, a swallowed fetch failure, and virtual-scroll sizing. `SparkGridRenderers` was\n * extracted to stop that and could only take the stateless helpers with it; this takes the rest.\n *\n * ## What it deliberately does NOT own: streaming\n *\n * `spark-grid-renderers.ts` records why — a websocket dependency graph must not reach the bundle\n * of every PO detail page, none of which stream. So rows can come from **either** side:\n *\n * - unbound `data` — the grid fetches for itself, paging and sorting server-side;\n * - bound `data` — the grid renders what it is given and never fetches.\n *\n * `spark-query-list` keeps the socket and feeds its snapshot in. This is the line `bs-datatable`\n * itself draws: `[data]` and `[fetch]` are mutually exclusive, and binding both makes `[fetch]`\n * win silently.\n *\n * ## Reading its state\n *\n * `query`, `entityType`, `customActions`, `selection`, `canRead`, `canCreate` and `resultCount`\n * are readable so a host can render chrome around the grid. Read them through a template\n * reference variable — `<spark-query-grid #grid>` … `grid.query()` — not `viewChild`: hosts wrap\n * grids in `@if`, where a `viewChild` is intermittently undefined.\n */\n@Component({\n selector: 'spark-query-grid',\n imports: [CommonModule, RouterModule, BsAlertComponent, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsSpinnerComponent, SparkGridCellComponent, ResolveTranslationPipe, QueryCellValuePipe, QueryReferenceChipsPipe, TranslateKeyPipe, SparkAttributeDescriptionComponent],\n templateUrl: './spark-query-grid.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkQueryGridComponent {\n private readonly sparkService = inject(SparkService);\n private readonly gridRenderers = inject(SparkGridRenderers);\n private readonly queryRefresh = inject(SparkQueryRefreshService);\n readonly lang = inject(SparkLanguageService);\n\n /** Query alias or id. */\n queryId = input.required<string>();\n\n /**\n * The parent persistent object this query is scoped to, when it has one.\n *\n * Optional, because not every query is a detail of something: a page can host a grid that\n * stands on its own — \"my accounts\", a dashboard list — and the server already treats an absent\n * parent as \"no parent\" rather than as an error. Requiring these made that shape impossible to\n * express: the component simply never loaded, with no request, no error and no log.\n *\n * Pass both or neither. One without the other is ignored, matching `SparkService.executeQuery`,\n * which omits either param when it is falsy, and the execute endpoint, which resolves a parent\n * only when both are present.\n */\n parentId = input<string>('');\n parentType = input<string>('');\n\n /**\n * Rows supplied from outside. When bound, the grid renders these and runs no fetch.\n *\n * This is how streaming stays out of this component (see the class comment). `null` — the\n * default — means \"fetch for yourself\"; an empty array means \"you have been given no rows\",\n * which is a different statement and renders an empty grid rather than triggering a load.\n */\n data = input<QueryResultItem[] | null>(null);\n\n /**\n * Server-side search term, passed through to the query.\n *\n * An input rather than a box, so the host owns the control and the grid owns the request. A\n * host with client-side rows filters them itself before binding `data`.\n */\n search = input<string>('');\n\n /**\n * Column metadata for externally supplied rows. Required whenever `data` is bound, because a\n * projection cannot describe itself — there is no per-row metadata left to infer it from.\n */\n columns = input<QueryColumn[] | null>(null);\n\n /**\n * Change this to re-run the query. Any value works; only its identity matters.\n *\n * A declarative token rather than only a `reload()` method, because calling a method means\n * holding a component handle, and hosts wrap this grid in `@if`, where a `viewChild` is\n * intermittently undefined.\n *\n * This drives the CHEAP refresh (see {@link reload}). It deliberately does not feed the main\n * effect: re-running `loadData` would re-resolve the query, the entity types, the permissions\n * and the lookups, and reset the user's page and sort on every button press.\n */\n reloadToken = input<unknown>(null);\n\n /**\n * Paging and sorting. Two-way, so a host driving `data` can sort those rows by whatever the\n * user actually clicked — the datatable writes the new sort back through here.\n */\n settings = model(new DatatableSettings({\n perPage: { values: SPARK_GRID_PAGE_SIZES, selected: SPARK_GRID_PAGE_SIZES[0] },\n page: { values: [1], selected: 1 },\n sortColumns: [],\n }));\n\n /** Rows the user has ticked. Two-way so chrome outside the grid can read and clear them. */\n selection = model<QueryResultItem[]>([]);\n\n /**\n * Replaces where the first column's link points, per row.\n *\n * Return `null` to suppress the link for that row — useful when a grid mixes rows that have a\n * detail page with rows that do not.\n *\n * ⚠️ **It changes the destination, not the permission.** `canRead()` still gates whether any\n * link is rendered at all, and this function is never consulted when that gate is closed. It\n * cannot be used to reach a row the rights model withheld; it exists for the case where the\n * row's natural destination is not `/po/{type}/{id}` — a composed row that maps to a page of\n * its own, or a grid embedded in a route that owns its own child paths.\n */\n rowRoute = input<((row: QueryResultItem) => unknown[] | null) | null>(null);\n\n /** Emitted whenever a load or a page fetch fails, for a host in bespoke chrome. */\n error = output<HttpErrorResponse>();\n rowClicked = output<QueryResultItem>();\n customActionExecuted = output<{ action: CustomActionDefinition }>();\n\n colors = Color;\n\n /**\n * Where the first column's link points for this row: the host's `rowRoute` when it supplied one,\n * otherwise the row's own detail page.\n *\n * A method rather than a computed because the answer is per row, and the template already\n * iterates rows — a computed would have to be a map keyed by id, rebuilt on every page.\n */\n protected rowRouteFor(row: QueryResultItem): unknown[] | null {\n const custom = this.rowRoute();\n if (custom) return custom(row);\n\n const type = this.entityType();\n\n // ⚠️ A composed type has no per-row detail page by construction: its rows are computed, and\n // `{Name}Actions.OnLoadAsync` serves ONE page which is free to ignore the id it was given. So\n // /po/{type}/{rowId} does not 404 — it silently renders that same page, which is worse, because\n // nothing looks wrong. This branch is live in DemoApp today: Read/StartPage implies\n // Query/StartPage, so the composed grid renders with canRead() true and every row linked.\n //\n // `clrType` is absent exactly for those types and is already on the wire; the grid simply never\n // consulted it. A host whose composed rows DO have a page says so with `rowRoute`.\n if (!type?.clrType) return null;\n\n return ['/po', type.alias || type.id, row.id];\n }\n\n query = signal<SparkQuery | null>(null);\n entityType = signal<EntityType | null>(null);\n allEntityTypes = signal<EntityType[]>([]);\n lookupReferenceOptions = signal<Record<string, LookupReference>>({});\n loading = signal(true);\n canRead = signal(false);\n canCreate = signal(false);\n resultCount = signal<number | null>(null);\n customActions = signal<CustomActionDefinition[]>([]);\n\n /** Names the server withheld for this RESULT; see QueryResult.disabledActions. */\n private readonly disabledActions = signal<string[]>([]);\n\n /**\n * The actions actually offered for this result.\n *\n * The catalogue at `/spark/actions/{objectTypeId}` is per TYPE and is never told what an\n * execution returned, so an action that applies to only some results cannot be filtered there.\n * A custom query withholds what does not apply via `CustomQueryArgs.DisableActions(...)`, and\n * the answer arrives on the result.\n *\n * An affordance, not a permission -- the action handler still refuses on its own terms.\n */\n visibleCustomActions = computed(() => {\n const withheld = this.disabledActions();\n if (!withheld.length) return this.customActions();\n\n const lowered = new Set(withheld.map(name => name.toLowerCase()));\n return this.customActions().filter(action => !lowered.has(action.name.toLowerCase()));\n });\n fetchFn = signal<BsDatatableFetch<QueryResultItem> | null>(null);\n\n /**\n * Why the component renders its own failure instead of only reporting one.\n *\n * `SparkService` is a bare `firstValueFrom` passthrough with no interceptor, so every failure\n * surfaces here and nowhere else. A host embedding this grid cannot surface what it never sees,\n * and the default has to be visible with no host cooperation — hence a rendered alert, not just\n * an output.\n */\n errorMessage = signal<string | null>(null);\n\n /** 'none' unless an action is selection-gated, so unaffected grids gain no checkbox column. */\n selectionMode = computed(() => selectionModeFor(this.customActions()));\n\n isVirtualScrolling = computed(() => isVirtualScrollingQuery(this.query()));\n\n /**\n * Columns as sent with the most recent fetched page.\n *\n * A host binding `data` (streaming) supplies its own via the `columns` input instead — the\n * snapshot carries them once, exactly as a paged result does.\n */\n private readonly fetchedColumns = signal<QueryColumn[]>([]);\n\n /** Every column on the wire, drawn or not — what renderers and lookups resolve against. */\n allColumns = computed(() => this.columns() ?? this.fetchedColumns());\n\n /**\n * The columns the grid draws. `isVisible: false` ships a value without a column, so a renderer\n * can read a sibling the grid does not show; undefined means visible, so a server that predates\n * the field still draws everything.\n */\n visibleColumns = computed(() => this.allColumns().filter(c => c.isVisible !== false));\n\n /**\n * True when rows do not come from this component's own fetch.\n *\n * Either because the host bound `data`, or because the query streams — a streaming query's rows\n * arrive over a socket and `/execute` is not a way to get them. The grid recognises the second\n * case itself rather than waiting to be told, because it resolves the query before the host can\n * see it: left to `data` alone, every streaming grid would fire one pointless fetch on mount,\n * before the host had anything to bind.\n */\n hasExternalData = computed(() =>\n this.data() !== null || this.query()?.isStreamingQuery === true);\n\n /** Whether an action's selection rule is satisfied right now. The server checks it again. */\n isActionEnabled(action: CustomActionDefinition): boolean {\n return parseSelectionRule(action.selectionRule)(this.selection().map(r => r.id).length);\n }\n\n constructor() {\n effect(() => {\n const qId = this.queryId();\n const pId = this.parentId();\n const pType = this.parentType();\n // Only the query id is required. Requiring a parent here is what made a standalone grid\n // silently render nothing.\n if (qId) {\n this.loadData(qId, pId, pType);\n } else {\n // No query id at all. `loading` starts true, so without this the component would spin\n // forever instead of saying anything.\n this.loading.set(false);\n }\n });\n\n // Separate effect, so the token drives the cheap refresh and never the full metadata reload.\n // `first` skips the initial run: the effect above has already fetched, and reacting to the\n // token's starting value would double-fetch on mount.\n let first = true;\n effect(() => {\n // Both the host's token and the server's refreshQuery drive the same cheap refresh.\n this.reloadToken();\n this.queryRefresh.tokenFor(this.queryId());\n if (first) { first = false; return; }\n untracked(() => this.reload());\n });\n\n // A new search term must refetch even when page, perPage and sort are unchanged — the\n // datatable dedupes reloads by exactly that triple, and a new fetch identity is what resets\n // its dedupe key. Skipping the first run keeps mount to a single request.\n let firstSearch = true;\n effect(() => {\n this.search();\n if (firstSearch) { firstSearch = false; return; }\n untracked(() => this.onSearchChanged());\n });\n }\n\n /**\n * Re-run the query, keeping the current page, sort and scroll position.\n *\n * Data-level on purpose: it re-seeds the fetch closure and nothing else. For a definition\n * change — new columns, a renamed query — the inputs themselves must change; that is the\n * expensive path. Inert when rows come from the host: there is nothing here to re-run.\n */\n reload(): void {\n if (this.hasExternalData()) return;\n const q = this.query();\n if (q) this.fetchFn.set(this.makeFetch(q, this.parentId(), this.parentType()));\n }\n\n private onSearchChanged(): void {\n if (this.hasExternalData()) return;\n const s = this.settings();\n // Back to page 1: the old page number means nothing against a different result set.\n this.settings.set(new DatatableSettings({\n perPage: { values: s.perPage.values, selected: s.perPage.selected },\n page: { values: [1], selected: 1 },\n sortColumns: s.sortColumns,\n }));\n this.reload();\n }\n\n async onCustomAction(action: CustomActionDefinition): Promise<void> {\n if (action.confirmationMessageKey) {\n const message = this.lang.t(action.confirmationMessageKey) || 'Are you sure?';\n if (!confirm(message)) return;\n }\n try {\n // The sub-query's container travels with the action (#327). Without it an action invoked\n // from a company's Cars tab could not tell it was on a company's page at all — the grid knew\n // (it filters the rows by that parent) and simply dropped the fact on the way out.\n //\n // Sent as parentId/parentType, NOT as the `parent` argument: that one means an object of this\n // action's OWN type and is loaded under it server-side, so handing it a Company id for a Car\n // action refuses — correctly, and confusingly.\n const pId = this.parentId();\n const pType = this.parentType();\n await this.sparkService.executeCustomAction(\n this.entityType()!.id,\n action.name,\n undefined,\n this.selection().map(r => r.id),\n pId && pType ? { id: pId, type: pType } : undefined,\n // The query too: the server re-runs it narrowed to these ids, so the action receives the\n // rows this grid rendered rather than a re-derivation from documents.\n this.query()?.id);\n this.customActionExecuted.emit({ action });\n if (action.refreshOnCompleted) this.reload();\n } catch (e) {\n const err = e as HttpErrorResponse;\n this.errorMessage.set(err.error?.error || err.message || this.lang.t('common.actionFailed') || 'Action failed');\n }\n }\n\n private reportError(err: HttpErrorResponse): void {\n this.errorMessage.set(this.describe(err));\n this.error.emit(err);\n }\n\n /**\n * A 404 is deliberately generic.\n *\n * `Endpoints/Queries/Get.cs` answers 404 with byte-identical bodies for \"no such query\" and\n * \"you may not see it\", so existence is not disclosed (security audit M-3). The component\n * therefore genuinely cannot tell them apart, and both \"Not found\" and \"Access denied\" would be\n * a guess — one of them leaking, the other misleading.\n */\n private describe(err: HttpErrorResponse): string {\n if (err?.status === 404) {\n return this.lang.t('spark.query.unavailable') || 'This list is not available.';\n }\n return err?.error?.error || err?.message\n || this.lang.t('common.unexpectedError') || 'An unexpected error occurred';\n }\n\n private async loadData(queryId: string, parentId: string, parentType: string): Promise<void> {\n this.loading.set(true);\n this.errorMessage.set(null);\n this.fetchFn.set(null);\n // Reset everything derived from the previous query, not just the fetch. Leaving\n // `entityType`/`canRead` behind let a failed reload build a row link out of the PREVIOUS type\n // and the previous permission.\n this.query.set(null);\n this.entityType.set(null);\n this.canRead.set(false);\n this.canCreate.set(false);\n this.customActions.set([]);\n this.resultCount.set(null);\n // Ids from the previous query are meaningless against the next one, and would be POSTed as\n // though they belonged to it.\n this.selection.set([]);\n try {\n const [resolvedQuery, entityTypes] = await Promise.all([\n this.sparkService.getQuery(queryId),\n this.sparkService.getEntityTypes(),\n ]);\n\n this.query.set(resolvedQuery);\n this.allEntityTypes.set(entityTypes);\n\n const et = this.resolveEntityType(resolvedQuery, entityTypes);\n this.entityType.set(et);\n if (et) {\n const [permissions, actions] = await Promise.all([\n this.sparkService.getPermissions(et.id),\n this.sparkService.getCustomActions(et.id),\n ]);\n this.canRead.set(permissions.canRead);\n this.canCreate.set(permissions.canCreate);\n // 'query', not 'list'. The server model has always documented \"detail\" | \"query\" |\n // \"both\"; a filter testing for a value nothing emits renders the action NOWHERE.\n this.customActions.set(filterQueryActions(actions));\n }\n\n this.settings.set(initialGridSettings(resolvedQuery));\n // The datatable drives paging/sorting via [(settings)] and calls fetchFn per page. Virtual\n // scrolling is just the [virtualScroll] template flag.\n // `resolvedQuery`, not `hasExternalData()`: the query signal is set above, but reading the\n // computed here would depend on signal-read ordering inside an async method. Ask the value\n // directly.\n if (this.data() === null && !resolvedQuery?.isStreamingQuery) {\n this.fetchFn.set(this.makeFetch(resolvedQuery, parentId, parentType));\n }\n\n this.loadLookupReferenceOptions();\n } catch (e) {\n this.fetchFn.set(null);\n this.reportError(e as HttpErrorResponse);\n } finally {\n this.loading.set(false);\n }\n }\n\n /**\n * The query's entity type.\n *\n * The source-name fallback is not optional garnish: a `Database.*` query need not declare\n * `entityType`, and the sub-query grid — which matched on the declared name alone — rendered\n * those as an empty card with no columns, no rows and no error, while the identical query\n * rendered correctly as a page. Both grids are this one now, so there is one answer.\n */\n private resolveEntityType(query: SparkQuery | null, entityTypes: EntityType[]): EntityType | null {\n if (!query) return null;\n\n if (query.entityType) {\n return entityTypes.find(t =>\n t.name === query.entityType || t.alias === query.entityType?.toLowerCase()) ?? null;\n }\n\n const sourceName = extractSourceName(query.source);\n const singular = singularize(sourceName);\n return entityTypes.find(t =>\n t.name === sourceName || t.name === singular || t.clrType?.endsWith(singular)) ?? null;\n }\n\n private makeFetch(query: SparkQuery, parentId: string, parentType: string): BsDatatableFetch<QueryResultItem> {\n return (req) => this.sparkService.executeQuery(query.id, {\n sortColumns: req.sortColumns,\n skip: (req.page - 1) * req.perPage,\n take: req.perPage,\n search: this.search() || undefined,\n parentId, parentType,\n }).then(r => {\n this.errorMessage.set(null);\n this.resultCount.set(r.totalItems);\n // Columns come from the result now, not from the entity type: the server decides the query\n // surface (ShowedOn.Query) and is the same place the sort-column allow-list is checked.\n // ?? [] because a malformed or older response must render an empty grid, not throw inside a\n // computed — where the stack points at the column filter and not at the response that lacked them.\n this.fetchedColumns.set(r.columns ?? []);\n // Per-result, so it is re-read on every page rather than latched from the first.\n this.disabledActions.set(r.disabledActions ?? []);\n return {\n data: r.items,\n totalRecords: r.totalItems,\n totalPages: Math.ceil(r.totalItems / req.perPage) || 1,\n perPage: req.perPage,\n page: req.page,\n };\n }).catch((e: HttpErrorResponse) => {\n // Report before returning the empty page, or a failed fetch is indistinguishable from a\n // query that legitimately has no rows.\n this.reportError(e);\n this.resultCount.set(0);\n return { data: [], totalRecords: 0, totalPages: 1, perPage: req.perPage, page: req.page };\n });\n }\n\n private async loadLookupReferenceOptions(): Promise<void> {\n // Over ALL columns, not just the drawn ones: an undrawn column's value can still be rendered\n // by a renderer reading it as a sibling, and it would resolve to a raw key without its options.\n this.lookupReferenceOptions.set(await this.gridRenderers.loadLookupOptions(this.allColumns()));\n }\n\n /**\n * The underlying value a custom renderer receives, which is not the printable one.\n *\n * A projection is flat, so this is the cell's own value rather than a display string. It is\n * deliberately not the attribute-shaped `rendererValue`: a query row has no nested object to\n * fall back to, and reaching for one would hand every renderer `undefined`.\n */\n rendererValueFor(item: QueryResultItem, column: QueryColumn): unknown {\n return cellValue(valueFor(item, column.name));\n }\n\n getColumnRendererComponent(column: QueryColumn): Type<any> | null {\n return this.gridRenderers.columnComponentFor(column);\n }\n\n getColumnRendererInputs(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any> {\n return this.gridRenderers.columnInputsFor(component, item, column);\n }\n}\n\nfunction extractSourceName(source: string): string {\n const dotIndex = source.indexOf('.');\n return dotIndex >= 0 ? source.substring(dotIndex + 1) : source;\n}\n\n/**\n * Enough English to map a query source onto a type name — `Cars` to `Car`, `People` to `Person`.\n *\n * Deliberately a small table plus three suffix rules rather than a library: it runs against type\n * names the application itself chose, and a wrong guess costs nothing, since the caller falls\n * through to matching the plural and the CLR type name.\n */\nfunction singularize(plural: string): string {\n const irregulars: Record<string, string> = {\n 'People': 'Person',\n 'Children': 'Child',\n 'Men': 'Man',\n 'Women': 'Woman',\n };\n if (irregulars[plural]) return irregulars[plural];\n if (plural.endsWith('ies')) return plural.slice(0, -3) + 'y';\n if (plural.endsWith('es')) return plural.slice(0, -2);\n if (plural.endsWith('s')) return plural.slice(0, -1);\n return plural;\n}\n","<!--\n Three explicit states, in this order, and the order is load-bearing.\n\n This template used to open with `@if (query(); as q)` wrapping EVERYTHING, and `query()` is only\n set after loadData's awaits resolve. Three separate bugs fell out of that one line: the spinner\n was unreachable on a first load (it rendered inside the gate, while `loading` starts true and\n `query` starts null), a first-load failure rendered ZERO DOM — no card, no message, nothing to\n see or report — and a failed RELOAD left the previous query's rows on screen.\n\n So: `loading` is checked first and outside any dependency on `query`, and the final `@else`\n always renders something. Do not fold these back into one gate, and do not move the spinner\n inside the `query()` branch.\n-->\n@if (loading()) {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n} @else if (query()) {\n <!-- A page-fetch failure while the grid is already resolved. Without this the catch returns an\n empty page and a failed query is indistinguishable from one that legitimately has no rows. -->\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n\n <!--\n One datatable, two row sources. `[data]` and `[fetch]` are mutually exclusive in\n ng-bootstrap — binding both makes `[fetch]` win silently — so exactly one is ever non-null\n here: `fetchFn` is left null whenever `data` is bound. See the class comment for why rows can\n arrive from outside at all (streaming must not put a websocket in every detail page's bundle).\n -->\n <bs-datatable\n [selectionMode]=\"selectionMode()\"\n [(selection)]=\"selection\"\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [data]=\"data()\"\n [fetch]=\"fetchFn()\"\n [(settings)]=\"settings\">\n @for (col of visibleColumns(); track col.name) {\n <div *bsDatatableColumn=\"col.name; sortable: true\">\n {{ (col.label | resolveTranslation) || col.name }}\n <spark-attribute-description [description]=\"col.description\" />\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (col of visibleColumns(); track col.name; let first = $first) {\n <td>\n @if (row) {\n <!-- The first column links to the row's detail page. Two things about this are\n routinely misread:\n\n 1. `cellContent` is projected INSIDE the anchor, so a custom `renderer` does NOT\n suppress this link — a renderer that emits its own <a> produces nested anchors\n (invalid HTML) rather than replacing this one.\n 2. `canRead()` is the whole gate, and it is the rights model: `Query` without\n `Read` lists the rows and withholds the link. Withhold `Read` for a query\n whose rows no detail page can load — a Custom.* query that fabricates rows in\n memory, say.\n 3. `rowRoute` replaces the DESTINATION only, never the gate: returning a route\n from it cannot make a row clickable that `canRead()` withheld, and returning\n null from it suppresses the link for that one row. -->\n @if (first && canRead() && rowRouteFor(row); as route) {\n <a [routerLink]=\"route\"\n (click)=\"rowClicked.emit(row)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, col: col }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, col: col }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-container>\n </bs-datatable>\n} @else {\n <!-- The query could not be resolved. Rendering something keeps the host's layout intact and,\n crucially, makes the failure visible: this branch used to render nothing at all. -->\n <bs-alert [type]=\"colors.danger\" class=\"mb-0\">\n {{ errorMessage() || ('spark.query.unavailable' | t) }}\n </bs-alert>\n}\n\n<ng-template #cellContent let-item let-col=\"col\">\n <!--\n Presentation lives in <spark-grid-cell>, shared with the AsDetail table on the PO detail page.\n Value resolution stays here: a query row is a PersistentObject with an attribute list, and the\n AsDetail table's rows are plain dictionaries, so only the rendering is common.\n\n `link` is deliberately not passed. The first-column link is the grid's own rule and wraps this\n template from outside; setting both would nest anchors.\n -->\n <spark-grid-cell\n [column]=\"col\"\n [display]=\"(col | queryCellValue:item:lookupReferenceOptions())\"\n [rendererValue]=\"rendererValueFor(item, col)\"\n [item]=\"item\"\n [chips]=\"(col | queryReferenceChips:item)\" />\n</ng-template>\n","import { ChangeDetectionStrategy, Component, computed, contentChildren, input, output, viewChild, TemplateRef } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsPriorityNavComponent, BsPriorityNavItemDirective } from '@mintplayer/ng-bootstrap/priority-nav';\nimport { ResolveTranslationPipe } from '@mintplayer/ng-spark/pipes';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { CustomActionDefinition, PersistentObject, QueryResultItem } from '@mintplayer/ng-spark/models';\nimport { inject } from '@angular/core';\nimport { SparkQueryGridComponent } from './spark-query-grid.component';\nimport {\n SparkQueryActionsDirective,\n SparkQueryCaptionDirective,\n SparkQueryIconDirective,\n slotFor,\n} from './spark-query-slots';\n\n/**\n * A `<bs-card>` around a {@link SparkQueryGridComponent}: icon, caption, actions, grid.\n *\n * ## Chrome is overridden, not replaced\n *\n * Every header region has a default, and a host replaces only the ones it supplies. That is what\n * lets this component serve the auto-rendered case: a sub-query is rendered once per entry in\n * `EntityTypeDefinition.Queries` with nobody projecting into it, and it must look right with no\n * host cooperation at all. A slot mechanism that only ever *replaced* chrome would leave that\n * call site blank — which is why an earlier design had the query carry its own chrome from the\n * server. Overriding a default needs no host; replacing one does.\n *\n * ## Two ways in, one set of templates\n *\n * Hand-written markup uses the structural directives and is found with `contentChildren`.\n * The auto-rendered path cannot: `spark-po-detail` is created by the router, so in a default app\n * there is no tag to project into. It therefore forwards `TemplateRef`s as inputs instead — a\n * directive cannot cross a component boundary but its template can, and that forwarding is\n * already the idiom in `spark-po-detail` (`extraActionsTemplate`, `extraContentTemplate`).\n *\n * Content wins over a forwarded input: the closer declaration is the more specific one.\n */\n@Component({\n selector: 'spark-query-card',\n imports: [CommonModule, BsCardComponent, BsCardHeaderComponent, BsPriorityNavComponent, BsPriorityNavItemDirective, SparkQueryGridComponent, ResolveTranslationPipe],\n templateUrl: './spark-query-card.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkQueryCardComponent {\n readonly lang = inject(SparkLanguageService);\n\n queryId = input.required<string>();\n parentId = input<string>('');\n parentType = input<string>('');\n reloadToken = input<unknown>(null);\n data = input<QueryResultItem[] | null>(null);\n search = input<string>('');\n\n /**\n * Slots forwarded from a host that cannot project content — see the class comment. A card\n * reached through hand-written markup should use the structural directives instead.\n */\n iconTemplate = input<TemplateRef<any> | null>(null);\n captionTemplate = input<TemplateRef<any> | null>(null);\n actionsTemplate = input<TemplateRef<any> | null>(null);\n\n error = output<HttpErrorResponse>();\n rowClicked = output<QueryResultItem>();\n customActionExecuted = output<{ action: CustomActionDefinition }>();\n\n /**\n * Forwarded to the grid. Without this the escape hatch was unreachable from a card — i.e. from\n * every auto-rendered sub-query and program-unit query page, which is most grids.\n */\n rowRoute = input<((row: QueryResultItem) => unknown[] | null) | null>(null);\n\n colors = Color;\n\n private readonly iconSlots = contentChildren(SparkQueryIconDirective);\n private readonly captionSlots = contentChildren(SparkQueryCaptionDirective);\n private readonly actionSlots = contentChildren(SparkQueryActionsDirective);\n\n /**\n * The grid, read only to surface its state — the query, the actions, the selection — to this\n * component's own header.\n *\n * Optional rather than `required` on purpose. The header renders ABOVE the grid in this\n * template, so on the first change-detection pass the view query has not resolved yet and\n * `viewChild.required()` would throw where a plain one returns `undefined`. Everything below\n * therefore reads it defensively; the signal updates once the view initialises and the header\n * re-renders with the real query.\n *\n * A host reads grid state through a template reference variable instead, because a host may put\n * the grid behind an `@if`, where a view query genuinely is intermittently undefined.\n */\n protected readonly grid = viewChild(SparkQueryGridComponent);\n\n protected readonly query = computed(() => this.grid()?.query() ?? null);\n\n protected readonly iconTpl = computed(() =>\n slotFor(this.iconSlots(), this.query())?.templateRef ?? this.iconTemplate());\n\n protected readonly captionTpl = computed(() =>\n slotFor(this.captionSlots(), this.query())?.templateRef ?? this.captionTemplate());\n\n protected readonly actionsTpl = computed(() =>\n slotFor(this.actionSlots(), this.query())?.templateRef ?? this.actionsTemplate());\n\n /** The caption the card renders unless a slot replaces it. */\n protected readonly caption = computed(() => {\n const q = this.query();\n return (q?.description ? this.lang.resolve(q.description) : '') || q?.name || '';\n });\n\n protected readonly customActions = computed(() => this.grid()?.visibleCustomActions() ?? []);\n protected readonly selection = computed(() => this.grid()?.selection() ?? []);\n}\n","<!--\n The card is always rendered. A host that wants no card uses <spark-query-grid> directly — which\n is what the old `showCard=\"false\"` meant, expressed as a component choice rather than a flag.\n-->\n<bs-card class=\"d-block my-3\">\n <bs-card-header>\n <div class=\"d-flex align-items-center gap-2\">\n @if (iconTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: query() }\"></ng-container>\n }\n\n @if (actionsTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: customActions(), selection: selection(), query: query() }\"></ng-container>\n } @else if (customActions().length) {\n <!-- The default: the actions the server declares for this type. The nav renders only when\n there are any, so a query without actions is pixel-identical to a plain caption.\n\n Disabled, not hidden: hiding makes the affordance undiscoverable and reflows the\n priority nav on every selection change. The server enforces the same rule. -->\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-sm btn-outline-primary\"\n [disabled]=\"!grid()?.isActionEnabled(action)\" (click)=\"grid()?.onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n </bs-priority-nav>\n }\n\n <!--\n Caption last, actions first. The auto margin is conditional rather than fixed, and that is\n the point: with actions present `ms-auto` pushes the caption to the trailing edge, and with\n none it falls back to `me-auto` so a plain card looks exactly as it always did. A fixed\n `ms-auto` would have right-aligned the caption of every action-less query card in every app\n — a change nobody asked for, to fix a layout only some cards have.\n -->\n <span [class.ms-auto]=\"customActions().length\" [class.me-auto]=\"!customActions().length\">\n @if (captionTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: caption(), query: query() }\"></ng-container>\n } @else {\n {{ caption() }}\n }\n </span>\n </div>\n </bs-card-header>\n\n <div class=\"p-3\">\n <spark-query-grid\n [queryId]=\"queryId()\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\"\n [reloadToken]=\"reloadToken()\"\n [data]=\"data()\"\n [search]=\"search()\"\n [rowRoute]=\"rowRoute()\"\n (error)=\"error.emit($event)\"\n (rowClicked)=\"rowClicked.emit($event)\"\n (customActionExecuted)=\"customActionExecuted.emit($event)\" />\n </div>\n</bs-card>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-grid.mjs","sources":["../../grid/src/spark-grid-columns.ts","../../grid/src/spark-grid-renderers.ts","../../grid/src/spark-query-slots.ts","../../grid/src/spark-grid-cell.component.ts","../../grid/src/spark-grid-cell.component.html","../../grid/src/spark-query-grid.component.ts","../../grid/src/spark-query-grid.component.html","../../grid/src/spark-query-card.component.ts","../../grid/src/spark-query-card.component.html","../../grid/mintplayer-ng-spark-grid.ts"],"sourcesContent":["import { DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';\nimport { SortColumn } from '@mintplayer/pagination';\nimport {\n EntityAttributeDefinition,\n EntityType,\n ShowedOn,\n SparkQuery,\n hasShowedOnFlag,\n} from '@mintplayer/ng-spark/models';\n\n/** Page sizes offered by every Spark grid. */\nexport const SPARK_GRID_PAGE_SIZES = [10, 25, 50];\n\n/**\n * The attributes a grid shows, in display order.\n *\n * Shared so the two grids cannot disagree about what \"visible\" means — they each had their own\n * copy of this expression, which is the kind of thing that stays identical right up until it\n * doesn't.\n */\nexport function visibleGridAttributes(entityType: EntityType | null): EntityAttributeDefinition[] {\n return entityType?.attributes\n .filter(a => a.isVisible && hasShowedOnFlag(a.showedOn, ShowedOn.Query))\n .sort((a, b) => a.order - b.order) ?? [];\n}\n\n/**\n * Initial datatable settings for a query, seeded with the query's declared sort.\n *\n * The datatable owns paging and sorting from here on and calls the fetch callback per page; this\n * only decides where it starts.\n */\nexport function initialGridSettings(query: SparkQuery | null): DatatableSettings {\n // Nullable because one caller resolves its query from a route param and may not have one yet;\n // an unsorted grid is the right fallback, not a crash.\n const sortColumns: SortColumn[] = (query?.sortColumns || []).map(sc => ({\n property: sc.property,\n direction: sc.direction === 'desc' ? 'descending' as const : 'ascending' as const,\n }));\n\n return new DatatableSettings({\n perPage: { values: SPARK_GRID_PAGE_SIZES, selected: SPARK_GRID_PAGE_SIZES[0] },\n page: { values: [1], selected: 1 },\n sortColumns,\n });\n}\n\n/** Whether a query renders as a virtual-scrolling grid rather than a paged one. */\nexport function isVirtualScrollingQuery(query: SparkQuery | null): boolean {\n return query?.renderMode === 'VirtualScrolling';\n}\n","import { inject, Injectable, Type } from '@angular/core';\nimport {\n EntityAttributeDefinition,\n LookupReference,\n QueryColumn,\n QueryResultItem,\n SparkCellColumn,\n valueFor,\n} from '@mintplayer/ng-spark/models';\nimport { SPARK_ATTRIBUTE_RENDERERS, cellValue, withDeclaredInputs } from '@mintplayer/ng-spark/renderers';\nimport { SparkService } from '@mintplayer/ng-spark/services';\n\n/**\n * Renderer lookup and lookup-reference loading for a Spark grid.\n *\n * This was extracted when `spark-query-list` and `spark-sub-query` were two components holding\n * byte-identical copies of it — around 120 lines between them. That duplication was not a\n * tidiness complaint: it produced drift. The two copies disagreed about `[indeterminate]`, about\n * resetting permission state, about whether a fetch failure surfaces or is swallowed, and about\n * virtual-scroll sizing — four user-visible bugs, each fixed on one side and not the other.\n *\n * There is now one grid, {@link SparkQueryGridComponent}, so the drift cannot recur. This stays\n * separate because it is stateless service-shaped logic rather than view state, and because it is\n * what a custom grid would need in order to render Spark cells at all.\n */\n@Injectable({ providedIn: 'root' })\nexport class SparkGridRenderers {\n private readonly registry = inject(SPARK_ATTRIBUTE_RENDERERS);\n private readonly sparkService = inject(SparkService);\n\n /** The registered column component for a column, or null to fall back to the default cell. */\n columnComponentFor(column: SparkCellColumn): Type<any> | null {\n if (!column.renderer) return null;\n return this.registry.find(r => r.name === column.renderer)?.columnComponent ?? null;\n }\n\n /**\n * Inputs for a query-grid cell renderer, filtered to what the component actually declares —\n * `NgComponentOutlet` throws on an input the target does not have, which is what lets every\n * member of the renderer contract be optional.\n */\n columnInputsFor(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any> {\n return this.cellInputsFor(component, cellValue(valueFor(item, column.name)), column, item);\n }\n\n /**\n * The same contract for a row that is not a query result — an AsDetail sub-table row, which is\n * a plain dictionary of embedded values with no id and no column metadata of its own, so its\n * value cannot be read the way {@link columnInputsFor} reads one.\n *\n * Only the extraction differs; the renderer contract is identical, and stating it once is what\n * stops the two from drifting the way the cell markup already had.\n */\n cellInputsFor(component: Type<any>, value: unknown, column: SparkCellColumn, item: unknown): Record<string, any> {\n return withDeclaredInputs(component, {\n value,\n column,\n options: column.rendererOptions,\n item,\n });\n }\n\n /**\n * Loads every lookup reference the visible columns need, in one pass.\n *\n * Returns an empty map rather than throwing when there are none, so callers never branch on it.\n */\n async loadLookupOptions(columns: readonly (SparkCellColumn | EntityAttributeDefinition)[]): Promise<Record<string, LookupReference>> {\n const lookupColumns = columns.filter(c => c.lookupReferenceType);\n if (lookupColumns.length === 0) return {};\n\n const names = [...new Set(lookupColumns.map(c => c.lookupReferenceType!))];\n const entries = await Promise.all(\n names.map(async name => [name, await this.sparkService.getLookupReference(name)] as const),\n );\n return entries.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {} as Record<string, LookupReference>);\n }\n}\n","import { Directive, inject, input, TemplateRef } from '@angular/core';\nimport { CustomActionDefinition, PersistentObject, SparkQuery } from '@mintplayer/ng-spark/models';\n\n/**\n * Header slots for `<spark-query-card>`.\n *\n * Each directive marks a template that REPLACES one region of the card header. Supplying one\n * leaves the other two alone — that is the whole point of having three rather than the single\n * whole-header template they replace, where changing the icon meant re-implementing the caption\n * and the action bar as well.\n *\n * An omitted slot is not an empty slot: the card renders its default. This is what keeps the\n * auto-rendered sub-query working. A sub-query is rendered from `EntityTypeDefinition.Queries`\n * with no host to project into, so a mechanism that only ever REPLACED chrome would leave that\n * call site with nothing — which is why an earlier design had the query declare its own chrome\n * server-side. Overriding a default needs no host; replacing one does.\n *\n * The two ends of that are visible in the defaults themselves. Neither `SparkQuery` nor\n * `EntityType` carries an icon, so the server has nothing to say and the slot is the only\n * source. Actions are the mirror image: the server declares them per type, so the default is\n * the real answer and the slot is a rare override.\n *\n * Naming follows ng-bootstrap's `*bsDatatableColumn` convention — prefix, component, slot —\n * with `spark`, since these are ng-spark directives and `bs` is another package's prefix. These\n * are the first attribute directives in ng-spark; every existing selector is an element.\n *\n * ## Targeting one query\n *\n * Each slot takes an optional query alias or id as its value. A detail page renders one card per\n * entry in `EntityTypeDefinition.Queries`, so a host that supplies a bare slot would decorate\n * every one of them identically — rarely what is wanted. A targeted slot applies to that query;\n * an untargeted one is the fallback for the rest.\n *\n * ```html\n * <span *sparkQueryIcon=\"'cars'\"><spark-icon name=\"car-front\" /></span>\n * <span *sparkQueryIcon><spark-icon name=\"table\" /></span>\n * ```\n *\n * Matching is case-insensitive, against the query's alias and then its id. This is the\n * `bsPriorityNavItem` shape: a value input aliased to the selector, collected with\n * `contentChildren`.\n */\n\n/** Resolves a slot list to the one that applies to a query: targeted first, then untargeted. */\nexport function slotFor<T extends { forQuery: () => string }>(\n slots: readonly T[],\n query: SparkQuery | null,\n): T | null {\n if (!slots.length) return null;\n\n const matches = (target: string) =>\n !!target && (\n target.localeCompare(query?.alias ?? '', undefined, { sensitivity: 'accent' }) === 0 ||\n target.localeCompare(query?.id ?? '', undefined, { sensitivity: 'accent' }) === 0);\n\n // A targeted slot wins over the catch-all even when it is declared later: \"this one query\"\n // is the more specific statement, and declaration order in a template is not a priority.\n return slots.find(s => matches(s.forQuery())) ?? slots.find(s => !s.forQuery()) ?? null;\n}\n\n/**\n * The icon at the header's leading edge. No default: nothing in the model describes one.\n *\n * ```html\n * <spark-query-card [queryId]=\"'cars'\">\n * <spark-icon *sparkQueryIcon name=\"car-front\" />\n * </spark-query-card>\n * ```\n */\n@Directive({ selector: '[sparkQueryIcon]' })\nexport class SparkQueryIconDirective {\n readonly templateRef = inject<TemplateRef<SparkQuerySlotContext>>(TemplateRef);\n\n /** Query alias or id this slot applies to. Empty targets every query on the page. */\n readonly forQuery = input('', { alias: 'sparkQueryIcon' });\n\n static ngTemplateContextGuard(\n _dir: SparkQueryIconDirective,\n ctx: unknown,\n ): ctx is SparkQuerySlotContext {\n return true;\n }\n}\n\n/**\n * The header caption. Defaults to the query's translated description, falling back to its name.\n *\n * The context carries that resolved default as `$implicit`, so a host can decorate it — add a\n * count, a badge — without re-resolving the translation itself.\n */\n@Directive({ selector: '[sparkQueryCaption]' })\nexport class SparkQueryCaptionDirective {\n readonly templateRef = inject<TemplateRef<SparkQueryCaptionContext>>(TemplateRef);\n\n readonly forQuery = input('', { alias: 'sparkQueryCaption' });\n\n static ngTemplateContextGuard(\n _dir: SparkQueryCaptionDirective,\n ctx: unknown,\n ): ctx is SparkQueryCaptionContext {\n return true;\n }\n}\n\n/**\n * The buttons at the header's trailing edge. Defaults to the server-declared custom actions.\n *\n * The context carries those actions and the current selection, so a host that wants its own\n * buttons ALONGSIDE the server's can render both rather than choosing. Without that, overriding\n * this slot to add one button would silently drop every action the type declares — and the\n * server's actions are the ones carrying `selectionRule` and the permission filter.\n *\n * ```html\n * <ng-container *sparkQueryActions=\"let actions; selection as rows\">\n * <button (click)=\"export(rows)\">Export</button>\n * </ng-container>\n * ```\n */\n@Directive({ selector: '[sparkQueryActions]' })\nexport class SparkQueryActionsDirective {\n readonly templateRef = inject<TemplateRef<SparkQueryActionsContext>>(TemplateRef);\n\n readonly forQuery = input('', { alias: 'sparkQueryActions' });\n\n static ngTemplateContextGuard(\n _dir: SparkQueryActionsDirective,\n ctx: unknown,\n ): ctx is SparkQueryActionsContext {\n return true;\n }\n}\n\n/** Context for the icon slot: the query whose card is being rendered. */\nexport class SparkQuerySlotContext {\n $implicit: SparkQuery | null = null;\n}\n\nexport class SparkQueryCaptionContext {\n /** The caption the card would have rendered: description, or the query name. */\n $implicit = '';\n query: SparkQuery | null = null;\n}\n\nexport class SparkQueryActionsContext {\n /** The custom actions the card would have rendered, already filtered for this query. */\n $implicit: CustomActionDefinition[] = [];\n /** Rows currently ticked. Empty unless an action is selection-gated. */\n selection: PersistentObject[] = [];\n query: SparkQuery | null = null;\n}\n","import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';\nimport { CommonModule, NgComponentOutlet } from '@angular/common';\nimport { RouterModule } from '@angular/router';\nimport { EntityAttributeDefinition, SparkCellColumn } from '@mintplayer/ng-spark/models';\nimport { ReferenceChip } from '@mintplayer/ng-spark/pipes';\nimport { SparkGridRenderers } from './spark-grid-renderers';\n\n/**\n * One cell of a Spark table, wherever that table is.\n *\n * ## Why this exists\n *\n * The cell markup was written out three times: twice in the query grids (since merged into\n * {@link SparkQueryGridComponent}) and once more in the AsDetail table on the PO detail page. The\n * third copy was never counted, and it had already drifted — a `boolean` column rendered the text\n * `\"true\"` there while the grid rendered a checkbox, a `color` rendered its hex string rather than\n * a swatch, and a custom renderer was dispatched by a second, hand-copied lookup.\n *\n * ## What it does and does not own\n *\n * It owns **presentation**: which control a `dataType` becomes, and dispatching a declared custom\n * renderer. It does not own **value resolution**, and deliberately so — the two callers read from\n * genuinely different row models. A query row is a `PersistentObject` with an attribute list and\n * an id; an AsDetail row is a plain dictionary of embedded values with neither. Trying to unify\n * that would put a second row-access path inside this component and buy nothing.\n *\n * So the caller resolves the value with whichever pipe fits its row model, and passes the result.\n *\n * ## The two links are not the same link, and only one is here\n *\n * `link` is for a cell whose own value points at another entity — an AsDetail reference column.\n * The query grid's first-column link is a different rule (it points at the row's own detail page,\n * gated on `Read`), and it stays in the grid, wrapping this component. Passing both would nest\n * anchors, which is invalid HTML; the grid therefore leaves `link` unset.\n */\n@Component({\n selector: 'spark-grid-cell',\n imports: [CommonModule, NgComponentOutlet, RouterModule],\n templateUrl: './spark-grid-cell.component.html',\n styleUrl: './spark-grid-cell.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkGridCellComponent {\n private readonly renderers = inject(SparkGridRenderers);\n\n /** The column being rendered. Its `dataType` and `renderer` decide everything below. */\n column = input.required<SparkCellColumn>();\n\n /**\n * What the caller's value pipe produced: the display text for most columns, and the raw value\n * for `boolean` and `color`, which need the value rather than a rendering of it.\n */\n display = input<unknown>(null);\n\n /**\n * The value handed to a declared custom renderer.\n *\n * Separate from {@link display} because they are not the same thing: a renderer receives the\n * underlying value — for AsDetail, the nested object itself — while `display` has already been\n * flattened to something printable.\n */\n rendererValue = input<unknown>(null);\n\n /** The row, passed through to a custom renderer as `item`. */\n item = input<unknown>(null);\n\n /**\n * Pre-resolved chips for a reference-array column, or empty when the column is not one.\n *\n * Resolved by the caller because the label source differs: a query row carries a per-id\n * breadcrumb map, while an AsDetail row's `__sparkBreadcrumbs` is keyed by column name only and\n * so cannot label the members of an array. Rather than render a row of raw ids, an AsDetail\n * caller passes nothing and the cell falls through to text.\n */\n chips = input<ReferenceChip[]>([]);\n\n /** Route for a cell whose value references another entity. See the class comment. */\n link = input<unknown[] | null>(null);\n\n protected readonly rendererComponent = computed(() => this.renderers.columnComponentFor(this.column()));\n\n protected readonly rendererInputs = computed(() => {\n const component = this.rendererComponent();\n return component\n ? this.renderers.cellInputsFor(component, this.rendererValue(), this.column(), this.item())\n : {};\n });\n\n /** Null and undefined are distinct from `false` here — see the template. */\n protected readonly isUnsetBoolean = computed(() => this.display() == null);\n\n /**\n * {@link display} when it really is a `Date`, and `null` otherwise.\n *\n * Angular's `DatePipe` does not degrade on a non-date: it **throws**\n * `NG02100: InvalidPipeArgument`, which would take down the whole cell. Both cell pipes\n * deliberately fall back to the raw text for an unparseable date rather than hiding the stored\n * value, so that text reaches this component and must not be piped. A template cannot express\n * `instanceof`, hence the computed.\n */\n protected readonly dateValue = computed(() => {\n const value = this.display();\n return value instanceof Date && !Number.isNaN(value.getTime()) ? value : null;\n });\n}\n","@if (rendererComponent(); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: rendererInputs()\"></ng-container>\n} @else if (column().dataType === 'boolean') {\n <!-- [indeterminate] matters: without it a null boolean renders as an unchecked box, which reads\n as an explicit `false`. One of the three copies of this cell bound it and the others had\n drifted, so the same column said different things on a detail page and in a grid. -->\n <input type=\"checkbox\"\n [checked]=\"display() === true\"\n [indeterminate]=\"isUnsetBoolean()\"\n disabled\n onclick=\"return false;\">\n} @else if (column().dataType === 'date' || column().dataType === 'datetime') {\n <!--\n Formatted in ONE place for both grids. Before this, a date column printed whatever its pipe\n produced, which was the raw ISO string — `2026-09-07T13:25:57.3119825Z` in a table cell. Both\n cell pipes now hand over a real Date, and `date:` accepts a string too, so an unparseable value\n that fell back to text still renders as that text rather than blank.\n -->\n @if (dateValue(); as when) {\n {{ when | date:(column().dataType === 'date' ? 'mediumDate' : 'short') }}\n } @else {\n {{ display() }}\n }\n} @else if (column().dataType === 'color') {\n @if (display(); as colorVal) {\n <!-- Shares `.spark-color-swatch` with the detail page, which is where the sizing already\n lived. It used to be inline here because the grid rendered inside <mp-datatable>'s\n shadow root, where neither this component's scoped rules nor Bootstrap's arrived;\n ng-bootstrap 22.18.0 moved the datatable to the light DOM, so the class reaches it. -->\n <span class=\"spark-color-swatch d-inline-block align-middle border rounded\"\n [style.background-color]=\"colorVal\"></span>\n }\n} @else if (column().dataType === 'image') {\n @if (display(); as src) {\n <!-- `alt` is empty on purpose — the cell is decorative next to the row's own labelled\n columns, and a filename read aloud is worse than nothing. -->\n <img [src]=\"src\" alt=\"\" loading=\"lazy\" class=\"spark-grid-image align-middle rounded\">\n }\n} @else if (column().dataType === 'url') {\n @if (display(); as href) {\n <!-- rel is not optional with target=_blank: without noopener the opened page gets a handle on\n this one through window.opener, and these hrefs are data. -->\n <a [href]=\"href\" target=\"_blank\" rel=\"noopener noreferrer\">{{ href }}</a>\n }\n} @else if (chips().length) {\n <span class=\"d-inline-flex flex-wrap gap-1\">\n @for (chip of chips(); track chip.id) {\n <span class=\"spark-chip\">{{ chip.label }}</span>\n }\n </span>\n} @else if (link(); as route) {\n <a [routerLink]=\"route\">{{ display() }}</a>\n} @else {\n {{ display() }}\n}\n","import { ChangeDetectionStrategy, Component, computed, effect, inject, input, model, output, signal, untracked, Type } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { RouterModule } from '@angular/router';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, DatatableSettings, type BsDatatableFetch } from '@mintplayer/ng-bootstrap/datatable';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SparkQueryRefreshService } from '@mintplayer/ng-spark/client-operations';\nimport { cellValue } from '@mintplayer/ng-spark/renderers';\nimport { QueryCellValuePipe, QueryReferenceChipsPipe, ResolveTranslationPipe, TranslateKeyPipe } from '@mintplayer/ng-spark/pipes';\nimport { SparkAttributeDescriptionComponent } from '@mintplayer/ng-spark/attribute-description';\nimport { SparkLanguageService, SparkService } from '@mintplayer/ng-spark/services';\nimport {\n CustomActionDefinition,\n EntityAttributeDefinition,\n EntityType,\n LookupReference,\n QueryColumn,\n QueryResultItem,\n SparkQuery,\n filterQueryActions,\n parseSelectionRule,\n selectionModeFor,\n valueFor,\n} from '@mintplayer/ng-spark/models';\nimport { SPARK_GRID_PAGE_SIZES, initialGridSettings, isVirtualScrollingQuery } from './spark-grid-columns';\nimport { SparkGridRenderers } from './spark-grid-renderers';\nimport { SparkGridCellComponent } from './spark-grid-cell.component';\n\n/**\n * The one Spark grid: a `<bs-datatable>` rendering a query or a sub-query.\n *\n * This replaces two components that were the same grid written twice — and, counting\n * `spark-query-list`'s streaming and paged branches, the `<bs-datatable>` element itself written\n * three times. The duplication had already produced four user-visible bugs, each fixed on one\n * side and not the other: `[indeterminate]` on null booleans, permission state surviving a failed\n * reload, a swallowed fetch failure, and virtual-scroll sizing. `SparkGridRenderers` was\n * extracted to stop that and could only take the stateless helpers with it; this takes the rest.\n *\n * ## What it deliberately does NOT own: streaming\n *\n * `spark-grid-renderers.ts` records why — a websocket dependency graph must not reach the bundle\n * of every PO detail page, none of which stream. So rows can come from **either** side:\n *\n * - unbound `data` — the grid fetches for itself, paging and sorting server-side;\n * - bound `data` — the grid renders what it is given and never fetches.\n *\n * `spark-query-list` keeps the socket and feeds its snapshot in. This is the line `bs-datatable`\n * itself draws: `[data]` and `[fetch]` are mutually exclusive, and binding both makes `[fetch]`\n * win silently.\n *\n * ## Reading its state\n *\n * `query`, `entityType`, `customActions`, `selection`, `canRead`, `canCreate` and `resultCount`\n * are readable so a host can render chrome around the grid. Read them through a template\n * reference variable — `<spark-query-grid #grid>` … `grid.query()` — not `viewChild`: hosts wrap\n * grids in `@if`, where a `viewChild` is intermittently undefined.\n */\n@Component({\n selector: 'spark-query-grid',\n imports: [CommonModule, RouterModule, BsAlertComponent, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsSpinnerComponent, SparkGridCellComponent, ResolveTranslationPipe, QueryCellValuePipe, QueryReferenceChipsPipe, TranslateKeyPipe, SparkAttributeDescriptionComponent],\n templateUrl: './spark-query-grid.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkQueryGridComponent {\n private readonly sparkService = inject(SparkService);\n private readonly gridRenderers = inject(SparkGridRenderers);\n private readonly queryRefresh = inject(SparkQueryRefreshService);\n readonly lang = inject(SparkLanguageService);\n\n /** Query alias or id. */\n queryId = input.required<string>();\n\n /**\n * The parent persistent object this query is scoped to, when it has one.\n *\n * Optional, because not every query is a detail of something: a page can host a grid that\n * stands on its own — \"my accounts\", a dashboard list — and the server already treats an absent\n * parent as \"no parent\" rather than as an error. Requiring these made that shape impossible to\n * express: the component simply never loaded, with no request, no error and no log.\n *\n * Pass both or neither. One without the other is ignored, matching `SparkService.executeQuery`,\n * which omits either param when it is falsy, and the execute endpoint, which resolves a parent\n * only when both are present.\n */\n parentId = input<string>('');\n parentType = input<string>('');\n\n /**\n * Rows supplied from outside. When bound, the grid renders these and runs no fetch.\n *\n * This is how streaming stays out of this component (see the class comment). `null` — the\n * default — means \"fetch for yourself\"; an empty array means \"you have been given no rows\",\n * which is a different statement and renders an empty grid rather than triggering a load.\n */\n data = input<QueryResultItem[] | null>(null);\n\n /**\n * Server-side search term, passed through to the query.\n *\n * An input rather than a box, so the host owns the control and the grid owns the request. A\n * host with client-side rows filters them itself before binding `data`.\n */\n search = input<string>('');\n\n /**\n * Column metadata for externally supplied rows. Required whenever `data` is bound, because a\n * projection cannot describe itself — there is no per-row metadata left to infer it from.\n */\n columns = input<QueryColumn[] | null>(null);\n\n /**\n * Change this to re-run the query. Any value works; only its identity matters.\n *\n * A declarative token rather than only a `reload()` method, because calling a method means\n * holding a component handle, and hosts wrap this grid in `@if`, where a `viewChild` is\n * intermittently undefined.\n *\n * This drives the CHEAP refresh (see {@link reload}). It deliberately does not feed the main\n * effect: re-running `loadData` would re-resolve the query, the entity types, the permissions\n * and the lookups, and reset the user's page and sort on every button press.\n */\n reloadToken = input<unknown>(null);\n\n /**\n * Paging and sorting. Two-way, so a host driving `data` can sort those rows by whatever the\n * user actually clicked — the datatable writes the new sort back through here.\n */\n settings = model(new DatatableSettings({\n perPage: { values: SPARK_GRID_PAGE_SIZES, selected: SPARK_GRID_PAGE_SIZES[0] },\n page: { values: [1], selected: 1 },\n sortColumns: [],\n }));\n\n /** Rows the user has ticked. Two-way so chrome outside the grid can read and clear them. */\n selection = model<QueryResultItem[]>([]);\n\n /**\n * Replaces where the first column's link points, per row.\n *\n * Return `null` to suppress the link for that row — useful when a grid mixes rows that have a\n * detail page with rows that do not.\n *\n * ⚠️ **It changes the destination, not the permission.** `canRead()` still gates whether any\n * link is rendered at all, and this function is never consulted when that gate is closed. It\n * cannot be used to reach a row the rights model withheld; it exists for the case where the\n * row's natural destination is not `/po/{type}/{id}` — a composed row that maps to a page of\n * its own, or a grid embedded in a route that owns its own child paths.\n */\n rowRoute = input<((row: QueryResultItem) => unknown[] | null) | null>(null);\n\n /** Emitted whenever a load or a page fetch fails, for a host in bespoke chrome. */\n error = output<HttpErrorResponse>();\n rowClicked = output<QueryResultItem>();\n customActionExecuted = output<{ action: CustomActionDefinition }>();\n\n colors = Color;\n\n /**\n * Where the first column's link points for this row: the host's `rowRoute` when it supplied one,\n * otherwise the row's own detail page.\n *\n * A method rather than a computed because the answer is per row, and the template already\n * iterates rows — a computed would have to be a map keyed by id, rebuilt on every page.\n */\n protected rowRouteFor(row: QueryResultItem): unknown[] | null {\n const custom = this.rowRoute();\n if (custom) return custom(row);\n\n const type = this.entityType();\n\n // ⚠️ A composed type has no per-row detail page by construction: its rows are computed, and\n // `{Name}Actions.OnLoadAsync` serves ONE page which is free to ignore the id it was given. So\n // /po/{type}/{rowId} does not 404 — it silently renders that same page, which is worse, because\n // nothing looks wrong. This branch is live in DemoApp today: Read/StartPage implies\n // Query/StartPage, so the composed grid renders with canRead() true and every row linked.\n //\n // `clrType` is absent exactly for those types and is already on the wire; the grid simply never\n // consulted it. A host whose composed rows DO have a page says so with `rowRoute`.\n if (!type?.clrType) return null;\n\n return ['/po', type.alias || type.id, row.id];\n }\n\n query = signal<SparkQuery | null>(null);\n entityType = signal<EntityType | null>(null);\n allEntityTypes = signal<EntityType[]>([]);\n lookupReferenceOptions = signal<Record<string, LookupReference>>({});\n loading = signal(true);\n canRead = signal(false);\n canCreate = signal(false);\n resultCount = signal<number | null>(null);\n customActions = signal<CustomActionDefinition[]>([]);\n\n /** Names the server withheld for this RESULT; see QueryResult.disabledActions. */\n private readonly disabledActions = signal<string[]>([]);\n\n /**\n * The actions actually offered for this result.\n *\n * The catalogue at `/spark/actions/{objectTypeId}` is per TYPE and is never told what an\n * execution returned, so an action that applies to only some results cannot be filtered there.\n * A custom query withholds what does not apply via `CustomQueryArgs.DisableActions(...)`, and\n * the answer arrives on the result.\n *\n * An affordance, not a permission -- the action handler still refuses on its own terms.\n */\n visibleCustomActions = computed(() => {\n const withheld = this.disabledActions();\n if (!withheld.length) return this.customActions();\n\n const lowered = new Set(withheld.map(name => name.toLowerCase()));\n return this.customActions().filter(action => !lowered.has(action.name.toLowerCase()));\n });\n fetchFn = signal<BsDatatableFetch<QueryResultItem> | null>(null);\n\n /**\n * Why the component renders its own failure instead of only reporting one.\n *\n * `SparkService` is a bare `firstValueFrom` passthrough with no interceptor, so every failure\n * surfaces here and nowhere else. A host embedding this grid cannot surface what it never sees,\n * and the default has to be visible with no host cooperation — hence a rendered alert, not just\n * an output.\n */\n errorMessage = signal<string | null>(null);\n\n /** 'none' unless an action is selection-gated, so unaffected grids gain no checkbox column. */\n selectionMode = computed(() => selectionModeFor(this.customActions()));\n\n isVirtualScrolling = computed(() => isVirtualScrollingQuery(this.query()));\n\n /**\n * Columns as sent with the most recent fetched page.\n *\n * A host binding `data` (streaming) supplies its own via the `columns` input instead — the\n * snapshot carries them once, exactly as a paged result does.\n */\n private readonly fetchedColumns = signal<QueryColumn[]>([]);\n\n /** Every column on the wire, drawn or not — what renderers and lookups resolve against. */\n allColumns = computed(() => this.columns() ?? this.fetchedColumns());\n\n /**\n * The columns the grid draws. `isVisible: false` ships a value without a column, so a renderer\n * can read a sibling the grid does not show; undefined means visible, so a server that predates\n * the field still draws everything.\n */\n visibleColumns = computed(() => this.allColumns().filter(c => c.isVisible !== false));\n\n /**\n * True when rows do not come from this component's own fetch.\n *\n * Either because the host bound `data`, or because the query streams — a streaming query's rows\n * arrive over a socket and `/execute` is not a way to get them. The grid recognises the second\n * case itself rather than waiting to be told, because it resolves the query before the host can\n * see it: left to `data` alone, every streaming grid would fire one pointless fetch on mount,\n * before the host had anything to bind.\n */\n hasExternalData = computed(() =>\n this.data() !== null || this.query()?.isStreamingQuery === true);\n\n /** Whether an action's selection rule is satisfied right now. The server checks it again. */\n isActionEnabled(action: CustomActionDefinition): boolean {\n return parseSelectionRule(action.selectionRule)(this.selection().map(r => r.id).length);\n }\n\n constructor() {\n effect(() => {\n const qId = this.queryId();\n const pId = this.parentId();\n const pType = this.parentType();\n // Only the query id is required. Requiring a parent here is what made a standalone grid\n // silently render nothing.\n if (qId) {\n this.loadData(qId, pId, pType);\n } else {\n // No query id at all. `loading` starts true, so without this the component would spin\n // forever instead of saying anything.\n this.loading.set(false);\n }\n });\n\n // Separate effect, so the token drives the cheap refresh and never the full metadata reload.\n // `first` skips the initial run: the effect above has already fetched, and reacting to the\n // token's starting value would double-fetch on mount.\n let first = true;\n effect(() => {\n // Both the host's token and the server's refreshQuery drive the same cheap refresh.\n this.reloadToken();\n this.queryRefresh.tokenFor(this.queryId());\n if (first) { first = false; return; }\n untracked(() => this.reload());\n });\n\n // A new search term must refetch even when page, perPage and sort are unchanged — the\n // datatable dedupes reloads by exactly that triple, and a new fetch identity is what resets\n // its dedupe key. Skipping the first run keeps mount to a single request.\n let firstSearch = true;\n effect(() => {\n this.search();\n if (firstSearch) { firstSearch = false; return; }\n untracked(() => this.onSearchChanged());\n });\n }\n\n /**\n * Re-run the query, keeping the current page, sort and scroll position.\n *\n * Data-level on purpose: it re-seeds the fetch closure and nothing else. For a definition\n * change — new columns, a renamed query — the inputs themselves must change; that is the\n * expensive path. Inert when rows come from the host: there is nothing here to re-run.\n */\n reload(): void {\n if (this.hasExternalData()) return;\n const q = this.query();\n if (q) this.fetchFn.set(this.makeFetch(q, this.parentId(), this.parentType()));\n }\n\n private onSearchChanged(): void {\n if (this.hasExternalData()) return;\n const s = this.settings();\n // Back to page 1: the old page number means nothing against a different result set.\n this.settings.set(new DatatableSettings({\n perPage: { values: s.perPage.values, selected: s.perPage.selected },\n page: { values: [1], selected: 1 },\n sortColumns: s.sortColumns,\n }));\n this.reload();\n }\n\n async onCustomAction(action: CustomActionDefinition): Promise<void> {\n if (action.confirmationMessageKey) {\n const message = this.lang.t(action.confirmationMessageKey) || 'Are you sure?';\n if (!confirm(message)) return;\n }\n try {\n // The sub-query's container travels with the action (#327). Without it an action invoked\n // from a company's Cars tab could not tell it was on a company's page at all — the grid knew\n // (it filters the rows by that parent) and simply dropped the fact on the way out.\n //\n // Sent as parentId/parentType, NOT as the `parent` argument: that one means an object of this\n // action's OWN type and is loaded under it server-side, so handing it a Company id for a Car\n // action refuses — correctly, and confusingly.\n const pId = this.parentId();\n const pType = this.parentType();\n await this.sparkService.executeCustomAction(\n this.entityType()!.id,\n action.name,\n undefined,\n this.selection().map(r => r.id),\n pId && pType ? { id: pId, type: pType } : undefined,\n // The query too: the server re-runs it narrowed to these ids, so the action receives the\n // rows this grid rendered rather than a re-derivation from documents.\n this.query()?.id);\n this.customActionExecuted.emit({ action });\n if (action.refreshOnCompleted) this.reload();\n } catch (e) {\n const err = e as HttpErrorResponse;\n this.errorMessage.set(err.error?.error || err.message || this.lang.t('common.actionFailed') || 'Action failed');\n }\n }\n\n private reportError(err: HttpErrorResponse): void {\n this.errorMessage.set(this.describe(err));\n this.error.emit(err);\n }\n\n /**\n * A 404 is deliberately generic.\n *\n * `Endpoints/Queries/Get.cs` answers 404 with byte-identical bodies for \"no such query\" and\n * \"you may not see it\", so existence is not disclosed (security audit M-3). The component\n * therefore genuinely cannot tell them apart, and both \"Not found\" and \"Access denied\" would be\n * a guess — one of them leaking, the other misleading.\n */\n private describe(err: HttpErrorResponse): string {\n if (err?.status === 404) {\n return this.lang.t('spark.query.unavailable') || 'This list is not available.';\n }\n return err?.error?.error || err?.message\n || this.lang.t('common.unexpectedError') || 'An unexpected error occurred';\n }\n\n private async loadData(queryId: string, parentId: string, parentType: string): Promise<void> {\n this.loading.set(true);\n this.errorMessage.set(null);\n this.fetchFn.set(null);\n // Reset everything derived from the previous query, not just the fetch. Leaving\n // `entityType`/`canRead` behind let a failed reload build a row link out of the PREVIOUS type\n // and the previous permission.\n this.query.set(null);\n this.entityType.set(null);\n this.canRead.set(false);\n this.canCreate.set(false);\n this.customActions.set([]);\n this.resultCount.set(null);\n // Ids from the previous query are meaningless against the next one, and would be POSTed as\n // though they belonged to it.\n this.selection.set([]);\n try {\n const [resolvedQuery, entityTypes] = await Promise.all([\n this.sparkService.getQuery(queryId),\n this.sparkService.getEntityTypes(),\n ]);\n\n this.query.set(resolvedQuery);\n this.allEntityTypes.set(entityTypes);\n\n const et = this.resolveEntityType(resolvedQuery, entityTypes);\n this.entityType.set(et);\n if (et) {\n const [permissions, actions] = await Promise.all([\n this.sparkService.getPermissions(et.id),\n this.sparkService.getCustomActions(et.id),\n ]);\n this.canRead.set(permissions.canRead);\n this.canCreate.set(permissions.canCreate);\n // 'query', not 'list'. The server model has always documented \"detail\" | \"query\" |\n // \"both\"; a filter testing for a value nothing emits renders the action NOWHERE.\n this.customActions.set(filterQueryActions(actions));\n }\n\n this.settings.set(initialGridSettings(resolvedQuery));\n // The datatable drives paging/sorting via [(settings)] and calls fetchFn per page. Virtual\n // scrolling is just the [virtualScroll] template flag.\n // `resolvedQuery`, not `hasExternalData()`: the query signal is set above, but reading the\n // computed here would depend on signal-read ordering inside an async method. Ask the value\n // directly.\n if (this.data() === null && !resolvedQuery?.isStreamingQuery) {\n this.fetchFn.set(this.makeFetch(resolvedQuery, parentId, parentType));\n }\n\n this.loadLookupReferenceOptions();\n } catch (e) {\n this.fetchFn.set(null);\n this.reportError(e as HttpErrorResponse);\n } finally {\n this.loading.set(false);\n }\n }\n\n /**\n * The query's entity type.\n *\n * The source-name fallback is not optional garnish: a `Database.*` query need not declare\n * `entityType`, and the sub-query grid — which matched on the declared name alone — rendered\n * those as an empty card with no columns, no rows and no error, while the identical query\n * rendered correctly as a page. Both grids are this one now, so there is one answer.\n */\n private resolveEntityType(query: SparkQuery | null, entityTypes: EntityType[]): EntityType | null {\n if (!query) return null;\n\n if (query.entityType) {\n return entityTypes.find(t =>\n t.name === query.entityType || t.alias === query.entityType?.toLowerCase()) ?? null;\n }\n\n const sourceName = extractSourceName(query.source);\n const singular = singularize(sourceName);\n return entityTypes.find(t =>\n t.name === sourceName || t.name === singular || t.clrType?.endsWith(singular)) ?? null;\n }\n\n private makeFetch(query: SparkQuery, parentId: string, parentType: string): BsDatatableFetch<QueryResultItem> {\n return (req) => this.sparkService.executeQuery(query.id, {\n sortColumns: req.sortColumns,\n skip: (req.page - 1) * req.perPage,\n take: req.perPage,\n search: this.search() || undefined,\n parentId, parentType,\n }).then(r => {\n this.errorMessage.set(null);\n this.resultCount.set(r.totalItems);\n // Columns come from the result now, not from the entity type: the server decides the query\n // surface (ShowedOn.Query) and is the same place the sort-column allow-list is checked.\n // ?? [] because a malformed or older response must render an empty grid, not throw inside a\n // computed — where the stack points at the column filter and not at the response that lacked them.\n this.fetchedColumns.set(r.columns ?? []);\n // Per-result, so it is re-read on every page rather than latched from the first.\n this.disabledActions.set(r.disabledActions ?? []);\n return {\n data: r.items,\n totalRecords: r.totalItems,\n totalPages: Math.ceil(r.totalItems / req.perPage) || 1,\n perPage: req.perPage,\n page: req.page,\n };\n }).catch((e: HttpErrorResponse) => {\n // Report before returning the empty page, or a failed fetch is indistinguishable from a\n // query that legitimately has no rows.\n this.reportError(e);\n this.resultCount.set(0);\n return { data: [], totalRecords: 0, totalPages: 1, perPage: req.perPage, page: req.page };\n });\n }\n\n private async loadLookupReferenceOptions(): Promise<void> {\n // Over ALL columns, not just the drawn ones: an undrawn column's value can still be rendered\n // by a renderer reading it as a sibling, and it would resolve to a raw key without its options.\n this.lookupReferenceOptions.set(await this.gridRenderers.loadLookupOptions(this.allColumns()));\n }\n\n /**\n * The underlying value a custom renderer receives, which is not the printable one.\n *\n * A projection is flat, so this is the cell's own value rather than a display string. It is\n * deliberately not the attribute-shaped `rendererValue`: a query row has no nested object to\n * fall back to, and reaching for one would hand every renderer `undefined`.\n */\n rendererValueFor(item: QueryResultItem, column: QueryColumn): unknown {\n return cellValue(valueFor(item, column.name));\n }\n\n getColumnRendererComponent(column: QueryColumn): Type<any> | null {\n return this.gridRenderers.columnComponentFor(column);\n }\n\n getColumnRendererInputs(component: Type<any>, item: QueryResultItem, column: QueryColumn): Record<string, any> {\n return this.gridRenderers.columnInputsFor(component, item, column);\n }\n}\n\nfunction extractSourceName(source: string): string {\n const dotIndex = source.indexOf('.');\n return dotIndex >= 0 ? source.substring(dotIndex + 1) : source;\n}\n\n/**\n * Enough English to map a query source onto a type name — `Cars` to `Car`, `People` to `Person`.\n *\n * Deliberately a small table plus three suffix rules rather than a library: it runs against type\n * names the application itself chose, and a wrong guess costs nothing, since the caller falls\n * through to matching the plural and the CLR type name.\n */\nfunction singularize(plural: string): string {\n const irregulars: Record<string, string> = {\n 'People': 'Person',\n 'Children': 'Child',\n 'Men': 'Man',\n 'Women': 'Woman',\n };\n if (irregulars[plural]) return irregulars[plural];\n if (plural.endsWith('ies')) return plural.slice(0, -3) + 'y';\n if (plural.endsWith('es')) return plural.slice(0, -2);\n if (plural.endsWith('s')) return plural.slice(0, -1);\n return plural;\n}\n","<!--\n Three explicit states, in this order, and the order is load-bearing.\n\n This template used to open with `@if (query(); as q)` wrapping EVERYTHING, and `query()` is only\n set after loadData's awaits resolve. Three separate bugs fell out of that one line: the spinner\n was unreachable on a first load (it rendered inside the gate, while `loading` starts true and\n `query` starts null), a first-load failure rendered ZERO DOM — no card, no message, nothing to\n see or report — and a failed RELOAD left the previous query's rows on screen.\n\n So: `loading` is checked first and outside any dependency on `query`, and the final `@else`\n always renders something. Do not fold these back into one gate, and do not move the spinner\n inside the `query()` branch.\n-->\n@if (loading()) {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n} @else if (query()) {\n <!-- A page-fetch failure while the grid is already resolved. Without this the catch returns an\n empty page and a failed query is indistinguishable from one that legitimately has no rows. -->\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n\n <!--\n One datatable, two row sources. `[data]` and `[fetch]` are mutually exclusive in\n ng-bootstrap — binding both makes `[fetch]` win silently — so exactly one is ever non-null\n here: `fetchFn` is left null whenever `data` is bound. See the class comment for why rows can\n arrive from outside at all (streaming must not put a websocket in every detail page's bundle).\n -->\n <bs-datatable\n [selectionMode]=\"selectionMode()\"\n [(selection)]=\"selection\"\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [data]=\"data()\"\n [fetch]=\"fetchFn()\"\n [(settings)]=\"settings\">\n @for (col of visibleColumns(); track col.name) {\n <div *bsDatatableColumn=\"col.name; sortable: true\">\n {{ (col.label | resolveTranslation) || col.name }}\n <spark-attribute-description [description]=\"col.description\" />\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (col of visibleColumns(); track col.name; let first = $first) {\n <td>\n @if (row) {\n <!-- The first column links to the row's detail page. Two things about this are\n routinely misread:\n\n 1. `cellContent` is projected INSIDE the anchor, so a custom `renderer` does NOT\n suppress this link — a renderer that emits its own <a> produces nested anchors\n (invalid HTML) rather than replacing this one.\n 2. `canRead()` is the whole gate, and it is the rights model: `Query` without\n `Read` lists the rows and withholds the link. Withhold `Read` for a query\n whose rows no detail page can load — a Custom.* query that fabricates rows in\n memory, say.\n 3. `rowRoute` replaces the DESTINATION only, never the gate: returning a route\n from it cannot make a row clickable that `canRead()` withheld, and returning\n null from it suppresses the link for that one row. -->\n @if (first && canRead() && rowRouteFor(row); as route) {\n <a [routerLink]=\"route\"\n (click)=\"rowClicked.emit(row)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, col: col }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, col: col }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-container>\n </bs-datatable>\n} @else {\n <!-- The query could not be resolved. Rendering something keeps the host's layout intact and,\n crucially, makes the failure visible: this branch used to render nothing at all. -->\n <bs-alert [type]=\"colors.danger\" class=\"mb-0\">\n {{ errorMessage() || ('spark.query.unavailable' | t) }}\n </bs-alert>\n}\n\n<ng-template #cellContent let-item let-col=\"col\">\n <!--\n Presentation lives in <spark-grid-cell>, shared with the AsDetail table on the PO detail page.\n Value resolution stays here: a query row is a PersistentObject with an attribute list, and the\n AsDetail table's rows are plain dictionaries, so only the rendering is common.\n\n `link` is deliberately not passed. The first-column link is the grid's own rule and wraps this\n template from outside; setting both would nest anchors.\n -->\n <spark-grid-cell\n [column]=\"col\"\n [display]=\"(col | queryCellValue:item:lookupReferenceOptions())\"\n [rendererValue]=\"rendererValueFor(item, col)\"\n [item]=\"item\"\n [chips]=\"(col | queryReferenceChips:item)\" />\n</ng-template>\n","import { ChangeDetectionStrategy, Component, computed, contentChildren, input, output, viewChild, TemplateRef } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsPriorityNavComponent, BsPriorityNavItemDirective } from '@mintplayer/ng-bootstrap/priority-nav';\nimport { ResolveTranslationPipe } from '@mintplayer/ng-spark/pipes';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { CustomActionDefinition, PersistentObject, QueryResultItem } from '@mintplayer/ng-spark/models';\nimport { inject } from '@angular/core';\nimport { SparkQueryGridComponent } from './spark-query-grid.component';\nimport {\n SparkQueryActionsDirective,\n SparkQueryCaptionDirective,\n SparkQueryIconDirective,\n slotFor,\n} from './spark-query-slots';\n\n/**\n * A `<bs-card>` around a {@link SparkQueryGridComponent}: icon, caption, actions, grid.\n *\n * ## Chrome is overridden, not replaced\n *\n * Every header region has a default, and a host replaces only the ones it supplies. That is what\n * lets this component serve the auto-rendered case: a sub-query is rendered once per entry in\n * `EntityTypeDefinition.Queries` with nobody projecting into it, and it must look right with no\n * host cooperation at all. A slot mechanism that only ever *replaced* chrome would leave that\n * call site blank — which is why an earlier design had the query carry its own chrome from the\n * server. Overriding a default needs no host; replacing one does.\n *\n * ## Two ways in, one set of templates\n *\n * Hand-written markup uses the structural directives and is found with `contentChildren`.\n * The auto-rendered path cannot: `spark-po-detail` is created by the router, so in a default app\n * there is no tag to project into. It therefore forwards `TemplateRef`s as inputs instead — a\n * directive cannot cross a component boundary but its template can, and that forwarding is\n * already the idiom in `spark-po-detail` (`extraActionsTemplate`, `extraContentTemplate`).\n *\n * Content wins over a forwarded input: the closer declaration is the more specific one.\n */\n@Component({\n selector: 'spark-query-card',\n imports: [CommonModule, BsCardComponent, BsCardHeaderComponent, BsPriorityNavComponent, BsPriorityNavItemDirective, SparkQueryGridComponent, ResolveTranslationPipe],\n templateUrl: './spark-query-card.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class SparkQueryCardComponent {\n readonly lang = inject(SparkLanguageService);\n\n queryId = input.required<string>();\n parentId = input<string>('');\n parentType = input<string>('');\n reloadToken = input<unknown>(null);\n data = input<QueryResultItem[] | null>(null);\n search = input<string>('');\n\n /**\n * Slots forwarded from a host that cannot project content — see the class comment. A card\n * reached through hand-written markup should use the structural directives instead.\n */\n iconTemplate = input<TemplateRef<any> | null>(null);\n captionTemplate = input<TemplateRef<any> | null>(null);\n actionsTemplate = input<TemplateRef<any> | null>(null);\n\n error = output<HttpErrorResponse>();\n rowClicked = output<QueryResultItem>();\n customActionExecuted = output<{ action: CustomActionDefinition }>();\n\n /**\n * Forwarded to the grid. Without this the escape hatch was unreachable from a card — i.e. from\n * every auto-rendered sub-query and program-unit query page, which is most grids.\n */\n rowRoute = input<((row: QueryResultItem) => unknown[] | null) | null>(null);\n\n colors = Color;\n\n private readonly iconSlots = contentChildren(SparkQueryIconDirective);\n private readonly captionSlots = contentChildren(SparkQueryCaptionDirective);\n private readonly actionSlots = contentChildren(SparkQueryActionsDirective);\n\n /**\n * The grid, read only to surface its state — the query, the actions, the selection — to this\n * component's own header.\n *\n * Optional rather than `required` on purpose. The header renders ABOVE the grid in this\n * template, so on the first change-detection pass the view query has not resolved yet and\n * `viewChild.required()` would throw where a plain one returns `undefined`. Everything below\n * therefore reads it defensively; the signal updates once the view initialises and the header\n * re-renders with the real query.\n *\n * A host reads grid state through a template reference variable instead, because a host may put\n * the grid behind an `@if`, where a view query genuinely is intermittently undefined.\n */\n protected readonly grid = viewChild(SparkQueryGridComponent);\n\n protected readonly query = computed(() => this.grid()?.query() ?? null);\n\n protected readonly iconTpl = computed(() =>\n slotFor(this.iconSlots(), this.query())?.templateRef ?? this.iconTemplate());\n\n protected readonly captionTpl = computed(() =>\n slotFor(this.captionSlots(), this.query())?.templateRef ?? this.captionTemplate());\n\n protected readonly actionsTpl = computed(() =>\n slotFor(this.actionSlots(), this.query())?.templateRef ?? this.actionsTemplate());\n\n /** The caption the card renders unless a slot replaces it. */\n protected readonly caption = computed(() => {\n const q = this.query();\n return (q?.description ? this.lang.resolve(q.description) : '') || q?.name || '';\n });\n\n protected readonly customActions = computed(() => this.grid()?.visibleCustomActions() ?? []);\n protected readonly selection = computed(() => this.grid()?.selection() ?? []);\n}\n","<!--\n The card is always rendered. A host that wants no card uses <spark-query-grid> directly — which\n is what the old `showCard=\"false\"` meant, expressed as a component choice rather than a flag.\n-->\n<bs-card class=\"d-block my-3\">\n <bs-card-header>\n <div class=\"d-flex align-items-center gap-2\">\n @if (iconTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: query() }\"></ng-container>\n }\n\n @if (actionsTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: customActions(), selection: selection(), query: query() }\"></ng-container>\n } @else if (customActions().length) {\n <!-- The default: the actions the server declares for this type. The nav renders only when\n there are any, so a query without actions is pixel-identical to a plain caption.\n\n Disabled, not hidden: hiding makes the affordance undiscoverable and reflows the\n priority nav on every selection change. The server enforces the same rule. -->\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-sm btn-outline-primary\"\n [disabled]=\"!grid()?.isActionEnabled(action)\" (click)=\"grid()?.onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n </bs-priority-nav>\n }\n\n <!--\n Caption last, actions first. The auto margin is conditional rather than fixed, and that is\n the point: with actions present `ms-auto` pushes the caption to the trailing edge, and with\n none it falls back to `me-auto` so a plain card looks exactly as it always did. A fixed\n `ms-auto` would have right-aligned the caption of every action-less query card in every app\n — a change nobody asked for, to fix a layout only some cards have.\n -->\n <span [class.ms-auto]=\"customActions().length\" [class.me-auto]=\"!customActions().length\">\n @if (captionTpl(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl; context: { $implicit: caption(), query: query() }\"></ng-container>\n } @else {\n {{ caption() }}\n }\n </span>\n </div>\n </bs-card-header>\n\n <div class=\"p-3\">\n <spark-query-grid\n [queryId]=\"queryId()\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\"\n [reloadToken]=\"reloadToken()\"\n [data]=\"data()\"\n [search]=\"search()\"\n [rowRoute]=\"rowRoute()\"\n (error)=\"error.emit($event)\"\n (rowClicked)=\"rowClicked.emit($event)\"\n (customActionExecuted)=\"customActionExecuted.emit($event)\" />\n </div>\n</bs-card>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -298,9 +298,70 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
298
298
|
args: [{ name: 'asDetailColumns', standalone: true, pure: true }]
|
|
299
299
|
}] });
|
|
300
300
|
|
|
301
|
+
/**
|
|
302
|
+
* The value of one cell in an `AsDetail` table, **typed by the column's `dataType`** rather than
|
|
303
|
+
* flattened to a string.
|
|
304
|
+
*
|
|
305
|
+
* <p>
|
|
306
|
+
* This used to end in `return String(value)` for everything, and declare `: string`. That is fine
|
|
307
|
+
* for a cell which is only interpolated, and wrong for one whose consumer inspects it —
|
|
308
|
+
* `spark-grid-cell` branches on the column type and binds `[checked]="display() === true"` and
|
|
309
|
+
* `[indeterminate]="display() == null"` for a boolean, so it needs the value and not a rendering
|
|
310
|
+
* of it.
|
|
311
|
+
* </p>
|
|
312
|
+
* <p>
|
|
313
|
+
* The visible symptom was a detail page showing unticked checkboxes for rows whose edit form showed
|
|
314
|
+
* them ticked — the edit form reads `attribute.objects` directly, so it never went through here. All
|
|
315
|
+
* three states of a `bool?` were affected, and one of them silently:
|
|
316
|
+
* </p>
|
|
317
|
+
* <ul>
|
|
318
|
+
* <li><b>true</b> — `'true' === true` is false, so it rendered <b>unchecked</b>;</li>
|
|
319
|
+
* <li><b>null</b> — became `''`, and `'' == null` is false, so it rendered unchecked <b>and
|
|
320
|
+
* determinate</b>, i.e. claiming to be false;</li>
|
|
321
|
+
* <li><b>false</b> — `'false'` is not `=== true`, so it rendered correctly <b>by accident</b>.</li>
|
|
322
|
+
* </ul>
|
|
323
|
+
* <p>
|
|
324
|
+
* Types that stay strings do so deliberately, not by omission. `color`, `image` and `url` are bound
|
|
325
|
+
* into a style, an `src` and an `href`, so a string is what they need. `Reference` and `AsDetail`
|
|
326
|
+
* resolve to a breadcrumb, which is a label rather than a value.
|
|
327
|
+
* </p>
|
|
328
|
+
* <p>
|
|
329
|
+
* `date` and `datetime` return a real `Date`. They arrive as ISO strings, and the cell used to
|
|
330
|
+
* print that string verbatim — `2026-09-07T13:25:57.3119825Z` in a table column. Returning the
|
|
331
|
+
* parsed value lets `spark-grid-cell` format it in one place for both grids; an unparseable value
|
|
332
|
+
* falls back to its text, because showing what is there beats showing `Invalid Date`.
|
|
333
|
+
* </p>
|
|
334
|
+
*/
|
|
301
335
|
class AsDetailCellValuePipe {
|
|
302
336
|
transform(row, parentAttr, col, asDetailRefOptions) {
|
|
303
337
|
const value = row[col.name];
|
|
338
|
+
// Before the null short-circuit, because for these types "absent" is a value the consumer has
|
|
339
|
+
// to be able to see: `null` is what makes a checkbox indeterminate rather than false, and it is
|
|
340
|
+
// what distinguishes "no number" from the number zero. `''` erases both.
|
|
341
|
+
switch (col.dataType) {
|
|
342
|
+
case 'boolean':
|
|
343
|
+
return typeof value === 'boolean' ? value : null;
|
|
344
|
+
case 'number':
|
|
345
|
+
case 'decimal': {
|
|
346
|
+
if (value == null || value === '')
|
|
347
|
+
return null;
|
|
348
|
+
const asNumber = typeof value === 'number' ? value : Number(value);
|
|
349
|
+
// A value that is not a number is passed through as text rather than reported as NaN: the
|
|
350
|
+
// cell's job is to show what is there, and "NaN" tells the reader nothing about it.
|
|
351
|
+
return Number.isNaN(asNumber) ? String(value) : asNumber;
|
|
352
|
+
}
|
|
353
|
+
case 'date':
|
|
354
|
+
case 'datetime': {
|
|
355
|
+
if (value == null || value === '')
|
|
356
|
+
return null;
|
|
357
|
+
if (value instanceof Date)
|
|
358
|
+
return Number.isNaN(value.getTime()) ? null : value;
|
|
359
|
+
const parsed = new Date(value);
|
|
360
|
+
// Same rule as the number branch: an unparseable date shows its own text rather than
|
|
361
|
+
// "Invalid Date", which would hide the value that is actually stored.
|
|
362
|
+
return Number.isNaN(parsed.getTime()) ? String(value) : parsed;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
304
365
|
if (value == null)
|
|
305
366
|
return '';
|
|
306
367
|
if (col.dataType === 'Reference' && col.query) {
|
|
@@ -547,6 +608,18 @@ class QueryCellValuePipe {
|
|
|
547
608
|
// checkbox instead of an unchecked one.
|
|
548
609
|
if (column.dataType === 'boolean')
|
|
549
610
|
return cell.value ?? null;
|
|
611
|
+
// Dates are parsed here for the same reason booleans are passed through above: the cell needs
|
|
612
|
+
// the value, not a rendering of it. Both grids feed `spark-grid-cell`, so both have to agree on
|
|
613
|
+
// the type or the same `datetime` column formats one way in a query grid and another in an
|
|
614
|
+
// AsDetail table. Unparseable input keeps its own text rather than becoming "Invalid Date".
|
|
615
|
+
if (column.dataType === 'date' || column.dataType === 'datetime') {
|
|
616
|
+
if (cell.value == null || cell.value === '')
|
|
617
|
+
return null;
|
|
618
|
+
if (cell.value instanceof Date)
|
|
619
|
+
return Number.isNaN(cell.value.getTime()) ? null : cell.value;
|
|
620
|
+
const parsed = new Date(cell.value);
|
|
621
|
+
return Number.isNaN(parsed.getTime()) ? String(cell.value) : parsed;
|
|
622
|
+
}
|
|
550
623
|
return cell.value ?? '';
|
|
551
624
|
}
|
|
552
625
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: QueryCellValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mintplayer-ng-spark-pipes.mjs","sources":["../../pipes/src/translate-key.pipe.ts","../../pipes/src/resolve-translation.pipe.ts","../../pipes/src/input-type.pipe.ts","../../pipes/src/apply-field-template.ts","../../pipes/src/attribute-value.pipe.ts","../../pipes/src/raw-attribute-value.pipe.ts","../../pipes/src/reference-display-value.pipe.ts","../../pipes/src/reference-attr-value.pipe.ts","../../pipes/src/reference-link-route.pipe.ts","../../pipes/src/reference-chips.pipe.ts","../../pipes/src/router-link.pipe.ts","../../pipes/src/as-detail-type.pipe.ts","../../pipes/src/as-detail-columns.pipe.ts","../../pipes/src/as-detail-cell-value.pipe.ts","../../pipes/src/as-detail-display-value.pipe.ts","../../pipes/src/can-create-detail-row.pipe.ts","../../pipes/src/can-delete-detail-row.pipe.ts","../../pipes/src/lookup-display-type.pipe.ts","../../pipes/src/lookup-display-value.pipe.ts","../../pipes/src/lookup-options.pipe.ts","../../pipes/src/inline-ref-options.pipe.ts","../../pipes/src/error-for-attribute.pipe.ts","../../pipes/src/icon-name.pipe.ts","../../pipes/src/array-value.pipe.ts","../../pipes/src/query-cell.pipe.ts","../../pipes/mintplayer-ng-spark-pipes.ts"],"sourcesContent":["import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\n\n@Pipe({ name: 't', pure: false, standalone: true })\nexport class TranslateKeyPipe implements PipeTransform {\n private readonly lang = inject(SparkLanguageService);\n\n transform(key: string): string {\n return this.lang.t(key);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { TranslatedString, resolveTranslation } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'resolveTranslation', standalone: true, pure: false })\nexport class ResolveTranslationPipe implements PipeTransform {\n transform(value: TranslatedString | undefined, fallback?: string): string {\n return resolveTranslation(value) || fallback || '';\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({ name: 'inputType', standalone: true, pure: true })\nexport class InputTypePipe implements PipeTransform {\n transform(dataType: string): string {\n switch (dataType) {\n case 'number':\n case 'decimal':\n return 'number';\n case 'boolean':\n return 'checkbox';\n case 'datetime':\n return 'datetime-local';\n case 'date':\n return 'date';\n case 'color':\n return 'color';\n case 'url':\n case 'image':\n // Both hold a URL, so `url` gets the browser's own validation and keyboard. `image` is a\n // link to an image rather than an upload: the value is still a string the author types.\n return 'url';\n default:\n return 'text';\n }\n }\n}\n","/**\n * Fills a `{Field}` template from a plain object's own fields. Used ONLY for AsDetail\n * nested-object summary display: an embedded value object (no id, no document) is rendered\n * client-side from its own fields. This is deliberately distinct from entity/reference\n * breadcrumbs — those are resolved recursively on the server (BreadcrumbResolver) and the\n * client only reads the resulting strings. Unknown or null placeholders render empty.\n */\nexport function applyFieldTemplate(template: string, data: Record<string, any>): string {\n return template.replace(/\\{(\\w+)\\}/g, (_match, propertyName) => {\n const value = data[propertyName];\n return value != null ? String(value) : '';\n });\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType, LookupReference, PersistentObject, nestedPoToDict, resolveTranslation } from '@mintplayer/ng-spark/models';\nimport { applyFieldTemplate } from './apply-field-template';\n\n@Pipe({ name: 'attributeValue', standalone: true, pure: true })\nexport class AttributeValuePipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null, entityType: EntityType | null, lookupRefOptions: Record<string, LookupReference>, allEntityTypes: EntityType[]): any {\n if (!item) return '';\n const attr = item.attributes.find(a => a.name === attrName);\n if (!attr) return '';\n\n if (attr.breadcrumb) return attr.breadcrumb;\n\n const attrDef = entityType?.attributes.find(a => a.name === attrName);\n if (attrDef?.dataType === 'AsDetail') {\n // Server emits nested PO(s) in attr.objects (array) / attr.object (single) — attr.value is null.\n if (attr.isArray) {\n const count = attr.objects?.length ?? 0;\n if (count === 0) return '';\n return `${count} item${count !== 1 ? 's' : ''}`;\n }\n if (attr.object) {\n // The server has already resolved this object's breadcrumb, and it can resolve templates\n // this side cannot. A type's breadcrumb may name a computed property that `[IgnoreProperty]`\n // keeps out of the model — HR's `Address.Crumb` is exactly that, `[Breadcrumb, IgnoreProperty]`\n // — so the template `{Crumb}` has no matching attribute here and never will. Recomputing it\n // client-side produced an empty string and fell through to \"(object)\" while the correct\n // \"Deinzestraat 231, 9700 Oudenaarde\" sat unread on `attr.object.breadcrumb`.\n if (attr.object.breadcrumb) return attr.object.breadcrumb;\n return this.formatAsDetailValue(attrDef, nestedPoToDict(attr.object), allEntityTypes);\n }\n }\n\n if (attrDef?.lookupReferenceType && attr.value != null && attr.value !== '') {\n const lookupRef = lookupRefOptions[attrDef.lookupReferenceType];\n if (lookupRef) {\n const option = lookupRef.values.find(v => v.key === String(attr.value));\n if (option) {\n return resolveTranslation(option.values) || option.key;\n }\n }\n }\n\n if (attrDef?.dataType === 'boolean') {\n return attr.value ?? null;\n }\n\n return attr.value ?? '';\n }\n\n private formatAsDetailValue(attrDef: EntityAttributeDefinition, value: Record<string, any>, allEntityTypes: EntityType[]): string {\n const asDetailType = allEntityTypes.find(t => t.clrType === attrDef.asDetailType);\n\n if (asDetailType?.breadcrumb) {\n const result = applyFieldTemplate(asDetailType.breadcrumb, value);\n if (result && result.trim()) return result;\n }\n\n // Last resort, reached when the type declares no breadcrumb or its template resolved to\n // nothing. Joining the scalar values is always more use to a reader than \"(object)\", which\n // named the failure rather than the row and looked identical for every unresolvable cell.\n return Object.values(value)\n .filter(v => v != null && typeof v !== 'object' && String(v).trim() !== '')\n .join(', ');\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'rawAttributeValue', standalone: true, pure: true })\nexport class RawAttributeValuePipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null): any {\n return item?.attributes.find(a => a.name === attrName)?.value;\n }\n}\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { EntityAttributeDefinition, PersistentObject, QueryResultItem } from '@mintplayer/ng-spark/models';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\n\n@Pipe({ name: 'referenceDisplayValue', standalone: true, pure: true })\nexport class ReferenceDisplayValuePipe implements PipeTransform {\n private readonly lang = inject(SparkLanguageService);\n\n transform(attr: EntityAttributeDefinition, formData: Record<string, any>, referenceOptions: Record<string, QueryResultItem[]>): string {\n const selectedId = formData[attr.name];\n if (!selectedId) return this.lang.t('notSelected');\n\n const options = referenceOptions[attr.name] || [];\n const selected = options.find(o => o.id === selectedId);\n // The server resolves a row's display string into `breadcrumb`; falling back to the id\n // beats showing nothing, and there is no third source now that a row carries no `name`.\n return selected?.breadcrumb || selectedId;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'referenceAttrValue', standalone: true, pure: true })\nexport class ReferenceAttrValuePipe implements PipeTransform {\n transform(item: PersistentObject, attrName: string): any {\n const attr = item.attributes.find(a => a.name === attrName);\n if (!attr) return '';\n if (attr.breadcrumb) return attr.breadcrumb;\n return attr.value ?? '';\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityType } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'referenceLinkRoute', standalone: true, pure: true })\nexport class ReferenceLinkRoutePipe implements PipeTransform {\n transform(referenceClrType: string, referenceId: any, allEntityTypes: EntityType[]): string[] | null {\n if (!referenceId || !referenceClrType) return null;\n const targetType = allEntityTypes.find(t => t.clrType === referenceClrType);\n if (!targetType) return null;\n\n // Presence in the catalogue means the caller may LIST this type; opening one is a different\n // right. Without this a type granted Query but not Read rendered a clickable reference whose\n // click refused on arrival — while the grid's own first column, three components away, gated on\n // canRead and got it right. Same question, two answers.\n if (targetType.canRead === false) return null;\n\n return ['/po', targetType.alias || targetType.id, referenceId];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject } from '@mintplayer/ng-spark/models';\n\nexport interface ReferenceChip {\n id: string;\n label: string;\n}\n\n/**\n * Resolves a multi-reference attribute (`dataType === 'Reference'`, `isArray === true`)\n * to a list of chips. The attribute's `value` carries the id array; `breadcrumbs` (a\n * server-resolved id → label map) provides each chip's display label, falling back to\n * the id when no breadcrumb is present. Mirrors the single-reference `breadcrumb`\n * display, applied per id.\n */\n@Pipe({ name: 'referenceChips', standalone: true, pure: true })\nexport class ReferenceChipsPipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null): ReferenceChip[] {\n const attr = item?.attributes.find(a => a.name === attrName);\n if (!attr || !Array.isArray(attr.value)) return [];\n const breadcrumbs = attr.breadcrumbs ?? {};\n return attr.value\n .filter(v => v != null && v !== '')\n .map(v => {\n const id = String(v);\n return { id, label: breadcrumbs[id] || id };\n });\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { ProgramUnit } from '@mintplayer/ng-spark/models';\n\n/**\n * Maps a program unit to the router commands that open it. Type comparisons are exact: the\n * server's loader canonicalizes `type` casing, so tolerating variants here would only mask a\n * server that stopped doing so.\n *\n * Returns null for a `url` unit — an external address is an `<a href>`, not a router link; the\n * component rendering the menu owns that branch.\n */\n@Pipe({ name: 'routerLink', standalone: true, pure: true })\nexport class RouterLinkPipe implements PipeTransform {\n transform(unit: ProgramUnit): string[] | null {\n if (unit.type === 'query') {\n return ['/query', unit.alias || unit.queryId!];\n } else if (unit.type === 'persistentObject') {\n const type = unit.alias || unit.persistentObjectId!;\n return unit.objectId ? ['/po', type, unit.objectId] : ['/po', type];\n } else if (unit.type === 'url') {\n return null;\n }\n return ['/'];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'asDetailType', standalone: true, pure: true })\nexport class AsDetailTypePipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, asDetailTypes: Record<string, EntityType>): EntityType | null {\n return asDetailTypes[attr.name] || null;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'asDetailColumns', standalone: true, pure: true })\nexport class AsDetailColumnsPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, asDetailTypes: Record<string, EntityType>): EntityAttributeDefinition[] {\n const type = asDetailTypes[attr.name];\n if (!type) return [];\n return type.attributes\n .filter(a => a.isVisible)\n .sort((a, b) => a.order - b.order);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { AS_DETAIL_BREADCRUMBS_KEY, EntityAttributeDefinition, PersistentObject, QueryResultItem, selfBreadcrumb } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'asDetailCellValue', standalone: true, pure: true })\nexport class AsDetailCellValuePipe implements PipeTransform {\n transform(row: Record<string, any>, parentAttr: EntityAttributeDefinition, col: EntityAttributeDefinition, asDetailRefOptions: Record<string, Record<string, QueryResultItem[]>>): string {\n const value = row[col.name];\n if (value == null) return '';\n\n if (col.dataType === 'Reference' && col.query) {\n // Prefer the breadcrumb the server already resolved by id — it is page-independent, so it\n // renders the label even when the referenced document falls outside the reference query's\n // first options page (issue #185).\n const serverBreadcrumb = (row[AS_DETAIL_BREADCRUMBS_KEY] as Record<string, string> | undefined)?.[col.name];\n if (serverBreadcrumb) return serverBreadcrumb;\n\n // Fallback: resolve against the loaded options page (legacy path).\n const parentOptions = asDetailRefOptions[parentAttr.name];\n if (parentOptions) {\n const options = parentOptions[col.name];\n if (options) {\n const match = options.find(o => o.id === value);\n if (match) return match.breadcrumb || String(value);\n }\n }\n }\n\n // A nested-AsDetail column's value is an inner dict, so String(value) produced \"[object\n // Object]\". The flattener kept that object's server-resolved breadcrumb for exactly this.\n if (col.dataType === 'AsDetail' && typeof value === 'object') {\n return selfBreadcrumb(value as Record<string, any>, col.asDetailType) ?? '';\n }\n\n return String(value);\n }\n}\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType, selfBreadcrumb } from '@mintplayer/ng-spark/models';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { applyFieldTemplate } from './apply-field-template';\n\n@Pipe({ name: 'asDetailDisplayValue', standalone: true, pure: true })\nexport class AsDetailDisplayValuePipe implements PipeTransform {\n private readonly lang = inject(SparkLanguageService);\n\n transform(attr: EntityAttributeDefinition, formData: Record<string, any>, asDetailTypes: Record<string, EntityType>): string {\n const value = formData[attr.name];\n if (!value) return this.lang.t('notSet');\n\n const asDetailType = asDetailTypes[attr.name] || null;\n\n // The server's own resolution wins, because it can render templates this side cannot: a\n // breadcrumb may name a property that `[IgnoreProperty]` deliberately keeps out of the model\n // (HR's `Address.Crumb`), and no amount of client-side substitution will ever find it. Passing\n // the type name filters out the mapper's \"template rendered blank\" placeholder, which is the\n // bare type name rather than an empty string — see `selfBreadcrumb`.\n const resolved = selfBreadcrumb(value, asDetailType?.name);\n if (resolved) return resolved;\n\n // Still correct for a template naming real, projected attributes (`\"{Street}, {City}\"`), which\n // is the common case and the only one reachable on the create path, where there is no server\n // object to have resolved anything yet.\n if (asDetailType?.breadcrumb) {\n const result = applyFieldTemplate(asDetailType.breadcrumb, value);\n if (result && result.trim()) return result;\n }\n\n return this.lang.t('clickToEdit');\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityPermissions } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'canCreateDetailRow', standalone: true, pure: true })\nexport class CanCreateDetailRowPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, permissions: Record<string, EntityPermissions>): boolean {\n const perms = permissions[attr.name];\n return perms ? perms.canCreate : true;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityPermissions } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'canDeleteDetailRow', standalone: true, pure: true })\nexport class CanDeleteDetailRowPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, permissions: Record<string, EntityPermissions>): boolean {\n const perms = permissions[attr.name];\n return perms ? perms.canDelete : true;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { ELookupDisplayType, EntityAttributeDefinition, LookupReference } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'lookupDisplayType', standalone: true, pure: true })\nexport class LookupDisplayTypePipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, lookupRefOptions: Record<string, LookupReference>): ELookupDisplayType {\n const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;\n return lookupRef?.displayType ?? ELookupDisplayType.Dropdown;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, LookupReference, resolveTranslation } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'lookupDisplayValue', standalone: true, pure: true })\nexport class LookupDisplayValuePipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, formData: Record<string, any>, lookupRefOptions: Record<string, LookupReference>): string {\n const currentValue = formData[attr.name];\n if (currentValue == null || currentValue === '') return '';\n\n const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;\n const options = lookupRef?.values.filter(v => v.isActive) || [];\n const selected = options.find(o => o.key === String(currentValue));\n if (!selected) return String(currentValue);\n\n return resolveTranslation(selected.values) || selected.key;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, LookupReference, LookupReferenceValue } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'lookupOptions', standalone: true, pure: true })\nexport class LookupOptionsPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, lookupRefOptions: Record<string, LookupReference>): LookupReferenceValue[] {\n const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;\n return lookupRef?.values.filter(v => v.isActive) || [];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, PersistentObject, QueryResultItem } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'inlineRefOptions', standalone: true, pure: true })\nexport class InlineRefOptionsPipe implements PipeTransform {\n transform(parentAttr: EntityAttributeDefinition, col: EntityAttributeDefinition, asDetailRefOptions: Record<string, Record<string, QueryResultItem[]>>): QueryResultItem[] {\n return asDetailRefOptions[parentAttr.name]?.[col.name] || [];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { ValidationError, resolveTranslation } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'errorForAttribute', standalone: true, pure: true })\nexport class ErrorForAttributePipe implements PipeTransform {\n transform(attrName: string, validationErrors: ValidationError[]): string | null {\n const error = validationErrors.find(e => e.attributeName === attrName);\n return error ? resolveTranslation(error.errorMessage) : null;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({ name: 'iconName', standalone: true, pure: true })\nexport class IconNamePipe implements PipeTransform {\n transform(value: string | undefined, fallback: string): string {\n const iconClass = value || fallback;\n // Strip 'bi-' prefix if present\n return iconClass.startsWith('bi-') ? iconClass.substring(3) : iconClass;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject, nestedPoToDisplayRow } from '@mintplayer/ng-spark/models';\n\n/**\n * Resolves an attribute to a list of flat row dicts for the detail-page table.\n * AsDetail array attributes carry their data as nested PersistentObjects in\n * <c>attr.objects</c>, not <c>attr.value</c> — the server stopped putting flat\n * dicts in <c>value</c> when AsDetail moved to its dedicated wire shape. Without\n * this branch, the detail page rendered AsDetail arrays as empty tables even\n * when the edit page (which reads <c>attr.objects</c> directly) showed rows.\n */\n@Pipe({ name: 'arrayValue', standalone: true, pure: true })\nexport class ArrayValuePipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null): Record<string, any>[] {\n const attr = item?.attributes.find(a => a.name === attrName);\n if (!attr) return [];\n if (attr.dataType === 'AsDetail' && attr.isArray && Array.isArray(attr.objects)) {\n return attr.objects.map(po => nestedPoToDisplayRow(po));\n }\n if (Array.isArray(attr.value)) return attr.value;\n return [];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport {\n LookupReference,\n QueryColumn,\n QueryResultItem,\n resolveTranslation,\n valueFor,\n} from '@mintplayer/ng-spark/models';\nimport { ReferenceChip } from './reference-chips.pipe';\n\n/**\n * The display text of one query-grid cell.\n *\n * The attribute-shaped sibling of this ({@link AttributeValuePipe}) still serves detail and edit\n * pages, which do work in attributes. They are deliberately not one pipe: a query row is a flat\n * projection with no nested objects and no per-row metadata, so the fallbacks that make sense\n * there — reaching into `attr.object`, recomputing a breadcrumb template client-side — are not\n * merely unnecessary here, they are unreachable. Sharing the code would mean carrying branches\n * that can never fire and inviting the next reader to feed one shape into the other.\n */\n@Pipe({ name: 'queryCellValue', standalone: true, pure: true })\nexport class QueryCellValuePipe implements PipeTransform {\n transform(\n column: QueryColumn,\n item: QueryResultItem | null,\n lookupRefOptions: Record<string, LookupReference>,\n ): any {\n const cell = valueFor(item, column.name);\n if (!cell) return '';\n\n // A resolved reference display wins: the server can resolve breadcrumb templates this side\n // cannot (a template may name a computed property `[IgnoreProperty]` keeps out of the model).\n if (cell.breadcrumb) return cell.breadcrumb;\n\n if (column.dataType === 'AsDetail') {\n // An array cell carries a child COUNT rather than the children, so the wording — and its\n // pluralisation — is decided here, where the language is. A single-child cell carries the\n // child object (for a renderer to read) and is displayed by the server-resolved breadcrumb\n // above, never by stringifying it here.\n if (!column.isArray) return '';\n const count = typeof cell.value === 'number' ? cell.value : 0;\n return count === 0 ? '' : `${count} item${count !== 1 ? 's' : ''}`;\n }\n\n if (column.lookupReferenceType && cell.value != null && cell.value !== '') {\n const lookupRef = lookupRefOptions[column.lookupReferenceType];\n const option = lookupRef?.values.find(v => v.key === String(cell.value));\n if (option) return resolveTranslation(option.values) || option.key;\n }\n\n // Null rather than '' so the cell can tell \"false\" from \"unset\" and render an indeterminate\n // checkbox instead of an unchecked one.\n if (column.dataType === 'boolean') return cell.value ?? null;\n\n return cell.value ?? '';\n }\n}\n\n/**\n * Resolves a multi-reference column (`dataType === 'Reference'`, `isArray === true`) to chips.\n *\n * The cell's `value` carries the id array and `breadcrumbs` the server-resolved id → label map,\n * falling back to the id itself when a label is missing — the same display rule as a single\n * reference, applied per id.\n */\n@Pipe({ name: 'queryReferenceChips', standalone: true, pure: true })\nexport class QueryReferenceChipsPipe implements PipeTransform {\n transform(column: QueryColumn, item: QueryResultItem | null): ReferenceChip[] {\n const cell = valueFor(item, column.name);\n if (!cell || !Array.isArray(cell.value)) return [];\n\n const breadcrumbs = cell.breadcrumbs ?? {};\n return cell.value\n .filter(v => v != null && v !== '')\n .map(v => {\n const id = String(v);\n return { id, label: breadcrumbs[id] || id };\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-pipes.mjs","sources":["../../pipes/src/translate-key.pipe.ts","../../pipes/src/resolve-translation.pipe.ts","../../pipes/src/input-type.pipe.ts","../../pipes/src/apply-field-template.ts","../../pipes/src/attribute-value.pipe.ts","../../pipes/src/raw-attribute-value.pipe.ts","../../pipes/src/reference-display-value.pipe.ts","../../pipes/src/reference-attr-value.pipe.ts","../../pipes/src/reference-link-route.pipe.ts","../../pipes/src/reference-chips.pipe.ts","../../pipes/src/router-link.pipe.ts","../../pipes/src/as-detail-type.pipe.ts","../../pipes/src/as-detail-columns.pipe.ts","../../pipes/src/as-detail-cell-value.pipe.ts","../../pipes/src/as-detail-display-value.pipe.ts","../../pipes/src/can-create-detail-row.pipe.ts","../../pipes/src/can-delete-detail-row.pipe.ts","../../pipes/src/lookup-display-type.pipe.ts","../../pipes/src/lookup-display-value.pipe.ts","../../pipes/src/lookup-options.pipe.ts","../../pipes/src/inline-ref-options.pipe.ts","../../pipes/src/error-for-attribute.pipe.ts","../../pipes/src/icon-name.pipe.ts","../../pipes/src/array-value.pipe.ts","../../pipes/src/query-cell.pipe.ts","../../pipes/mintplayer-ng-spark-pipes.ts"],"sourcesContent":["import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\n\n@Pipe({ name: 't', pure: false, standalone: true })\nexport class TranslateKeyPipe implements PipeTransform {\n private readonly lang = inject(SparkLanguageService);\n\n transform(key: string): string {\n return this.lang.t(key);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { TranslatedString, resolveTranslation } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'resolveTranslation', standalone: true, pure: false })\nexport class ResolveTranslationPipe implements PipeTransform {\n transform(value: TranslatedString | undefined, fallback?: string): string {\n return resolveTranslation(value) || fallback || '';\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({ name: 'inputType', standalone: true, pure: true })\nexport class InputTypePipe implements PipeTransform {\n transform(dataType: string): string {\n switch (dataType) {\n case 'number':\n case 'decimal':\n return 'number';\n case 'boolean':\n return 'checkbox';\n case 'datetime':\n return 'datetime-local';\n case 'date':\n return 'date';\n case 'color':\n return 'color';\n case 'url':\n case 'image':\n // Both hold a URL, so `url` gets the browser's own validation and keyboard. `image` is a\n // link to an image rather than an upload: the value is still a string the author types.\n return 'url';\n default:\n return 'text';\n }\n }\n}\n","/**\n * Fills a `{Field}` template from a plain object's own fields. Used ONLY for AsDetail\n * nested-object summary display: an embedded value object (no id, no document) is rendered\n * client-side from its own fields. This is deliberately distinct from entity/reference\n * breadcrumbs — those are resolved recursively on the server (BreadcrumbResolver) and the\n * client only reads the resulting strings. Unknown or null placeholders render empty.\n */\nexport function applyFieldTemplate(template: string, data: Record<string, any>): string {\n return template.replace(/\\{(\\w+)\\}/g, (_match, propertyName) => {\n const value = data[propertyName];\n return value != null ? String(value) : '';\n });\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType, LookupReference, PersistentObject, nestedPoToDict, resolveTranslation } from '@mintplayer/ng-spark/models';\nimport { applyFieldTemplate } from './apply-field-template';\n\n@Pipe({ name: 'attributeValue', standalone: true, pure: true })\nexport class AttributeValuePipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null, entityType: EntityType | null, lookupRefOptions: Record<string, LookupReference>, allEntityTypes: EntityType[]): any {\n if (!item) return '';\n const attr = item.attributes.find(a => a.name === attrName);\n if (!attr) return '';\n\n if (attr.breadcrumb) return attr.breadcrumb;\n\n const attrDef = entityType?.attributes.find(a => a.name === attrName);\n if (attrDef?.dataType === 'AsDetail') {\n // Server emits nested PO(s) in attr.objects (array) / attr.object (single) — attr.value is null.\n if (attr.isArray) {\n const count = attr.objects?.length ?? 0;\n if (count === 0) return '';\n return `${count} item${count !== 1 ? 's' : ''}`;\n }\n if (attr.object) {\n // The server has already resolved this object's breadcrumb, and it can resolve templates\n // this side cannot. A type's breadcrumb may name a computed property that `[IgnoreProperty]`\n // keeps out of the model — HR's `Address.Crumb` is exactly that, `[Breadcrumb, IgnoreProperty]`\n // — so the template `{Crumb}` has no matching attribute here and never will. Recomputing it\n // client-side produced an empty string and fell through to \"(object)\" while the correct\n // \"Deinzestraat 231, 9700 Oudenaarde\" sat unread on `attr.object.breadcrumb`.\n if (attr.object.breadcrumb) return attr.object.breadcrumb;\n return this.formatAsDetailValue(attrDef, nestedPoToDict(attr.object), allEntityTypes);\n }\n }\n\n if (attrDef?.lookupReferenceType && attr.value != null && attr.value !== '') {\n const lookupRef = lookupRefOptions[attrDef.lookupReferenceType];\n if (lookupRef) {\n const option = lookupRef.values.find(v => v.key === String(attr.value));\n if (option) {\n return resolveTranslation(option.values) || option.key;\n }\n }\n }\n\n if (attrDef?.dataType === 'boolean') {\n return attr.value ?? null;\n }\n\n return attr.value ?? '';\n }\n\n private formatAsDetailValue(attrDef: EntityAttributeDefinition, value: Record<string, any>, allEntityTypes: EntityType[]): string {\n const asDetailType = allEntityTypes.find(t => t.clrType === attrDef.asDetailType);\n\n if (asDetailType?.breadcrumb) {\n const result = applyFieldTemplate(asDetailType.breadcrumb, value);\n if (result && result.trim()) return result;\n }\n\n // Last resort, reached when the type declares no breadcrumb or its template resolved to\n // nothing. Joining the scalar values is always more use to a reader than \"(object)\", which\n // named the failure rather than the row and looked identical for every unresolvable cell.\n return Object.values(value)\n .filter(v => v != null && typeof v !== 'object' && String(v).trim() !== '')\n .join(', ');\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'rawAttributeValue', standalone: true, pure: true })\nexport class RawAttributeValuePipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null): any {\n return item?.attributes.find(a => a.name === attrName)?.value;\n }\n}\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { EntityAttributeDefinition, PersistentObject, QueryResultItem } from '@mintplayer/ng-spark/models';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\n\n@Pipe({ name: 'referenceDisplayValue', standalone: true, pure: true })\nexport class ReferenceDisplayValuePipe implements PipeTransform {\n private readonly lang = inject(SparkLanguageService);\n\n transform(attr: EntityAttributeDefinition, formData: Record<string, any>, referenceOptions: Record<string, QueryResultItem[]>): string {\n const selectedId = formData[attr.name];\n if (!selectedId) return this.lang.t('notSelected');\n\n const options = referenceOptions[attr.name] || [];\n const selected = options.find(o => o.id === selectedId);\n // The server resolves a row's display string into `breadcrumb`; falling back to the id\n // beats showing nothing, and there is no third source now that a row carries no `name`.\n return selected?.breadcrumb || selectedId;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'referenceAttrValue', standalone: true, pure: true })\nexport class ReferenceAttrValuePipe implements PipeTransform {\n transform(item: PersistentObject, attrName: string): any {\n const attr = item.attributes.find(a => a.name === attrName);\n if (!attr) return '';\n if (attr.breadcrumb) return attr.breadcrumb;\n return attr.value ?? '';\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityType } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'referenceLinkRoute', standalone: true, pure: true })\nexport class ReferenceLinkRoutePipe implements PipeTransform {\n transform(referenceClrType: string, referenceId: any, allEntityTypes: EntityType[]): string[] | null {\n if (!referenceId || !referenceClrType) return null;\n const targetType = allEntityTypes.find(t => t.clrType === referenceClrType);\n if (!targetType) return null;\n\n // Presence in the catalogue means the caller may LIST this type; opening one is a different\n // right. Without this a type granted Query but not Read rendered a clickable reference whose\n // click refused on arrival — while the grid's own first column, three components away, gated on\n // canRead and got it right. Same question, two answers.\n if (targetType.canRead === false) return null;\n\n return ['/po', targetType.alias || targetType.id, referenceId];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject } from '@mintplayer/ng-spark/models';\n\nexport interface ReferenceChip {\n id: string;\n label: string;\n}\n\n/**\n * Resolves a multi-reference attribute (`dataType === 'Reference'`, `isArray === true`)\n * to a list of chips. The attribute's `value` carries the id array; `breadcrumbs` (a\n * server-resolved id → label map) provides each chip's display label, falling back to\n * the id when no breadcrumb is present. Mirrors the single-reference `breadcrumb`\n * display, applied per id.\n */\n@Pipe({ name: 'referenceChips', standalone: true, pure: true })\nexport class ReferenceChipsPipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null): ReferenceChip[] {\n const attr = item?.attributes.find(a => a.name === attrName);\n if (!attr || !Array.isArray(attr.value)) return [];\n const breadcrumbs = attr.breadcrumbs ?? {};\n return attr.value\n .filter(v => v != null && v !== '')\n .map(v => {\n const id = String(v);\n return { id, label: breadcrumbs[id] || id };\n });\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { ProgramUnit } from '@mintplayer/ng-spark/models';\n\n/**\n * Maps a program unit to the router commands that open it. Type comparisons are exact: the\n * server's loader canonicalizes `type` casing, so tolerating variants here would only mask a\n * server that stopped doing so.\n *\n * Returns null for a `url` unit — an external address is an `<a href>`, not a router link; the\n * component rendering the menu owns that branch.\n */\n@Pipe({ name: 'routerLink', standalone: true, pure: true })\nexport class RouterLinkPipe implements PipeTransform {\n transform(unit: ProgramUnit): string[] | null {\n if (unit.type === 'query') {\n return ['/query', unit.alias || unit.queryId!];\n } else if (unit.type === 'persistentObject') {\n const type = unit.alias || unit.persistentObjectId!;\n return unit.objectId ? ['/po', type, unit.objectId] : ['/po', type];\n } else if (unit.type === 'url') {\n return null;\n }\n return ['/'];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'asDetailType', standalone: true, pure: true })\nexport class AsDetailTypePipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, asDetailTypes: Record<string, EntityType>): EntityType | null {\n return asDetailTypes[attr.name] || null;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'asDetailColumns', standalone: true, pure: true })\nexport class AsDetailColumnsPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, asDetailTypes: Record<string, EntityType>): EntityAttributeDefinition[] {\n const type = asDetailTypes[attr.name];\n if (!type) return [];\n return type.attributes\n .filter(a => a.isVisible)\n .sort((a, b) => a.order - b.order);\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { AS_DETAIL_BREADCRUMBS_KEY, EntityAttributeDefinition, PersistentObject, QueryResultItem, selfBreadcrumb } from '@mintplayer/ng-spark/models';\n\n/** What a cell can resolve to: the column's own type, or `null` when it has no value. */\nexport type AsDetailCellValue = string | number | boolean | Date | null;\n\n/**\n * The value of one cell in an `AsDetail` table, **typed by the column's `dataType`** rather than\n * flattened to a string.\n *\n * <p>\n * This used to end in `return String(value)` for everything, and declare `: string`. That is fine\n * for a cell which is only interpolated, and wrong for one whose consumer inspects it —\n * `spark-grid-cell` branches on the column type and binds `[checked]=\"display() === true\"` and\n * `[indeterminate]=\"display() == null\"` for a boolean, so it needs the value and not a rendering\n * of it.\n * </p>\n * <p>\n * The visible symptom was a detail page showing unticked checkboxes for rows whose edit form showed\n * them ticked — the edit form reads `attribute.objects` directly, so it never went through here. All\n * three states of a `bool?` were affected, and one of them silently:\n * </p>\n * <ul>\n * <li><b>true</b> — `'true' === true` is false, so it rendered <b>unchecked</b>;</li>\n * <li><b>null</b> — became `''`, and `'' == null` is false, so it rendered unchecked <b>and\n * determinate</b>, i.e. claiming to be false;</li>\n * <li><b>false</b> — `'false'` is not `=== true`, so it rendered correctly <b>by accident</b>.</li>\n * </ul>\n * <p>\n * Types that stay strings do so deliberately, not by omission. `color`, `image` and `url` are bound\n * into a style, an `src` and an `href`, so a string is what they need. `Reference` and `AsDetail`\n * resolve to a breadcrumb, which is a label rather than a value.\n * </p>\n * <p>\n * `date` and `datetime` return a real `Date`. They arrive as ISO strings, and the cell used to\n * print that string verbatim — `2026-09-07T13:25:57.3119825Z` in a table column. Returning the\n * parsed value lets `spark-grid-cell` format it in one place for both grids; an unparseable value\n * falls back to its text, because showing what is there beats showing `Invalid Date`.\n * </p>\n */\n@Pipe({ name: 'asDetailCellValue', standalone: true, pure: true })\nexport class AsDetailCellValuePipe implements PipeTransform {\n transform(\n row: Record<string, any>,\n parentAttr: EntityAttributeDefinition,\n col: EntityAttributeDefinition,\n asDetailRefOptions: Record<string, Record<string, QueryResultItem[]>>,\n ): AsDetailCellValue {\n const value = row[col.name];\n\n // Before the null short-circuit, because for these types \"absent\" is a value the consumer has\n // to be able to see: `null` is what makes a checkbox indeterminate rather than false, and it is\n // what distinguishes \"no number\" from the number zero. `''` erases both.\n switch (col.dataType) {\n case 'boolean':\n return typeof value === 'boolean' ? value : null;\n\n case 'number':\n case 'decimal': {\n if (value == null || value === '') return null;\n const asNumber = typeof value === 'number' ? value : Number(value);\n // A value that is not a number is passed through as text rather than reported as NaN: the\n // cell's job is to show what is there, and \"NaN\" tells the reader nothing about it.\n return Number.isNaN(asNumber) ? String(value) : asNumber;\n }\n\n case 'date':\n case 'datetime': {\n if (value == null || value === '') return null;\n if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value;\n const parsed = new Date(value as string);\n // Same rule as the number branch: an unparseable date shows its own text rather than\n // \"Invalid Date\", which would hide the value that is actually stored.\n return Number.isNaN(parsed.getTime()) ? String(value) : parsed;\n }\n }\n\n if (value == null) return '';\n\n if (col.dataType === 'Reference' && col.query) {\n // Prefer the breadcrumb the server already resolved by id — it is page-independent, so it\n // renders the label even when the referenced document falls outside the reference query's\n // first options page (issue #185).\n const serverBreadcrumb = (row[AS_DETAIL_BREADCRUMBS_KEY] as Record<string, string> | undefined)?.[col.name];\n if (serverBreadcrumb) return serverBreadcrumb;\n\n // Fallback: resolve against the loaded options page (legacy path).\n const parentOptions = asDetailRefOptions[parentAttr.name];\n if (parentOptions) {\n const options = parentOptions[col.name];\n if (options) {\n const match = options.find(o => o.id === value);\n if (match) return match.breadcrumb || String(value);\n }\n }\n }\n\n // A nested-AsDetail column's value is an inner dict, so String(value) produced \"[object\n // Object]\". The flattener kept that object's server-resolved breadcrumb for exactly this.\n if (col.dataType === 'AsDetail' && typeof value === 'object') {\n return selfBreadcrumb(value as Record<string, any>, col.asDetailType) ?? '';\n }\n\n return String(value);\n }\n}\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { EntityAttributeDefinition, EntityType, selfBreadcrumb } from '@mintplayer/ng-spark/models';\nimport { SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport { applyFieldTemplate } from './apply-field-template';\n\n@Pipe({ name: 'asDetailDisplayValue', standalone: true, pure: true })\nexport class AsDetailDisplayValuePipe implements PipeTransform {\n private readonly lang = inject(SparkLanguageService);\n\n transform(attr: EntityAttributeDefinition, formData: Record<string, any>, asDetailTypes: Record<string, EntityType>): string {\n const value = formData[attr.name];\n if (!value) return this.lang.t('notSet');\n\n const asDetailType = asDetailTypes[attr.name] || null;\n\n // The server's own resolution wins, because it can render templates this side cannot: a\n // breadcrumb may name a property that `[IgnoreProperty]` deliberately keeps out of the model\n // (HR's `Address.Crumb`), and no amount of client-side substitution will ever find it. Passing\n // the type name filters out the mapper's \"template rendered blank\" placeholder, which is the\n // bare type name rather than an empty string — see `selfBreadcrumb`.\n const resolved = selfBreadcrumb(value, asDetailType?.name);\n if (resolved) return resolved;\n\n // Still correct for a template naming real, projected attributes (`\"{Street}, {City}\"`), which\n // is the common case and the only one reachable on the create path, where there is no server\n // object to have resolved anything yet.\n if (asDetailType?.breadcrumb) {\n const result = applyFieldTemplate(asDetailType.breadcrumb, value);\n if (result && result.trim()) return result;\n }\n\n return this.lang.t('clickToEdit');\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityPermissions } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'canCreateDetailRow', standalone: true, pure: true })\nexport class CanCreateDetailRowPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, permissions: Record<string, EntityPermissions>): boolean {\n const perms = permissions[attr.name];\n return perms ? perms.canCreate : true;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, EntityPermissions } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'canDeleteDetailRow', standalone: true, pure: true })\nexport class CanDeleteDetailRowPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, permissions: Record<string, EntityPermissions>): boolean {\n const perms = permissions[attr.name];\n return perms ? perms.canDelete : true;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { ELookupDisplayType, EntityAttributeDefinition, LookupReference } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'lookupDisplayType', standalone: true, pure: true })\nexport class LookupDisplayTypePipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, lookupRefOptions: Record<string, LookupReference>): ELookupDisplayType {\n const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;\n return lookupRef?.displayType ?? ELookupDisplayType.Dropdown;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, LookupReference, resolveTranslation } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'lookupDisplayValue', standalone: true, pure: true })\nexport class LookupDisplayValuePipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, formData: Record<string, any>, lookupRefOptions: Record<string, LookupReference>): string {\n const currentValue = formData[attr.name];\n if (currentValue == null || currentValue === '') return '';\n\n const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;\n const options = lookupRef?.values.filter(v => v.isActive) || [];\n const selected = options.find(o => o.key === String(currentValue));\n if (!selected) return String(currentValue);\n\n return resolveTranslation(selected.values) || selected.key;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, LookupReference, LookupReferenceValue } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'lookupOptions', standalone: true, pure: true })\nexport class LookupOptionsPipe implements PipeTransform {\n transform(attr: EntityAttributeDefinition, lookupRefOptions: Record<string, LookupReference>): LookupReferenceValue[] {\n const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;\n return lookupRef?.values.filter(v => v.isActive) || [];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { EntityAttributeDefinition, PersistentObject, QueryResultItem } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'inlineRefOptions', standalone: true, pure: true })\nexport class InlineRefOptionsPipe implements PipeTransform {\n transform(parentAttr: EntityAttributeDefinition, col: EntityAttributeDefinition, asDetailRefOptions: Record<string, Record<string, QueryResultItem[]>>): QueryResultItem[] {\n return asDetailRefOptions[parentAttr.name]?.[col.name] || [];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { ValidationError, resolveTranslation } from '@mintplayer/ng-spark/models';\n\n@Pipe({ name: 'errorForAttribute', standalone: true, pure: true })\nexport class ErrorForAttributePipe implements PipeTransform {\n transform(attrName: string, validationErrors: ValidationError[]): string | null {\n const error = validationErrors.find(e => e.attributeName === attrName);\n return error ? resolveTranslation(error.errorMessage) : null;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({ name: 'iconName', standalone: true, pure: true })\nexport class IconNamePipe implements PipeTransform {\n transform(value: string | undefined, fallback: string): string {\n const iconClass = value || fallback;\n // Strip 'bi-' prefix if present\n return iconClass.startsWith('bi-') ? iconClass.substring(3) : iconClass;\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport { PersistentObject, nestedPoToDisplayRow } from '@mintplayer/ng-spark/models';\n\n/**\n * Resolves an attribute to a list of flat row dicts for the detail-page table.\n * AsDetail array attributes carry their data as nested PersistentObjects in\n * <c>attr.objects</c>, not <c>attr.value</c> — the server stopped putting flat\n * dicts in <c>value</c> when AsDetail moved to its dedicated wire shape. Without\n * this branch, the detail page rendered AsDetail arrays as empty tables even\n * when the edit page (which reads <c>attr.objects</c> directly) showed rows.\n */\n@Pipe({ name: 'arrayValue', standalone: true, pure: true })\nexport class ArrayValuePipe implements PipeTransform {\n transform(attrName: string, item: PersistentObject | null): Record<string, any>[] {\n const attr = item?.attributes.find(a => a.name === attrName);\n if (!attr) return [];\n if (attr.dataType === 'AsDetail' && attr.isArray && Array.isArray(attr.objects)) {\n return attr.objects.map(po => nestedPoToDisplayRow(po));\n }\n if (Array.isArray(attr.value)) return attr.value;\n return [];\n }\n}\n","import { Pipe, PipeTransform } from '@angular/core';\nimport {\n LookupReference,\n QueryColumn,\n QueryResultItem,\n resolveTranslation,\n valueFor,\n} from '@mintplayer/ng-spark/models';\nimport { ReferenceChip } from './reference-chips.pipe';\n\n/**\n * The display text of one query-grid cell.\n *\n * The attribute-shaped sibling of this ({@link AttributeValuePipe}) still serves detail and edit\n * pages, which do work in attributes. They are deliberately not one pipe: a query row is a flat\n * projection with no nested objects and no per-row metadata, so the fallbacks that make sense\n * there — reaching into `attr.object`, recomputing a breadcrumb template client-side — are not\n * merely unnecessary here, they are unreachable. Sharing the code would mean carrying branches\n * that can never fire and inviting the next reader to feed one shape into the other.\n */\n@Pipe({ name: 'queryCellValue', standalone: true, pure: true })\nexport class QueryCellValuePipe implements PipeTransform {\n transform(\n column: QueryColumn,\n item: QueryResultItem | null,\n lookupRefOptions: Record<string, LookupReference>,\n ): any {\n const cell = valueFor(item, column.name);\n if (!cell) return '';\n\n // A resolved reference display wins: the server can resolve breadcrumb templates this side\n // cannot (a template may name a computed property `[IgnoreProperty]` keeps out of the model).\n if (cell.breadcrumb) return cell.breadcrumb;\n\n if (column.dataType === 'AsDetail') {\n // An array cell carries a child COUNT rather than the children, so the wording — and its\n // pluralisation — is decided here, where the language is. A single-child cell carries the\n // child object (for a renderer to read) and is displayed by the server-resolved breadcrumb\n // above, never by stringifying it here.\n if (!column.isArray) return '';\n const count = typeof cell.value === 'number' ? cell.value : 0;\n return count === 0 ? '' : `${count} item${count !== 1 ? 's' : ''}`;\n }\n\n if (column.lookupReferenceType && cell.value != null && cell.value !== '') {\n const lookupRef = lookupRefOptions[column.lookupReferenceType];\n const option = lookupRef?.values.find(v => v.key === String(cell.value));\n if (option) return resolveTranslation(option.values) || option.key;\n }\n\n // Null rather than '' so the cell can tell \"false\" from \"unset\" and render an indeterminate\n // checkbox instead of an unchecked one.\n if (column.dataType === 'boolean') return cell.value ?? null;\n\n // Dates are parsed here for the same reason booleans are passed through above: the cell needs\n // the value, not a rendering of it. Both grids feed `spark-grid-cell`, so both have to agree on\n // the type or the same `datetime` column formats one way in a query grid and another in an\n // AsDetail table. Unparseable input keeps its own text rather than becoming \"Invalid Date\".\n if (column.dataType === 'date' || column.dataType === 'datetime') {\n if (cell.value == null || cell.value === '') return null;\n if (cell.value instanceof Date) return Number.isNaN(cell.value.getTime()) ? null : cell.value;\n const parsed = new Date(cell.value as string);\n return Number.isNaN(parsed.getTime()) ? String(cell.value) : parsed;\n }\n\n return cell.value ?? '';\n }\n}\n\n/**\n * Resolves a multi-reference column (`dataType === 'Reference'`, `isArray === true`) to chips.\n *\n * The cell's `value` carries the id array and `breadcrumbs` the server-resolved id → label map,\n * falling back to the id itself when a label is missing — the same display rule as a single\n * reference, applied per id.\n */\n@Pipe({ name: 'queryReferenceChips', standalone: true, pure: true })\nexport class QueryReferenceChipsPipe implements PipeTransform {\n transform(column: QueryColumn, item: QueryResultItem | null): ReferenceChip[] {\n const cell = valueFor(item, column.name);\n if (!cell || !Array.isArray(cell.value)) return [];\n\n const breadcrumbs = cell.breadcrumbs ?? {};\n return cell.value\n .filter(v => v != null && v !== '')\n .map(v => {\n const id = String(v);\n return { id, label: breadcrumbs[id] || id };\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -547,6 +547,16 @@ declare class SparkGridCellComponent {
|
|
|
547
547
|
protected readonly rendererInputs: _angular_core.Signal<Record<string, any>>;
|
|
548
548
|
/** Null and undefined are distinct from `false` here — see the template. */
|
|
549
549
|
protected readonly isUnsetBoolean: _angular_core.Signal<boolean>;
|
|
550
|
+
/**
|
|
551
|
+
* {@link display} when it really is a `Date`, and `null` otherwise.
|
|
552
|
+
*
|
|
553
|
+
* Angular's `DatePipe` does not degrade on a non-date: it **throws**
|
|
554
|
+
* `NG02100: InvalidPipeArgument`, which would take down the whole cell. Both cell pipes
|
|
555
|
+
* deliberately fall back to the raw text for an unparseable date rather than hiding the stored
|
|
556
|
+
* value, so that text reaches this component and must not be piped. A template cannot express
|
|
557
|
+
* `instanceof`, hence the computed.
|
|
558
|
+
*/
|
|
559
|
+
protected readonly dateValue: _angular_core.Signal<Date | null>;
|
|
550
560
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkGridCellComponent, never>;
|
|
551
561
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkGridCellComponent, "spark-grid-cell", never, { "column": { "alias": "column"; "required": true; "isSignal": true; }; "display": { "alias": "display"; "required": false; "isSignal": true; }; "rendererValue": { "alias": "rendererValue"; "required": false; "isSignal": true; }; "item": { "alias": "item"; "required": false; "isSignal": true; }; "chips": { "alias": "chips"; "required": false; "isSignal": true; }; "link": { "alias": "link"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
552
562
|
}
|
|
@@ -96,8 +96,44 @@ declare class AsDetailColumnsPipe implements PipeTransform {
|
|
|
96
96
|
static ɵpipe: i0.ɵɵPipeDeclaration<AsDetailColumnsPipe, "asDetailColumns", true>;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/** What a cell can resolve to: the column's own type, or `null` when it has no value. */
|
|
100
|
+
type AsDetailCellValue = string | number | boolean | Date | null;
|
|
101
|
+
/**
|
|
102
|
+
* The value of one cell in an `AsDetail` table, **typed by the column's `dataType`** rather than
|
|
103
|
+
* flattened to a string.
|
|
104
|
+
*
|
|
105
|
+
* <p>
|
|
106
|
+
* This used to end in `return String(value)` for everything, and declare `: string`. That is fine
|
|
107
|
+
* for a cell which is only interpolated, and wrong for one whose consumer inspects it —
|
|
108
|
+
* `spark-grid-cell` branches on the column type and binds `[checked]="display() === true"` and
|
|
109
|
+
* `[indeterminate]="display() == null"` for a boolean, so it needs the value and not a rendering
|
|
110
|
+
* of it.
|
|
111
|
+
* </p>
|
|
112
|
+
* <p>
|
|
113
|
+
* The visible symptom was a detail page showing unticked checkboxes for rows whose edit form showed
|
|
114
|
+
* them ticked — the edit form reads `attribute.objects` directly, so it never went through here. All
|
|
115
|
+
* three states of a `bool?` were affected, and one of them silently:
|
|
116
|
+
* </p>
|
|
117
|
+
* <ul>
|
|
118
|
+
* <li><b>true</b> — `'true' === true` is false, so it rendered <b>unchecked</b>;</li>
|
|
119
|
+
* <li><b>null</b> — became `''`, and `'' == null` is false, so it rendered unchecked <b>and
|
|
120
|
+
* determinate</b>, i.e. claiming to be false;</li>
|
|
121
|
+
* <li><b>false</b> — `'false'` is not `=== true`, so it rendered correctly <b>by accident</b>.</li>
|
|
122
|
+
* </ul>
|
|
123
|
+
* <p>
|
|
124
|
+
* Types that stay strings do so deliberately, not by omission. `color`, `image` and `url` are bound
|
|
125
|
+
* into a style, an `src` and an `href`, so a string is what they need. `Reference` and `AsDetail`
|
|
126
|
+
* resolve to a breadcrumb, which is a label rather than a value.
|
|
127
|
+
* </p>
|
|
128
|
+
* <p>
|
|
129
|
+
* `date` and `datetime` return a real `Date`. They arrive as ISO strings, and the cell used to
|
|
130
|
+
* print that string verbatim — `2026-09-07T13:25:57.3119825Z` in a table column. Returning the
|
|
131
|
+
* parsed value lets `spark-grid-cell` format it in one place for both grids; an unparseable value
|
|
132
|
+
* falls back to its text, because showing what is there beats showing `Invalid Date`.
|
|
133
|
+
* </p>
|
|
134
|
+
*/
|
|
99
135
|
declare class AsDetailCellValuePipe implements PipeTransform {
|
|
100
|
-
transform(row: Record<string, any>, parentAttr: EntityAttributeDefinition, col: EntityAttributeDefinition, asDetailRefOptions: Record<string, Record<string, QueryResultItem[]>>):
|
|
136
|
+
transform(row: Record<string, any>, parentAttr: EntityAttributeDefinition, col: EntityAttributeDefinition, asDetailRefOptions: Record<string, Record<string, QueryResultItem[]>>): AsDetailCellValue;
|
|
101
137
|
static ɵfac: i0.ɵɵFactoryDeclaration<AsDetailCellValuePipe, never>;
|
|
102
138
|
static ɵpipe: i0.ɵɵPipeDeclaration<AsDetailCellValuePipe, "asDetailCellValue", true>;
|
|
103
139
|
}
|
|
@@ -200,4 +236,4 @@ declare class QueryReferenceChipsPipe implements PipeTransform {
|
|
|
200
236
|
}
|
|
201
237
|
|
|
202
238
|
export { ArrayValuePipe, AsDetailCellValuePipe, AsDetailColumnsPipe, AsDetailDisplayValuePipe, AsDetailTypePipe, AttributeValuePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, ErrorForAttributePipe, IconNamePipe, InlineRefOptionsPipe, InputTypePipe, LookupDisplayTypePipe, LookupDisplayValuePipe, LookupOptionsPipe, QueryCellValuePipe, QueryReferenceChipsPipe, RawAttributeValuePipe, ReferenceAttrValuePipe, ReferenceChipsPipe, ReferenceDisplayValuePipe, ReferenceLinkRoutePipe, ResolveTranslationPipe, RouterLinkPipe, TranslateKeyPipe };
|
|
203
|
-
export type { ReferenceChip };
|
|
239
|
+
export type { AsDetailCellValue, ReferenceChip };
|