@mintplayer/ng-spark 22.32.0 → 22.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -1
- package/fesm2022/mintplayer-ng-spark-attribute-description.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-account.mjs +18 -18
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs +16 -8
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-core.mjs +6 -6
- package/fesm2022/mintplayer-ng-spark-auth-external-login.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-login.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-register.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +24 -24
- package/fesm2022/mintplayer-ng-spark-column-filter.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-contributions.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-dashboards.mjs +726 -0
- package/fesm2022/mintplayer-ng-spark-dashboards.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-grid.mjs +220 -49
- package/fesm2022/mintplayer-ng-spark-grid.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-history.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-icon.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs +6 -6
- package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-models.mjs +44 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-moderation.mjs +21 -21
- package/fesm2022/mintplayer-ng-spark-notifications.mjs +687 -0
- package/fesm2022/mintplayer-ng-spark-notifications.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-organizations-accept.mjs +179 -0
- package/fesm2022/mintplayer-ng-spark-organizations-accept.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-organizations.mjs +202 -0
- package/fesm2022/mintplayer-ng-spark-organizations.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-panels.mjs +9 -1
- package/fesm2022/mintplayer-ng-spark-panels.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +125 -85
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +95 -29
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +84 -12
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +9 -9
- package/fesm2022/mintplayer-ng-spark-pwa.mjs +74 -6
- package/fesm2022/mintplayer-ng-spark-pwa.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +10 -109
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-renderers.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +3 -3
- package/fesm2022/mintplayer-ng-spark-score-renderers.mjs +801 -0
- package/fesm2022/mintplayer-ng-spark-score-renderers.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-services.mjs +424 -72
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-share-page.mjs +334 -0
- package/fesm2022/mintplayer-ng-spark-share-page.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-share.mjs +10 -0
- package/fesm2022/mintplayer-ng-spark-share.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-shell.mjs +38 -36
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-soft-delete.mjs +9 -9
- package/package.json +29 -1
- package/types/mintplayer-ng-spark-dashboards.d.ts +226 -0
- package/types/mintplayer-ng-spark-grid.d.ts +77 -26
- package/types/mintplayer-ng-spark-models.d.ts +150 -17
- package/types/mintplayer-ng-spark-notifications.d.ts +188 -0
- package/types/mintplayer-ng-spark-organizations-accept.d.ts +40 -0
- package/types/mintplayer-ng-spark-organizations.d.ts +72 -0
- package/types/mintplayer-ng-spark-panels.d.ts +16 -0
- package/types/mintplayer-ng-spark-pipes.d.ts +10 -0
- package/types/mintplayer-ng-spark-po-detail.d.ts +29 -0
- package/types/mintplayer-ng-spark-po-edit.d.ts +37 -0
- package/types/mintplayer-ng-spark-pwa.d.ts +48 -2
- package/types/mintplayer-ng-spark-query-list.d.ts +8 -23
- package/types/mintplayer-ng-spark-score-renderers.d.ts +340 -0
- package/types/mintplayer-ng-spark-services.d.ts +146 -6
- package/types/mintplayer-ng-spark-share-page.d.ts +67 -0
- package/types/mintplayer-ng-spark-share.d.ts +26 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mintplayer/ng-spark",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "22.
|
|
4
|
+
"version": "22.34.0",
|
|
5
5
|
"description": "Angular component library for MintPlayer.Spark CRUD applications",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -120,6 +120,10 @@
|
|
|
120
120
|
"types": "./types/mintplayer-ng-spark-contributions.d.ts",
|
|
121
121
|
"default": "./fesm2022/mintplayer-ng-spark-contributions.mjs"
|
|
122
122
|
},
|
|
123
|
+
"./dashboards": {
|
|
124
|
+
"types": "./types/mintplayer-ng-spark-dashboards.d.ts",
|
|
125
|
+
"default": "./fesm2022/mintplayer-ng-spark-dashboards.mjs"
|
|
126
|
+
},
|
|
123
127
|
"./grid": {
|
|
124
128
|
"types": "./types/mintplayer-ng-spark-grid.d.ts",
|
|
125
129
|
"default": "./fesm2022/mintplayer-ng-spark-grid.mjs"
|
|
@@ -160,6 +164,18 @@
|
|
|
160
164
|
"types": "./types/mintplayer-ng-spark-moderation.d.ts",
|
|
161
165
|
"default": "./fesm2022/mintplayer-ng-spark-moderation.mjs"
|
|
162
166
|
},
|
|
167
|
+
"./notifications": {
|
|
168
|
+
"types": "./types/mintplayer-ng-spark-notifications.d.ts",
|
|
169
|
+
"default": "./fesm2022/mintplayer-ng-spark-notifications.mjs"
|
|
170
|
+
},
|
|
171
|
+
"./organizations": {
|
|
172
|
+
"types": "./types/mintplayer-ng-spark-organizations.d.ts",
|
|
173
|
+
"default": "./fesm2022/mintplayer-ng-spark-organizations.mjs"
|
|
174
|
+
},
|
|
175
|
+
"./organizations/accept": {
|
|
176
|
+
"types": "./types/mintplayer-ng-spark-organizations-accept.d.ts",
|
|
177
|
+
"default": "./fesm2022/mintplayer-ng-spark-organizations-accept.mjs"
|
|
178
|
+
},
|
|
163
179
|
"./panels": {
|
|
164
180
|
"types": "./types/mintplayer-ng-spark-panels.d.ts",
|
|
165
181
|
"default": "./fesm2022/mintplayer-ng-spark-panels.mjs"
|
|
@@ -204,10 +220,22 @@
|
|
|
204
220
|
"types": "./types/mintplayer-ng-spark-routes.d.ts",
|
|
205
221
|
"default": "./fesm2022/mintplayer-ng-spark-routes.mjs"
|
|
206
222
|
},
|
|
223
|
+
"./score-renderers": {
|
|
224
|
+
"types": "./types/mintplayer-ng-spark-score-renderers.d.ts",
|
|
225
|
+
"default": "./fesm2022/mintplayer-ng-spark-score-renderers.mjs"
|
|
226
|
+
},
|
|
207
227
|
"./services": {
|
|
208
228
|
"types": "./types/mintplayer-ng-spark-services.d.ts",
|
|
209
229
|
"default": "./fesm2022/mintplayer-ng-spark-services.mjs"
|
|
210
230
|
},
|
|
231
|
+
"./share": {
|
|
232
|
+
"types": "./types/mintplayer-ng-spark-share.d.ts",
|
|
233
|
+
"default": "./fesm2022/mintplayer-ng-spark-share.mjs"
|
|
234
|
+
},
|
|
235
|
+
"./share/page": {
|
|
236
|
+
"types": "./types/mintplayer-ng-spark-share-page.d.ts",
|
|
237
|
+
"default": "./fesm2022/mintplayer-ng-spark-share-page.mjs"
|
|
238
|
+
},
|
|
211
239
|
"./shell": {
|
|
212
240
|
"types": "./types/mintplayer-ng-spark-shell.d.ts",
|
|
213
241
|
"default": "./fesm2022/mintplayer-ng-spark-shell.mjs"
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { SparkAttributeColumnRenderer, SparkAttributeDetailRenderer, SparkAttributeRendererRegistration } from "@mintplayer/ng-spark/renderers";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
import { Provider, Type } from "@angular/core";
|
|
4
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
5
|
+
import { SparkLanguageService } from "@mintplayer/ng-spark/services";
|
|
6
|
+
import { EntityAttributeDefinition, PersistentObject, TranslatedString } from "@mintplayer/ng-spark/models";
|
|
7
|
+
import { SparkDetailContext } from "@mintplayer/ng-spark/panels";
|
|
8
|
+
/** How a dashboard value is written: a plain number, bytes (binary units), a percentage, a date, or as is. */
|
|
9
|
+
export type SparkDashboardFormat = 'number' | 'bytes' | 'percent' | 'date' | 'datetime' | 'text';
|
|
10
|
+
/** A finite number from a wire value (a number or a numeric string), else null. */
|
|
11
|
+
export declare function toSparkNumber(value: unknown): number | null;
|
|
12
|
+
/** 1536 → "1.5 KB": binary units, one decimal from KB up; "—" for no value. */
|
|
13
|
+
export declare function formatSparkBytes(bytes: number | null | undefined, locale?: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* A value as a dashboard writes it: "—" for none; numbers by `format` (`decimals` places for `number`/`percent`,
|
|
16
|
+
* default 0); dates in the viewer's locale; anything else as text.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatSparkDashboardValue(value: unknown, format: SparkDashboardFormat | undefined, locale?: string, decimals?: number): string;
|
|
19
|
+
/** The colour a threshold gives a value: `danger` at or past `danger`, `warning` at or past `warning`, else none. */
|
|
20
|
+
export declare function sparkThresholdColor(value: number | null, thresholds: {
|
|
21
|
+
warning?: number;
|
|
22
|
+
danger?: number;
|
|
23
|
+
direction?: 'above' | 'below';
|
|
24
|
+
}): 'warning' | 'danger' | null;
|
|
25
|
+
/** `rendererOptions` of the `spark-stat` renderer. Every member is optional. */
|
|
26
|
+
export interface SparkStatOptions {
|
|
27
|
+
/** How the value is written. Default `'number'`. */
|
|
28
|
+
format?: SparkDashboardFormat;
|
|
29
|
+
/** Decimals for `number` (default 0) and `percent` (default 1). */
|
|
30
|
+
decimals?: number;
|
|
31
|
+
/** Text after the value, e.g. `' sites'`. Default none. */
|
|
32
|
+
suffix?: string;
|
|
33
|
+
/** The value turns amber at or past this. */
|
|
34
|
+
warning?: number;
|
|
35
|
+
/** The value turns red at or past this. */
|
|
36
|
+
danger?: number;
|
|
37
|
+
/** `'above'` (default): high is bad, as for disk use. `'below'`: low is bad, as for free space. */
|
|
38
|
+
direction?: 'above' | 'below';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The `spark-stat` renderer: one figure, large on a detail page (a dashboard tile) and plain in a grid cell,
|
|
42
|
+
* coloured amber or red once it passes the model's `warning` / `danger` threshold. No value draws a muted dash.
|
|
43
|
+
*/
|
|
44
|
+
export declare class SparkStatComponent implements SparkAttributeColumnRenderer, SparkAttributeDetailRenderer {
|
|
45
|
+
private readonly locale;
|
|
46
|
+
readonly value: import("@angular/core").InputSignal<any>;
|
|
47
|
+
readonly options: import("@angular/core").InputSignal<Record<string, any> | undefined>;
|
|
48
|
+
private readonly settings;
|
|
49
|
+
protected readonly text: import("@angular/core").Signal<string>;
|
|
50
|
+
protected readonly color: import("@angular/core").Signal<"warning" | "danger" | null>;
|
|
51
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkStatComponent, never>;
|
|
52
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkStatComponent, "spark-stat", never, {
|
|
53
|
+
"value": {
|
|
54
|
+
"alias": "value";
|
|
55
|
+
"required": false;
|
|
56
|
+
"isSignal": true;
|
|
57
|
+
};
|
|
58
|
+
"options": {
|
|
59
|
+
"alias": "options";
|
|
60
|
+
"required": false;
|
|
61
|
+
"isSignal": true;
|
|
62
|
+
};
|
|
63
|
+
}, {}, never, never, true, never>;
|
|
64
|
+
}
|
|
65
|
+
/** `rendererOptions` of the `spark-meter` renderer. Every member is optional. */
|
|
66
|
+
export interface SparkMeterOptions {
|
|
67
|
+
/** The ceiling when the value is a plain number (a value `{ value, max }` brings its own). Default 100. */
|
|
68
|
+
max?: number;
|
|
69
|
+
/** How the value and the ceiling are written. Default `'number'`. */
|
|
70
|
+
format?: SparkDashboardFormat;
|
|
71
|
+
/** Amber from this share of the ceiling, in percent. Default 75. */
|
|
72
|
+
warning?: number;
|
|
73
|
+
/** Red from this share of the ceiling, in percent. Default 90. */
|
|
74
|
+
danger?: number;
|
|
75
|
+
/** The meter's accessible name. Default `'Usage'`. */
|
|
76
|
+
label?: string;
|
|
77
|
+
}
|
|
78
|
+
interface MeterView {
|
|
79
|
+
value: number;
|
|
80
|
+
max: number;
|
|
81
|
+
/** The share of the ceiling, in percent (0–100), one decimal. */
|
|
82
|
+
share: number;
|
|
83
|
+
color: Color;
|
|
84
|
+
text: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The `spark-meter` renderer: how much of something is used, as a bar coloured by its share (green, amber from 75 %,
|
|
88
|
+
* red from 90 % by default) with "used of total (share)" next to it. The value is a number against the `max` option, or
|
|
89
|
+
* `{ value, max }` from the server (the dashboards package's `DashboardValues.Meter`), e.g. disk bytes used of the total.
|
|
90
|
+
* No value, or no ceiling, draws a muted dash.
|
|
91
|
+
*/
|
|
92
|
+
export declare class SparkMeterComponent implements SparkAttributeColumnRenderer, SparkAttributeDetailRenderer {
|
|
93
|
+
private readonly locale;
|
|
94
|
+
readonly value: import("@angular/core").InputSignal<any>;
|
|
95
|
+
readonly options: import("@angular/core").InputSignal<Record<string, any> | undefined>;
|
|
96
|
+
private readonly settings;
|
|
97
|
+
protected readonly label: import("@angular/core").Signal<string>;
|
|
98
|
+
protected readonly view: import("@angular/core").Signal<MeterView | null>;
|
|
99
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkMeterComponent, never>;
|
|
100
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkMeterComponent, "spark-meter", never, {
|
|
101
|
+
"value": {
|
|
102
|
+
"alias": "value";
|
|
103
|
+
"required": false;
|
|
104
|
+
"isSignal": true;
|
|
105
|
+
};
|
|
106
|
+
"options": {
|
|
107
|
+
"alias": "options";
|
|
108
|
+
"required": false;
|
|
109
|
+
"isSignal": true;
|
|
110
|
+
};
|
|
111
|
+
}, {}, never, never, true, never>;
|
|
112
|
+
}
|
|
113
|
+
/** One column of a `spark-dashboard-table`. */
|
|
114
|
+
export interface SparkDashboardTableColumn {
|
|
115
|
+
/** The row field. For a value that is a dictionary, its rows are `{ key, value }`. */
|
|
116
|
+
key: string;
|
|
117
|
+
/** A translation key for the header (`translations.json`), shown as is when it has no translation. Default `key`. */
|
|
118
|
+
label?: string;
|
|
119
|
+
/** How the cells are written. Numbers and bytes are right-aligned. Default: as is. */
|
|
120
|
+
format?: SparkDashboardFormat | 'boolean';
|
|
121
|
+
/** Translate each cell as `{translate}{value}` (e.g. `'seoUi.runStatus.'`), falling back to the value. */
|
|
122
|
+
translate?: string;
|
|
123
|
+
}
|
|
124
|
+
/** `rendererOptions` of the `spark-dashboard-table` renderer. */
|
|
125
|
+
export interface SparkDashboardTableOptions {
|
|
126
|
+
/** The columns, in order. Default: the first row's fields. */
|
|
127
|
+
columns?: SparkDashboardTableColumn[];
|
|
128
|
+
/** A translation key shown when there are no rows. Default `'dashboards.empty'`. */
|
|
129
|
+
empty?: string;
|
|
130
|
+
}
|
|
131
|
+
interface TableCell {
|
|
132
|
+
text: string;
|
|
133
|
+
check: boolean;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The `spark-dashboard-table` renderer (detail pages): a dashboard value that is a list of rows, such as the
|
|
137
|
+
* RavenDB statistics' collections (D12: tables are JSON attributes). A dictionary (`{ "Completed": 3 }`) reads as
|
|
138
|
+
* rows `{ key, value }`.
|
|
139
|
+
*/
|
|
140
|
+
export declare class SparkDashboardTableComponent implements SparkAttributeDetailRenderer {
|
|
141
|
+
private readonly locale;
|
|
142
|
+
protected readonly lang: SparkLanguageService;
|
|
143
|
+
readonly value: import("@angular/core").InputSignal<any>;
|
|
144
|
+
readonly options: import("@angular/core").InputSignal<Record<string, any> | undefined>;
|
|
145
|
+
protected readonly settings: import("@angular/core").Signal<SparkDashboardTableOptions>;
|
|
146
|
+
protected readonly rows: import("@angular/core").Signal<Record<string, unknown>[]>;
|
|
147
|
+
protected readonly columns: import("@angular/core").Signal<SparkDashboardTableColumn[]>;
|
|
148
|
+
protected readonly cells: import("@angular/core").Signal<TableCell[][]>;
|
|
149
|
+
protected header(column: SparkDashboardTableColumn): string;
|
|
150
|
+
protected isNumeric(column: SparkDashboardTableColumn | undefined): boolean;
|
|
151
|
+
private cell;
|
|
152
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkDashboardTableComponent, never>;
|
|
153
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkDashboardTableComponent, "spark-dashboard-table", never, {
|
|
154
|
+
"value": {
|
|
155
|
+
"alias": "value";
|
|
156
|
+
"required": false;
|
|
157
|
+
"isSignal": true;
|
|
158
|
+
};
|
|
159
|
+
"options": {
|
|
160
|
+
"alias": "options";
|
|
161
|
+
"required": false;
|
|
162
|
+
"isSignal": true;
|
|
163
|
+
};
|
|
164
|
+
}, {}, never, never, true, never>;
|
|
165
|
+
}
|
|
166
|
+
/** The rows of a table value: a list of objects as is, a dictionary as `{ key, value }` rows, anything else none. */
|
|
167
|
+
export declare function toSparkTableRows(value: unknown): Record<string, unknown>[];
|
|
168
|
+
/** The `metadata` key a dashboard carries (the dashboards package's `SparkDashboardActions.MetadataKey`). */
|
|
169
|
+
export declare const SPARK_DASHBOARD_METADATA_KEY = "dashboard";
|
|
170
|
+
/** Whether `item` is a dashboard: the server marks one with `metadata.dashboard`. */
|
|
171
|
+
export declare function isSparkDashboard(item: PersistentObject | null | undefined): boolean;
|
|
172
|
+
interface DashboardTile {
|
|
173
|
+
attribute: EntityAttributeDefinition;
|
|
174
|
+
/** Columns spanned: 1, 2, or the whole row. */
|
|
175
|
+
span: 1 | 2 | 'row';
|
|
176
|
+
component: Type<any> | null;
|
|
177
|
+
inputs: Record<string, any>;
|
|
178
|
+
/** The value as text, for an attribute without a detail renderer. */
|
|
179
|
+
text: string;
|
|
180
|
+
}
|
|
181
|
+
interface DashboardSection {
|
|
182
|
+
id: string;
|
|
183
|
+
name: string | null;
|
|
184
|
+
label?: TranslatedString;
|
|
185
|
+
tiles: DashboardTile[];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The dashboard tile layout (D12): replaces a dashboard's attribute cards on the routed detail page
|
|
189
|
+
* (`SPARK_DETAIL_LAYOUTS`, registered by `provideSparkDashboards()`). Each group of the model is a section, each
|
|
190
|
+
* attribute a tile: its label above its detail renderer (`spark-stat`, `spark-meter`, `spark-trend`,
|
|
191
|
+
* `spark-dashboard-table`, …) or its plain value. `columnSpan` 2 takes two columns, 3 and more (and a table without one) the
|
|
192
|
+
* whole row. An attribute the caller may not read is not on the object and has no tile. The page follows the object
|
|
193
|
+
* over `/spark/live` like any live type, so the tiles change in place.
|
|
194
|
+
*/
|
|
195
|
+
export declare class SparkDashboardComponent {
|
|
196
|
+
private readonly locale;
|
|
197
|
+
private readonly renderers;
|
|
198
|
+
readonly context: import("@angular/core").InputSignal<SparkDetailContext>;
|
|
199
|
+
protected readonly sections: import("@angular/core").Signal<DashboardSection[]>;
|
|
200
|
+
/** When the server read the values, in the viewer's locale. */
|
|
201
|
+
protected readonly generatedAt: import("@angular/core").Signal<string | null>;
|
|
202
|
+
private tile;
|
|
203
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkDashboardComponent, never>;
|
|
204
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkDashboardComponent, "spark-dashboard", never, {
|
|
205
|
+
"context": {
|
|
206
|
+
"alias": "context";
|
|
207
|
+
"required": true;
|
|
208
|
+
"isSignal": true;
|
|
209
|
+
};
|
|
210
|
+
}, {}, never, never, true, never>;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* The dashboard renderers under their model names. Renderers are one list, so add these to the app's own in its
|
|
214
|
+
* single `provideSparkAttributeRenderers` (or `provideSparkScoreRenderers`, which `spark-trend` comes from) call:
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* provideSparkScoreRenderers([...appRenderers, ...sparkDashboardRenderers]),
|
|
218
|
+
* provideSparkDashboards(),
|
|
219
|
+
*/
|
|
220
|
+
export declare const sparkDashboardRenderers: readonly SparkAttributeRendererRegistration[];
|
|
221
|
+
/**
|
|
222
|
+
* Draws every dashboard (an object the server marks with `metadata.dashboard`, the dashboards package's live virtual
|
|
223
|
+
* types) with the tile layout instead of the attribute cards, on the routed detail page. The renderers are registered
|
|
224
|
+
* separately: see {@link sparkDashboardRenderers}.
|
|
225
|
+
*/
|
|
226
|
+
export declare function provideSparkDashboards(): Provider[];
|
|
@@ -219,23 +219,22 @@ export declare function sparkActionClass(definition: CustomActionDefinition, siz
|
|
|
219
219
|
* The one Spark grid: a `<bs-datatable>` rendering a query or a sub-query.
|
|
220
220
|
*
|
|
221
221
|
* This replaces two components that were the same grid written twice — and, counting
|
|
222
|
-
* `spark-query-list`'s streaming and paged branches, the `<bs-datatable>` element itself
|
|
223
|
-
* three times. The duplication had already produced four user-visible bugs, each fixed on
|
|
224
|
-
* side and not the other: `[indeterminate]` on null booleans, permission state surviving a failed
|
|
222
|
+
* `spark-query-list`'s former streaming and paged branches, the `<bs-datatable>` element itself
|
|
223
|
+
* written three times. The duplication had already produced four user-visible bugs, each fixed on
|
|
224
|
+
* one side and not the other: `[indeterminate]` on null booleans, permission state surviving a failed
|
|
225
225
|
* reload, a swallowed fetch failure, and virtual-scroll sizing. `SparkGridRenderers` was
|
|
226
226
|
* extracted to stop that and could only take the stateless helpers with it; this takes the rest.
|
|
227
227
|
*
|
|
228
|
-
* ##
|
|
228
|
+
* ## Where the rows come from
|
|
229
229
|
*
|
|
230
|
-
* `
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* - unbound `data` — the grid fetches for itself, paging and sorting server-side;
|
|
230
|
+
* - unbound `data` — the grid fetches for itself, paging and sorting server-side: over HTTP, or over
|
|
231
|
+
* `/spark/live` when the grid is live (see {@link live});
|
|
234
232
|
* - bound `data` — the grid renders what it is given and never fetches.
|
|
235
233
|
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
*
|
|
234
|
+
* This is the line `bs-datatable` itself draws: `[data]` and `[fetch]` are mutually exclusive, and
|
|
235
|
+
* binding both makes `[fetch]` win silently. Live rides on `[fetch]`, so server-side paging, sort,
|
|
236
|
+
* search and filters work the same live or not; every embedded grid, sub-query and card follows a live
|
|
237
|
+
* query, not only the query page.
|
|
239
238
|
*
|
|
240
239
|
* ## Reading its state
|
|
241
240
|
*
|
|
@@ -246,6 +245,7 @@ export declare function sparkActionClass(definition: CustomActionDefinition, siz
|
|
|
246
245
|
*/
|
|
247
246
|
export declare class SparkQueryGridComponent {
|
|
248
247
|
private readonly sparkService;
|
|
248
|
+
private readonly liveService;
|
|
249
249
|
private readonly gridRenderers;
|
|
250
250
|
private readonly queryRefresh;
|
|
251
251
|
private readonly injector;
|
|
@@ -282,11 +282,31 @@ export declare class SparkQueryGridComponent {
|
|
|
282
282
|
/**
|
|
283
283
|
* Rows supplied from outside. When bound, the grid renders these and runs no fetch.
|
|
284
284
|
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
285
|
+
* `null` — the default — means "fetch for yourself"; an empty array means "you have been given no
|
|
286
|
+
* rows", which is a different statement and renders an empty grid rather than triggering a load.
|
|
287
|
+
* Bound rows are never live.
|
|
288
288
|
*/
|
|
289
289
|
data: import("@angular/core").InputSignal<QueryResultItem[] | null>;
|
|
290
|
+
/**
|
|
291
|
+
* Whether this grid follows its query over `/spark/live` (X4): `undefined` — the default — follows the
|
|
292
|
+
* query's own `live` flag; `true`/`false` overrides it (`[live]="false"` on a dashboard tile).
|
|
293
|
+
*
|
|
294
|
+
* Live, the grid's current request (page, sort, search, column filters, parent, deleted modes — exactly
|
|
295
|
+
* the `/execute` body) is ONE server subscription, sent again as an `update` on every page, sort, search
|
|
296
|
+
* or filter change, and every pushed page is rendered as it arrives: rows that change, appear or leave.
|
|
297
|
+
* A subscription `error` clears the rows and shows the message; it is not retried (see {@link isLive}).
|
|
298
|
+
* A virtual-scrolling query is never live: its blocks are separate pages fetched as the user scrolls, and
|
|
299
|
+
* one subscription follows one page.
|
|
300
|
+
*/
|
|
301
|
+
live: import("@angular/core").InputSignal<boolean | undefined>;
|
|
302
|
+
/**
|
|
303
|
+
* The live subscription ended with an error for the query loaded now. Reset by a new load; a live grid
|
|
304
|
+
* does not resubscribe by itself after an error (the answer would not change).
|
|
305
|
+
*/
|
|
306
|
+
private readonly liveFailed;
|
|
307
|
+
/** Whether rows arrive over `/spark/live` right now: the query page shows its LIVE badge from this. */
|
|
308
|
+
readonly isLive: import("@angular/core").Signal<boolean>;
|
|
309
|
+
private liveWanted;
|
|
290
310
|
/**
|
|
291
311
|
* Server-side search term, passed through to the query.
|
|
292
312
|
*
|
|
@@ -539,10 +559,9 @@ export declare class SparkQueryGridComponent {
|
|
|
539
559
|
deleteRows(rows: QueryResultItem[], definition?: CustomActionDefinition): Promise<void>;
|
|
540
560
|
isVirtualScrolling: import("@angular/core").Signal<boolean>;
|
|
541
561
|
/**
|
|
542
|
-
* Columns as sent with the most recent fetched page.
|
|
562
|
+
* Columns as sent with the most recent fetched (or pushed) page.
|
|
543
563
|
*
|
|
544
|
-
* A host binding `data`
|
|
545
|
-
* snapshot carries them once, exactly as a paged result does.
|
|
564
|
+
* A host binding `data` supplies its own via the `columns` input instead.
|
|
546
565
|
*/
|
|
547
566
|
private readonly fetchedColumns;
|
|
548
567
|
/**
|
|
@@ -557,15 +576,7 @@ export declare class SparkQueryGridComponent {
|
|
|
557
576
|
* each string names comes from `bsDatatableColumnLabel` in the template. See `sparkDatatableLabels`.
|
|
558
577
|
*/
|
|
559
578
|
datatableLabels: import("@angular/core").Signal<import("@mintplayer/ng-spark/services").SparkDatatableLabels>;
|
|
560
|
-
/**
|
|
561
|
-
* True when rows do not come from this component's own fetch.
|
|
562
|
-
*
|
|
563
|
-
* Either because the host bound `data`, or because the query streams — a streaming query's rows
|
|
564
|
-
* arrive over a socket and `/execute` is not a way to get them. The grid recognises the second
|
|
565
|
-
* case itself rather than waiting to be told, because it resolves the query before the host can
|
|
566
|
-
* see it: left to `data` alone, every streaming grid would fire one pointless fetch on mount,
|
|
567
|
-
* before the host had anything to bind.
|
|
568
|
-
*/
|
|
579
|
+
/** True when rows do not come from this component's own fetch: the host bound `data`. */
|
|
569
580
|
hasExternalData: import("@angular/core").Signal<boolean>;
|
|
570
581
|
/**
|
|
571
582
|
* Whether an action can run right now: its selection rule is satisfied, and the client method it
|
|
@@ -578,6 +589,22 @@ export declare class SparkQueryGridComponent {
|
|
|
578
589
|
*/
|
|
579
590
|
actionUnavailableReason(action: CustomActionDefinition): string | null;
|
|
580
591
|
constructor();
|
|
592
|
+
/** The live subscription of the query loaded now, while the grid is live. */
|
|
593
|
+
private liveSession;
|
|
594
|
+
private disposeLive;
|
|
595
|
+
/**
|
|
596
|
+
* A pushed page: re-fetch through the datatable, which lands in the live fetch and is served from
|
|
597
|
+
* memory. Through `reload()` rather than a new `[fetch]` identity, so page, sort and scroll stay.
|
|
598
|
+
*/
|
|
599
|
+
private onLivePush;
|
|
600
|
+
/**
|
|
601
|
+
* A live subscription error (defect 4): clear the rows — a stale page must never stay up looking current
|
|
602
|
+
* — and say why. Not retried: `unavailable` (unknown, forbidden, not live, missing parent — one answer),
|
|
603
|
+
* `invalid`, `limit` and `failed` would answer the same again, and a socket-level failure (4429, a
|
|
604
|
+
* repeated 4401) is the socket's to surface. No HTTP fallback either: `unavailable` is the same answer
|
|
605
|
+
* `/execute` gives as a 404, and an app stream's rows exist only on the socket.
|
|
606
|
+
*/
|
|
607
|
+
private onLiveError;
|
|
581
608
|
/**
|
|
582
609
|
* Re-run the query, keeping the current page, sort and scroll position.
|
|
583
610
|
*
|
|
@@ -689,7 +716,26 @@ export declare class SparkQueryGridComponent {
|
|
|
689
716
|
* rendered correctly as a page. Both grids are this one now, so there is one answer.
|
|
690
717
|
*/
|
|
691
718
|
private resolveEntityType;
|
|
719
|
+
/** The datatable's `[fetch]`: over `/spark/live` when the grid is live (see {@link live}), else HTTP. */
|
|
692
720
|
private makeFetch;
|
|
721
|
+
/**
|
|
722
|
+
* The `/execute` body for one datatable request — the same for HTTP and live. Read at call time, so
|
|
723
|
+
* what forces a refetch is the fetch identity `reload()` creates, not the value captured when the
|
|
724
|
+
* closure was built.
|
|
725
|
+
*/
|
|
726
|
+
private requestFor;
|
|
727
|
+
/**
|
|
728
|
+
* One page as the datatable takes it, recording what the chrome reads off a result: count, columns,
|
|
729
|
+
* the result's withheld actions, the ids on screen.
|
|
730
|
+
*/
|
|
731
|
+
private toPage;
|
|
732
|
+
/**
|
|
733
|
+
* Live: the request goes to this grid's {@link LiveGridSession} — subscribed on the first fetch, sent as
|
|
734
|
+
* an `update` when it changes, answered from the latest push when it does not. After an error every fetch
|
|
735
|
+
* is an empty page and the error stays shown.
|
|
736
|
+
*/
|
|
737
|
+
private makeLiveFetch;
|
|
738
|
+
private makeHttpFetch;
|
|
693
739
|
private loadLookupReferenceOptions;
|
|
694
740
|
/**
|
|
695
741
|
* The underlying value a custom renderer receives, which is not the printable one.
|
|
@@ -730,6 +776,11 @@ export declare class SparkQueryGridComponent {
|
|
|
730
776
|
"required": false;
|
|
731
777
|
"isSignal": true;
|
|
732
778
|
};
|
|
779
|
+
"live": {
|
|
780
|
+
"alias": "live";
|
|
781
|
+
"required": false;
|
|
782
|
+
"isSignal": true;
|
|
783
|
+
};
|
|
733
784
|
"search": {
|
|
734
785
|
"alias": "search";
|
|
735
786
|
"required": false;
|
|
@@ -341,6 +341,12 @@ export interface EntityType {
|
|
|
341
341
|
*/
|
|
342
342
|
canRead?: boolean;
|
|
343
343
|
alias?: string;
|
|
344
|
+
/**
|
|
345
|
+
* Whether an object of this type is followed over `/spark/live` (X4): `spark-po-detail` replaces the
|
|
346
|
+
* shown object when it changes and shows the unavailable state when it is deleted, and `spark-po-edit`
|
|
347
|
+
* adopts a newer version (or offers a merge when the form is dirty). Opt-in per type.
|
|
348
|
+
*/
|
|
349
|
+
live?: boolean;
|
|
344
350
|
/**
|
|
345
351
|
* Breadcrumb template: literal text plus `{AttributeName}` placeholders. A scalar placeholder
|
|
346
352
|
* renders its value; a reference placeholder renders the referenced entity's breadcrumb.
|
|
@@ -409,8 +415,12 @@ export interface SparkQuery {
|
|
|
409
415
|
indexName?: string;
|
|
410
416
|
/** Optional entity type name (e.g., "Person"). When set, used for entity type resolution. */
|
|
411
417
|
entityType?: string;
|
|
412
|
-
/**
|
|
413
|
-
|
|
418
|
+
/**
|
|
419
|
+
* Whether grids showing this query follow it over `/spark/live` (X4): the page re-renders when a row in
|
|
420
|
+
* it changes, appears or disappears, with server-side paging, sort, search and filters intact. Opt-in
|
|
421
|
+
* per query; a grid's `[live]` input overrides it. See `docs/guide-live-updates.md`.
|
|
422
|
+
*/
|
|
423
|
+
live?: boolean;
|
|
414
424
|
/**
|
|
415
425
|
* Whether the grid offers row selection (#460, D17). Absent is `'auto'`: derived from the offered
|
|
416
426
|
* actions. A sub-query entry on the parent's type may override it.
|
|
@@ -734,30 +744,153 @@ export interface EntityPermissions {
|
|
|
734
744
|
canRevertContribution?: boolean;
|
|
735
745
|
}
|
|
736
746
|
/**
|
|
737
|
-
* The
|
|
747
|
+
* The live-updates protocol (`/spark/live`, X4), as `docs/guide-live-updates.md` "The protocol" fixes it.
|
|
738
748
|
*
|
|
739
|
-
*
|
|
740
|
-
*
|
|
749
|
+
* One WebSocket per browser tab carries every subscription; one JSON object per text frame. Subscriptions
|
|
750
|
+
* are reads only: mutations stay on HTTP.
|
|
741
751
|
*/
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
data: QueryResultItem[];
|
|
746
|
-
}
|
|
747
|
-
export interface StreamingPatchItem {
|
|
752
|
+
/** A subscription to one persistent object: exactly the body of `POST /spark/po/load`. */
|
|
753
|
+
export interface LivePoRequest {
|
|
754
|
+
objectTypeId: string;
|
|
748
755
|
id: string;
|
|
749
|
-
|
|
750
|
-
|
|
756
|
+
deleted?: SparkDeletedFilter | null;
|
|
757
|
+
}
|
|
758
|
+
/** A sort column as `/spark/queries/execute` takes it. */
|
|
759
|
+
export interface LiveSortColumn {
|
|
760
|
+
property: string;
|
|
761
|
+
direction: 'asc' | 'desc';
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* A subscription to one page of a query: exactly the body of `POST /spark/queries/execute`
|
|
765
|
+
* (`retryResults` is ignored by the server — a push cannot prompt).
|
|
766
|
+
*/
|
|
767
|
+
export interface LiveQueryRequest {
|
|
768
|
+
queryId: string;
|
|
769
|
+
skip?: number | null;
|
|
770
|
+
take?: number | null;
|
|
771
|
+
sortColumns?: LiveSortColumn[] | null;
|
|
772
|
+
search?: string | null;
|
|
773
|
+
columns?: QueryColumnFilter[] | null;
|
|
774
|
+
parentId?: string | null;
|
|
775
|
+
parentType?: string | null;
|
|
776
|
+
deleted?: SparkDeletedFilter | null;
|
|
777
|
+
parentDeleted?: SparkDeletedFilter | null;
|
|
778
|
+
}
|
|
779
|
+
export interface LiveSubscribePoOp {
|
|
780
|
+
op: 'subscribe';
|
|
781
|
+
sub: string;
|
|
782
|
+
po: LivePoRequest;
|
|
783
|
+
}
|
|
784
|
+
export interface LiveSubscribeQueryOp {
|
|
785
|
+
op: 'subscribe';
|
|
786
|
+
sub: string;
|
|
787
|
+
query: LiveQueryRequest;
|
|
788
|
+
}
|
|
789
|
+
/** The same query subscription with a new page, sort, search or filters; the server keeps the sub. */
|
|
790
|
+
export interface LiveUpdateOp {
|
|
791
|
+
op: 'update';
|
|
792
|
+
sub: string;
|
|
793
|
+
query: LiveQueryRequest;
|
|
794
|
+
}
|
|
795
|
+
export interface LiveUnsubscribeOp {
|
|
796
|
+
op: 'unsubscribe';
|
|
797
|
+
sub: string;
|
|
751
798
|
}
|
|
752
|
-
export
|
|
799
|
+
export type LiveClientOp = LiveSubscribePoOp | LiveSubscribeQueryOp | LiveUpdateOp | LiveUnsubscribeOp;
|
|
800
|
+
/** `error` codes. Every one ends its subscription; the socket stays open. */
|
|
801
|
+
export type LiveErrorCode = 'unavailable' | 'invalid' | 'limit' | 'failed';
|
|
802
|
+
/** The changes to a held persistent object: top-level fields (`null` = removed) and whole attributes, by `name`. */
|
|
803
|
+
export interface LivePoPatch {
|
|
804
|
+
set?: Record<string, unknown>;
|
|
805
|
+
attributes?: PersistentObjectAttribute[];
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* The changes to a held query page. Apply: index the held rows by `id`; drop `remove`; replace or add each
|
|
809
|
+
* `upsert`; the rows are `order` mapped through the index when present, otherwise the held order minus the
|
|
810
|
+
* removed rows; then assign `set` (`totalItems`, `skip`, `take`, `disabledActions`, `typeHints`, …).
|
|
811
|
+
*/
|
|
812
|
+
export interface LiveQueryPatch {
|
|
813
|
+
upsert?: QueryResultItem[];
|
|
814
|
+
remove?: string[];
|
|
815
|
+
order?: string[];
|
|
816
|
+
set?: Record<string, unknown>;
|
|
817
|
+
}
|
|
818
|
+
/** The first state of an object, or one whose set or order of attributes changed. Replace. */
|
|
819
|
+
export interface LivePoFrame {
|
|
820
|
+
type: 'po';
|
|
821
|
+
sub: string;
|
|
822
|
+
po: PersistentObject;
|
|
823
|
+
}
|
|
824
|
+
export interface LivePoPatchFrame {
|
|
825
|
+
type: 'poPatch';
|
|
826
|
+
sub: string;
|
|
827
|
+
patch: LivePoPatch;
|
|
828
|
+
}
|
|
829
|
+
/** Deleted or no longer readable (one answer). The subscription has ended. */
|
|
830
|
+
export interface LiveGoneFrame {
|
|
831
|
+
type: 'gone';
|
|
832
|
+
sub: string;
|
|
833
|
+
}
|
|
834
|
+
/** The first page, a page whose columns changed, or a change a patch would not make smaller. Replace. */
|
|
835
|
+
export interface LiveResultFrame {
|
|
836
|
+
type: 'result';
|
|
837
|
+
sub: string;
|
|
838
|
+
result: QueryResult;
|
|
839
|
+
}
|
|
840
|
+
export interface LivePatchFrame {
|
|
753
841
|
type: 'patch';
|
|
754
|
-
|
|
842
|
+
sub: string;
|
|
843
|
+
patch: LiveQueryPatch;
|
|
755
844
|
}
|
|
756
|
-
|
|
845
|
+
/** The subscription has ended. Without `sub` it answers an unparseable frame. */
|
|
846
|
+
export interface LiveErrorFrame {
|
|
757
847
|
type: 'error';
|
|
848
|
+
sub?: string;
|
|
849
|
+
code: LiveErrorCode;
|
|
758
850
|
message: string;
|
|
759
851
|
}
|
|
760
|
-
|
|
852
|
+
/** Heartbeat. Nothing to answer. */
|
|
853
|
+
export interface LivePingFrame {
|
|
854
|
+
type: 'ping';
|
|
855
|
+
}
|
|
856
|
+
export type LiveServerFrame = LivePoFrame | LivePoPatchFrame | LiveGoneFrame | LiveResultFrame | LivePatchFrame | LiveErrorFrame | LivePingFrame;
|
|
857
|
+
/** Close codes with a meaning of their own; any other code is reconnected with backoff. */
|
|
858
|
+
export declare const LIVE_CLOSE_REAUTHENTICATE = 4401;
|
|
859
|
+
export declare const LIVE_CLOSE_TOO_MANY_SOCKETS = 4429;
|
|
860
|
+
export declare const LIVE_CLOSE_MESSAGE_TOO_LARGE = 1009;
|
|
861
|
+
/**
|
|
862
|
+
* Why a watcher's subscription ended, beyond the server's own {@link LiveErrorCode}s — the socket-level
|
|
863
|
+
* failures the client surfaces instead of retrying:
|
|
864
|
+
* - `tooManySockets`: closed with 4429; not reconnected until a new watcher asks.
|
|
865
|
+
* - `unauthenticated`: closed with 4401 again within seconds of reconnecting for a 4401.
|
|
866
|
+
* - `messageTooLarge`: closed with 1009, a client bug; not retried blindly.
|
|
867
|
+
*/
|
|
868
|
+
export type LiveFailureCode = LiveErrorCode | 'tooManySockets' | 'unauthenticated' | 'messageTooLarge';
|
|
869
|
+
export interface LiveErrorEvent {
|
|
870
|
+
type: 'error';
|
|
871
|
+
code: LiveFailureCode;
|
|
872
|
+
message: string;
|
|
873
|
+
}
|
|
874
|
+
/** `po`: the object with every patch applied. `gone` and `error` end the stream (it completes after them). */
|
|
875
|
+
export type LivePoEvent = {
|
|
876
|
+
type: 'po';
|
|
877
|
+
po: PersistentObject;
|
|
878
|
+
} | {
|
|
879
|
+
type: 'gone';
|
|
880
|
+
} | LiveErrorEvent;
|
|
881
|
+
/** `result`: the page with every patch applied. `error` ends the stream (it completes after it). */
|
|
882
|
+
export type LiveQueryEvent = {
|
|
883
|
+
type: 'result';
|
|
884
|
+
result: QueryResult;
|
|
885
|
+
} | LiveErrorEvent;
|
|
886
|
+
/**
|
|
887
|
+
* Applies a `patch` frame to a held page, exactly as the protocol says. A new id in `upsert` that `order`
|
|
888
|
+
* does not place (the server always sends `order` when membership changes, so this is defensive) is
|
|
889
|
+
* appended rather than dropped.
|
|
890
|
+
*/
|
|
891
|
+
export declare function applyLiveQueryPatch(held: QueryResult, patch: LiveQueryPatch): QueryResult;
|
|
892
|
+
/** Applies a `poPatch` frame to a held object: `set` assigned, changed attributes replaced by `name`. */
|
|
893
|
+
export declare function applyLivePoPatch(held: PersistentObject, patch: LivePoPatch): PersistentObject;
|
|
761
894
|
/**
|
|
762
895
|
* Conversions between the wire format for a timestamp and what an `<input type="datetime-local">`
|
|
763
896
|
* or `<input type="date">` will accept.
|