@mintplayer/ng-spark 0.3.0 → 22.0.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-client-operations.mjs +180 -0
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-icon.mjs +9 -6
- package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +84 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +91 -74
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +55 -22
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +97 -92
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +63 -11
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +71 -36
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +138 -126
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +172 -18
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +99 -50
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/package.json +12 -7
- package/types/mintplayer-ng-spark-client-operations.d.ts +170 -0
- package/types/mintplayer-ng-spark-icon.d.ts +1 -1
- package/types/mintplayer-ng-spark-models.d.ts +54 -10
- package/types/mintplayer-ng-spark-pipes.d.ts +8 -0
- package/types/mintplayer-ng-spark-po-create.d.ts +2 -1
- package/types/mintplayer-ng-spark-po-detail.d.ts +14 -16
- package/types/mintplayer-ng-spark-po-edit.d.ts +4 -2
- package/types/mintplayer-ng-spark-po-form.d.ts +10 -9
- package/types/mintplayer-ng-spark-query-list.d.ts +26 -16
- package/types/mintplayer-ng-spark-retry-action-modal.d.ts +33 -4
- package/types/mintplayer-ng-spark-services.d.ts +32 -6
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { PersistentObject } from '@mintplayer/ng-spark/models';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { InjectionToken, EnvironmentProviders } from '@angular/core';
|
|
4
|
+
|
|
5
|
+
declare enum NotificationKind {
|
|
6
|
+
Info = 0,
|
|
7
|
+
Success = 1,
|
|
8
|
+
Warning = 2,
|
|
9
|
+
Error = 3
|
|
10
|
+
}
|
|
11
|
+
interface NavigateOperation {
|
|
12
|
+
type: 'navigate';
|
|
13
|
+
objectTypeId?: string;
|
|
14
|
+
id?: string;
|
|
15
|
+
routeName?: string;
|
|
16
|
+
}
|
|
17
|
+
interface NotifyOperation {
|
|
18
|
+
type: 'notify';
|
|
19
|
+
message: string;
|
|
20
|
+
kind: NotificationKind;
|
|
21
|
+
durationMs?: number;
|
|
22
|
+
}
|
|
23
|
+
interface RefreshAttributeOperation {
|
|
24
|
+
type: 'refreshAttribute';
|
|
25
|
+
objectTypeId: string;
|
|
26
|
+
id: string;
|
|
27
|
+
attributeName: string;
|
|
28
|
+
value?: unknown;
|
|
29
|
+
}
|
|
30
|
+
interface RefreshQueryOperation {
|
|
31
|
+
type: 'refreshQuery';
|
|
32
|
+
queryId: string;
|
|
33
|
+
}
|
|
34
|
+
type DisableTarget = {
|
|
35
|
+
kind: 'persistentObject';
|
|
36
|
+
objectTypeId: string;
|
|
37
|
+
id: string;
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'query';
|
|
40
|
+
queryId: string;
|
|
41
|
+
} | {
|
|
42
|
+
kind: 'currentResponse';
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'session';
|
|
45
|
+
};
|
|
46
|
+
interface DisableActionOperation {
|
|
47
|
+
type: 'disableAction';
|
|
48
|
+
actionName: string;
|
|
49
|
+
target: DisableTarget;
|
|
50
|
+
}
|
|
51
|
+
interface RetryOperation {
|
|
52
|
+
type: 'retry';
|
|
53
|
+
step: number;
|
|
54
|
+
title: string;
|
|
55
|
+
options: string[];
|
|
56
|
+
defaultOption?: string | null;
|
|
57
|
+
persistentObject?: PersistentObject | null;
|
|
58
|
+
message?: string | null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Discriminated union of known operation types, plus an open shape for unknown
|
|
62
|
+
* future operations. Handlers should narrow via the `type` discriminator before
|
|
63
|
+
* accessing fields specific to their operation type.
|
|
64
|
+
*/
|
|
65
|
+
type ClientOperation = NavigateOperation | NotifyOperation | RefreshAttributeOperation | RefreshQueryOperation | DisableActionOperation | RetryOperation | {
|
|
66
|
+
type: string;
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Wire envelope returned by every action endpoint. `result` carries the primary
|
|
71
|
+
* payload (the PersistentObject for a Create, the QueryResult for an Execute,
|
|
72
|
+
* etc.); `operations` carries the side-effects the frontend dispatches.
|
|
73
|
+
*/
|
|
74
|
+
interface ClientOperationEnvelope<T = unknown> {
|
|
75
|
+
result: T | null;
|
|
76
|
+
operations: ClientOperation[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Routes received operations to registered handlers. Unknown operation types
|
|
81
|
+
* (no matching registration) are silently dropped — this is the forward-compat
|
|
82
|
+
* contract that lets new operation types ship server-side without coordinated
|
|
83
|
+
* client updates.
|
|
84
|
+
*
|
|
85
|
+
* Last-registered-wins on duplicate `type` values, matching standard
|
|
86
|
+
* Angular multi-provider override semantics.
|
|
87
|
+
*
|
|
88
|
+
* R2-H19 — security contract for handler authors:
|
|
89
|
+
* The dispatcher treats handler resolution as allow-list-by-type (unknown
|
|
90
|
+
* types drop). It does NOT validate the *content* of each operation. Handlers
|
|
91
|
+
* that act on URL-shaped fields (navigate, redirect, openWindow) MUST run
|
|
92
|
+
* the value through `sanitizeReturnUrl` from `@mintplayer/ng-spark-auth/models`
|
|
93
|
+
* (or an equivalent same-origin check) before acting on it. Otherwise a
|
|
94
|
+
* single attribute-echo XSS or a single mid-channel byte flip on a non-TLS
|
|
95
|
+
* path lets the server drive client navigation to an attacker host. The
|
|
96
|
+
* built-in `notify` handler renders via Angular interpolation (escaped) so
|
|
97
|
+
* it's safe to pass through, but anything more powerful must validate.
|
|
98
|
+
*/
|
|
99
|
+
declare class SparkClientOperationDispatcher {
|
|
100
|
+
private readonly handlerMap;
|
|
101
|
+
constructor();
|
|
102
|
+
dispatch(operations: readonly ClientOperation[] | null | undefined): void;
|
|
103
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkClientOperationDispatcher, never>;
|
|
104
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<SparkClientOperationDispatcher>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A handler for a specific operation type. Receives the operation and
|
|
109
|
+
* executes the side-effect (e.g. show a toast, navigate, refresh a query).
|
|
110
|
+
* Handlers should `as`-narrow the operation to the type they registered for.
|
|
111
|
+
*/
|
|
112
|
+
type ClientOperationHandler = (operation: ClientOperation) => void;
|
|
113
|
+
/**
|
|
114
|
+
* One entry in the multi-provider registration. Apps can register custom
|
|
115
|
+
* handlers alongside the built-in ones to extend the operation set with
|
|
116
|
+
* app-specific operation types.
|
|
117
|
+
*/
|
|
118
|
+
interface ClientOperationHandlerRegistration {
|
|
119
|
+
type: string;
|
|
120
|
+
handler: ClientOperationHandler;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Multi-provider token. `provideSparkClientOperations()` registers the
|
|
124
|
+
* built-in handlers; apps can add their own with additional `multi: true`
|
|
125
|
+
* providers using this token.
|
|
126
|
+
*/
|
|
127
|
+
declare const SPARK_CLIENT_OPERATION_HANDLERS: InjectionToken<readonly ClientOperationHandlerRegistration[]>;
|
|
128
|
+
|
|
129
|
+
interface SparkToast {
|
|
130
|
+
id: string;
|
|
131
|
+
message: string;
|
|
132
|
+
kind: NotificationKind;
|
|
133
|
+
durationMs: number;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Holds the active toasts as a signal. The `<spark-toast-container>` component
|
|
137
|
+
* renders them; the built-in `notify` operation handler pushes new toasts here.
|
|
138
|
+
*
|
|
139
|
+
* Auto-dismissal: each toast schedules its own removal after `durationMs`. Pass
|
|
140
|
+
* `0` to make a toast sticky (manual dismissal only).
|
|
141
|
+
*/
|
|
142
|
+
declare class SparkNotificationService {
|
|
143
|
+
private readonly _toasts;
|
|
144
|
+
readonly toasts: i0.Signal<readonly SparkToast[]>;
|
|
145
|
+
show(message: string, kind?: NotificationKind, durationMs?: number): void;
|
|
146
|
+
dismiss(id: string): void;
|
|
147
|
+
clear(): void;
|
|
148
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkNotificationService, never>;
|
|
149
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<SparkNotificationService>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
declare class SparkToastContainerComponent {
|
|
153
|
+
protected readonly notifications: SparkNotificationService;
|
|
154
|
+
protected readonly Kind: typeof NotificationKind;
|
|
155
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkToastContainerComponent, never>;
|
|
156
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkToastContainerComponent, "spark-toast-container", never, {}, {}, never, never, true, never>;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Registers the built-in client-operation handlers. Currently registers `notify`;
|
|
161
|
+
* additional types (`navigate`, `refreshQuery`, `refreshAttribute`, `disableAction`)
|
|
162
|
+
* land in subsequent commits. Apps add this once in their bootstrap providers.
|
|
163
|
+
*
|
|
164
|
+
* To register custom operation types alongside the built-ins, add additional
|
|
165
|
+
* `multi: true` providers using <see cref="SPARK_CLIENT_OPERATION_HANDLERS" />.
|
|
166
|
+
*/
|
|
167
|
+
declare function provideSparkClientOperations(): EnvironmentProviders;
|
|
168
|
+
|
|
169
|
+
export { NotificationKind, SPARK_CLIENT_OPERATION_HANDLERS, SparkClientOperationDispatcher, SparkNotificationService, SparkToastContainerComponent, provideSparkClientOperations };
|
|
170
|
+
export type { ClientOperation, ClientOperationEnvelope, ClientOperationHandler, ClientOperationHandlerRegistration, DisableActionOperation, DisableTarget, NavigateOperation, NotifyOperation, RefreshAttributeOperation, RefreshQueryOperation, RetryOperation, SparkToast };
|
|
@@ -4,7 +4,7 @@ import * as _angular_core from '@angular/core';
|
|
|
4
4
|
declare class SparkIconComponent {
|
|
5
5
|
private registry;
|
|
6
6
|
name: _angular_core.InputSignal<string>;
|
|
7
|
-
iconHtml: _angular_core.Signal<_angular_platform_browser.SafeHtml>;
|
|
7
|
+
iconHtml: _angular_core.Signal<_angular_platform_browser.SafeHtml | undefined>;
|
|
8
8
|
cssFallbackClass: _angular_core.Signal<string>;
|
|
9
9
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkIconComponent, never>;
|
|
10
10
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkIconComponent, "spark-icon", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
@@ -35,6 +35,14 @@ declare enum ShowedOn {
|
|
|
35
35
|
*/
|
|
36
36
|
declare function hasShowedOnFlag(value: ShowedOn | string | undefined, flag: ShowedOn): boolean;
|
|
37
37
|
|
|
38
|
+
interface PersistentObject {
|
|
39
|
+
id: string;
|
|
40
|
+
name: string;
|
|
41
|
+
objectTypeId: string;
|
|
42
|
+
breadcrumb?: string;
|
|
43
|
+
attributes: PersistentObjectAttribute[];
|
|
44
|
+
}
|
|
45
|
+
|
|
38
46
|
interface PersistentObjectAttribute {
|
|
39
47
|
id: string;
|
|
40
48
|
name: string;
|
|
@@ -61,14 +69,23 @@ interface PersistentObjectAttribute {
|
|
|
61
69
|
renderer?: string;
|
|
62
70
|
/** Options passed to the renderer component */
|
|
63
71
|
rendererOptions?: Record<string, any>;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
/**
|
|
73
|
+
* When `dataType === 'AsDetail'` and `isArray === false`: the single nested
|
|
74
|
+
* PersistentObject carrying the detail entity's values. `null` when the field is unset.
|
|
75
|
+
* Mirrors the server's PersistentObjectAttributeAsDetail.Object.
|
|
76
|
+
*/
|
|
77
|
+
object?: PersistentObject | null;
|
|
78
|
+
/**
|
|
79
|
+
* When `dataType === 'AsDetail'` and `isArray === true`: the nested PO collection, one
|
|
80
|
+
* per array element. Mirrors PersistentObjectAttributeAsDetail.Objects.
|
|
81
|
+
*/
|
|
82
|
+
objects?: PersistentObject[] | null;
|
|
83
|
+
/**
|
|
84
|
+
* CLR type name of the detail entity for AsDetail attributes (e.g. `HR.Entities.Address`).
|
|
85
|
+
* Emitted by the server so the frontend can look up the matching EntityType metadata
|
|
86
|
+
* without re-resolving through `asDetailType` on the schema definition.
|
|
87
|
+
*/
|
|
88
|
+
asDetailType?: string;
|
|
72
89
|
}
|
|
73
90
|
|
|
74
91
|
interface EntityAttributeDefinition {
|
|
@@ -271,5 +288,32 @@ interface StreamingErrorMessage {
|
|
|
271
288
|
}
|
|
272
289
|
type StreamingMessage = StreamingSnapshotMessage | StreamingPatchMessage | StreamingErrorMessage;
|
|
273
290
|
|
|
274
|
-
|
|
275
|
-
|
|
291
|
+
/**
|
|
292
|
+
* Resolves an `EntityType` by its CLR type name (e.g. `"HR.Entities.Address"`).
|
|
293
|
+
* Callers typically close over `sparkService.getEntityTypes()`'s cached list.
|
|
294
|
+
*/
|
|
295
|
+
type EntityTypeResolver = (clrTypeName: string) => EntityType | undefined;
|
|
296
|
+
/**
|
|
297
|
+
* Flattens a nested `PersistentObject` into the plain `Record<string, any>` shape the
|
|
298
|
+
* form state uses throughout ng-spark. Primitive / reference attributes contribute their
|
|
299
|
+
* `value`; nested AsDetail attributes recurse — single becomes an inner dict, array
|
|
300
|
+
* becomes an array of inner dicts. Returns `{}` for `null` / `undefined` input.
|
|
301
|
+
*
|
|
302
|
+
* This is the ONE place that reads the server's new AsDetail wire shape and collapses it
|
|
303
|
+
* back to the flat dict the form components already handle.
|
|
304
|
+
*/
|
|
305
|
+
declare function nestedPoToDict(po: PersistentObject | null | undefined): Record<string, any>;
|
|
306
|
+
/**
|
|
307
|
+
* Builds a nested `PersistentObject` from a flat dict against the schema in
|
|
308
|
+
* <paramref name="entityType"/>. Used when the form is about to save — AsDetail attributes
|
|
309
|
+
* are no longer sent as flat dicts in `attribute.value`; the server now requires
|
|
310
|
+
* `attribute.object` / `attribute.objects` with fully scaffolded nested POs.
|
|
311
|
+
*
|
|
312
|
+
* `resolve` walks through AsDetail types registered elsewhere (usually the full
|
|
313
|
+
* `getEntityTypes()` list, keyed by CLR type name). Nested AsDetail inside AsDetail is
|
|
314
|
+
* handled recursively.
|
|
315
|
+
*/
|
|
316
|
+
declare function dictToNestedPo(dict: Record<string, any> | null | undefined, entityType: EntityType, resolve: EntityTypeResolver): PersistentObject;
|
|
317
|
+
|
|
318
|
+
export { ELookupDisplayType, ShowedOn, currentLanguage, dictToNestedPo, hasShowedOnFlag, nestedPoToDict, resolveTranslation };
|
|
319
|
+
export type { AttributeGroup, AttributeTab, CustomActionDefinition, EntityAttributeDefinition, EntityPermissions, EntityType, EntityTypeResolver, LookupReference, LookupReferenceListItem, LookupReferenceValue, PersistentObject, PersistentObjectAttribute, ProgramUnit, ProgramUnitGroup, ProgramUnitsConfiguration, QueryResult, RetryActionPayload, RetryActionResult, SparkQuery, SparkQueryRenderMode, SparkQuerySortColumn, StreamingErrorMessage, StreamingMessage, StreamingPatchItem, StreamingPatchMessage, StreamingSnapshotMessage, TranslatedString, ValidationError, ValidationErrorResponse, ValidationRule };
|
|
@@ -134,6 +134,14 @@ declare class IconNamePipe implements PipeTransform {
|
|
|
134
134
|
static ɵpipe: i0.ɵɵPipeDeclaration<IconNamePipe, "iconName", true>;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Resolves an attribute to a list of flat row dicts for the detail-page table.
|
|
139
|
+
* AsDetail array attributes carry their data as nested PersistentObjects in
|
|
140
|
+
* <c>attr.objects</c>, not <c>attr.value</c> — the server stopped putting flat
|
|
141
|
+
* dicts in <c>value</c> when AsDetail moved to its dedicated wire shape. Without
|
|
142
|
+
* this branch, the detail page rendered AsDetail arrays as empty tables even
|
|
143
|
+
* when the edit page (which reads <c>attr.objects</c> directly) showed rows.
|
|
144
|
+
*/
|
|
137
145
|
declare class ArrayValuePipe implements PipeTransform {
|
|
138
146
|
transform(attrName: string, item: PersistentObject | null): Record<string, any>[];
|
|
139
147
|
static ɵfac: i0.ɵɵFactoryDeclaration<ArrayValuePipe, never>;
|
|
@@ -10,11 +10,12 @@ declare class SparkPoCreateComponent {
|
|
|
10
10
|
saved: _angular_core.OutputEmitterRef<PersistentObject>;
|
|
11
11
|
cancelled: _angular_core.OutputEmitterRef<void>;
|
|
12
12
|
colors: typeof Color;
|
|
13
|
-
entityType: _angular_core.WritableSignal<EntityType>;
|
|
13
|
+
entityType: _angular_core.WritableSignal<EntityType | null>;
|
|
14
14
|
type: _angular_core.WritableSignal<string>;
|
|
15
15
|
formData: _angular_core.WritableSignal<Record<string, any>>;
|
|
16
16
|
validationErrors: _angular_core.WritableSignal<ValidationError[]>;
|
|
17
17
|
isSaving: _angular_core.WritableSignal<boolean>;
|
|
18
|
+
private allEntityTypes;
|
|
18
19
|
generalErrors: _angular_core.Signal<ValidationError[]>;
|
|
19
20
|
constructor();
|
|
20
21
|
private onParamsChange;
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
2
|
import { TemplateRef, Type } from '@angular/core';
|
|
3
3
|
import { Color } from '@mintplayer/ng-bootstrap';
|
|
4
|
+
import { SparkLanguageService } from '@mintplayer/ng-spark/services';
|
|
4
5
|
import { PersistentObject, EntityType, CustomActionDefinition, LookupReference, EntityAttributeDefinition, AttributeTab, AttributeGroup, SparkQuery } from '@mintplayer/ng-spark/models';
|
|
5
|
-
import { DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';
|
|
6
|
-
import { VirtualDatatableDataSource } from '@mintplayer/ng-bootstrap/virtual-datatable';
|
|
7
|
-
import { PaginationResponse } from '@mintplayer/pagination';
|
|
6
|
+
import { DatatableSettings, BsDatatableFetch } from '@mintplayer/ng-bootstrap/datatable';
|
|
8
7
|
|
|
9
8
|
declare class SparkPoDetailComponent {
|
|
10
9
|
private readonly route;
|
|
11
10
|
private readonly router;
|
|
12
11
|
private readonly sparkService;
|
|
13
|
-
|
|
12
|
+
protected readonly lang: SparkLanguageService;
|
|
14
13
|
private readonly rendererRegistry;
|
|
15
14
|
showCustomActions: _angular_core.InputSignal<boolean>;
|
|
16
|
-
extraActionsTemplate: _angular_core.InputSignal<TemplateRef<void
|
|
15
|
+
extraActionsTemplate: _angular_core.InputSignal<TemplateRef<void> | null>;
|
|
17
16
|
extraContentTemplate: _angular_core.InputSignal<TemplateRef<{
|
|
18
17
|
$implicit: PersistentObject;
|
|
19
18
|
entityType: EntityType;
|
|
20
|
-
}
|
|
19
|
+
}> | null>;
|
|
21
20
|
edited: _angular_core.OutputEmitterRef<void>;
|
|
22
21
|
deleted: _angular_core.OutputEmitterRef<void>;
|
|
23
22
|
customActionExecuted: _angular_core.OutputEmitterRef<{
|
|
@@ -25,10 +24,10 @@ declare class SparkPoDetailComponent {
|
|
|
25
24
|
item: PersistentObject;
|
|
26
25
|
}>;
|
|
27
26
|
colors: typeof Color;
|
|
28
|
-
errorMessage: _angular_core.WritableSignal<string>;
|
|
29
|
-
entityType: _angular_core.WritableSignal<EntityType>;
|
|
27
|
+
errorMessage: _angular_core.WritableSignal<string | null>;
|
|
28
|
+
entityType: _angular_core.WritableSignal<EntityType | null>;
|
|
30
29
|
allEntityTypes: _angular_core.WritableSignal<EntityType[]>;
|
|
31
|
-
item: _angular_core.WritableSignal<PersistentObject>;
|
|
30
|
+
item: _angular_core.WritableSignal<PersistentObject | null>;
|
|
32
31
|
lookupReferenceOptions: _angular_core.WritableSignal<Record<string, LookupReference>>;
|
|
33
32
|
asDetailTypes: _angular_core.WritableSignal<Record<string, EntityType>>;
|
|
34
33
|
asDetailReferenceOptions: _angular_core.WritableSignal<Record<string, Record<string, PersistentObject[]>>>;
|
|
@@ -63,21 +62,20 @@ declare class SparkSubQueryComponent {
|
|
|
63
62
|
queryId: _angular_core.InputSignal<string>;
|
|
64
63
|
parentId: _angular_core.InputSignal<string>;
|
|
65
64
|
parentType: _angular_core.InputSignal<string>;
|
|
66
|
-
query: _angular_core.WritableSignal<SparkQuery>;
|
|
67
|
-
entityType: _angular_core.WritableSignal<EntityType>;
|
|
65
|
+
query: _angular_core.WritableSignal<SparkQuery | null>;
|
|
66
|
+
entityType: _angular_core.WritableSignal<EntityType | null>;
|
|
68
67
|
allEntityTypes: _angular_core.WritableSignal<EntityType[]>;
|
|
69
|
-
|
|
68
|
+
resultCount: _angular_core.WritableSignal<number | null>;
|
|
70
69
|
lookupReferenceOptions: _angular_core.WritableSignal<Record<string, LookupReference>>;
|
|
71
70
|
loading: _angular_core.WritableSignal<boolean>;
|
|
72
71
|
canRead: _angular_core.WritableSignal<boolean>;
|
|
73
72
|
settings: _angular_core.WritableSignal<DatatableSettings>;
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
fetchFn: _angular_core.WritableSignal<BsDatatableFetch<PersistentObject> | null>;
|
|
74
|
+
isVirtualScrolling: _angular_core.Signal<boolean>;
|
|
76
75
|
visibleAttributes: _angular_core.Signal<EntityAttributeDefinition[]>;
|
|
77
76
|
constructor();
|
|
78
77
|
private loadData;
|
|
79
|
-
private
|
|
80
|
-
onSettingsChange(): void;
|
|
78
|
+
private makeFetch;
|
|
81
79
|
private loadLookupReferenceOptions;
|
|
82
80
|
getColumnRendererComponent(attr: EntityAttributeDefinition): Type<any> | null;
|
|
83
81
|
getColumnRendererInputs(item: PersistentObject, attr: EntityAttributeDefinition): Record<string, any>;
|
|
@@ -10,17 +10,19 @@ declare class SparkPoEditComponent {
|
|
|
10
10
|
saved: _angular_core.OutputEmitterRef<PersistentObject>;
|
|
11
11
|
cancelled: _angular_core.OutputEmitterRef<void>;
|
|
12
12
|
colors: typeof Color;
|
|
13
|
-
entityType: _angular_core.WritableSignal<EntityType>;
|
|
14
|
-
item: _angular_core.WritableSignal<PersistentObject>;
|
|
13
|
+
entityType: _angular_core.WritableSignal<EntityType | null>;
|
|
14
|
+
item: _angular_core.WritableSignal<PersistentObject | null>;
|
|
15
15
|
type: string;
|
|
16
16
|
id: string;
|
|
17
17
|
formData: _angular_core.WritableSignal<Record<string, any>>;
|
|
18
18
|
validationErrors: _angular_core.WritableSignal<ValidationError[]>;
|
|
19
19
|
isSaving: _angular_core.WritableSignal<boolean>;
|
|
20
|
+
private allEntityTypes;
|
|
20
21
|
generalErrors: _angular_core.Signal<ValidationError[]>;
|
|
21
22
|
constructor();
|
|
22
23
|
private onParamsChange;
|
|
23
24
|
initFormData(): void;
|
|
25
|
+
private resolveEntityType;
|
|
24
26
|
getEditableAttributes(): _mintplayer_ng_spark_models.EntityAttributeDefinition[];
|
|
25
27
|
onSave(): Promise<void>;
|
|
26
28
|
onCancel(): void;
|
|
@@ -9,33 +9,33 @@ declare class SparkPoFormComponent {
|
|
|
9
9
|
private readonly sparkService;
|
|
10
10
|
private readonly translations;
|
|
11
11
|
private readonly rendererRegistry;
|
|
12
|
-
entityType: _angular_core.InputSignal<EntityType>;
|
|
12
|
+
entityType: _angular_core.InputSignal<EntityType | null>;
|
|
13
13
|
formData: _angular_core.ModelSignal<Record<string, any>>;
|
|
14
14
|
validationErrors: _angular_core.InputSignal<ValidationError[]>;
|
|
15
15
|
showButtons: _angular_core.InputSignal<boolean>;
|
|
16
16
|
isSaving: _angular_core.InputSignal<boolean>;
|
|
17
|
-
parentId: _angular_core.InputSignal<string>;
|
|
18
|
-
parentType: _angular_core.InputSignal<string>;
|
|
17
|
+
parentId: _angular_core.InputSignal<string | undefined>;
|
|
18
|
+
parentType: _angular_core.InputSignal<string | undefined>;
|
|
19
19
|
save: _angular_core.OutputEmitterRef<void>;
|
|
20
20
|
cancel: _angular_core.OutputEmitterRef<void>;
|
|
21
21
|
colors: typeof Color;
|
|
22
22
|
referenceOptions: _angular_core.WritableSignal<Record<string, PersistentObject[]>>;
|
|
23
23
|
asDetailTypes: _angular_core.WritableSignal<Record<string, EntityType>>;
|
|
24
24
|
lookupReferenceOptions: _angular_core.WritableSignal<Record<string, LookupReference>>;
|
|
25
|
-
editingAsDetailAttr: _angular_core.WritableSignal<EntityAttributeDefinition>;
|
|
25
|
+
editingAsDetailAttr: _angular_core.WritableSignal<EntityAttributeDefinition | null>;
|
|
26
26
|
asDetailFormData: _angular_core.WritableSignal<Record<string, any>>;
|
|
27
27
|
showAsDetailModal: _angular_core.WritableSignal<boolean>;
|
|
28
|
-
editingArrayIndex: _angular_core.WritableSignal<number>;
|
|
28
|
+
editingArrayIndex: _angular_core.WritableSignal<number | null>;
|
|
29
29
|
asDetailPermissions: _angular_core.WritableSignal<Record<string, EntityPermissions>>;
|
|
30
30
|
asDetailReferenceOptions: _angular_core.WritableSignal<Record<string, Record<string, PersistentObject[]>>>;
|
|
31
|
-
editingReferenceAttr: _angular_core.WritableSignal<EntityAttributeDefinition>;
|
|
31
|
+
editingReferenceAttr: _angular_core.WritableSignal<EntityAttributeDefinition | null>;
|
|
32
32
|
showReferenceModal: _angular_core.WritableSignal<boolean>;
|
|
33
33
|
referenceModalItems: _angular_core.WritableSignal<PersistentObject[]>;
|
|
34
|
-
referenceModalEntityType: _angular_core.WritableSignal<EntityType>;
|
|
35
|
-
referenceModalPagination: _angular_core.WritableSignal<PaginationResponse<PersistentObject
|
|
34
|
+
referenceModalEntityType: _angular_core.WritableSignal<EntityType | null>;
|
|
35
|
+
referenceModalPagination: _angular_core.WritableSignal<PaginationResponse<PersistentObject> | undefined>;
|
|
36
36
|
referenceModalSettings: _angular_core.WritableSignal<DatatableSettings>;
|
|
37
37
|
referenceSearchTerm: string;
|
|
38
|
-
editingLookupAttr: _angular_core.WritableSignal<EntityAttributeDefinition>;
|
|
38
|
+
editingLookupAttr: _angular_core.WritableSignal<EntityAttributeDefinition | null>;
|
|
39
39
|
showLookupModal: _angular_core.WritableSignal<boolean>;
|
|
40
40
|
lookupModalItems: _angular_core.WritableSignal<LookupReferenceValue[]>;
|
|
41
41
|
lookupSearchTerm: _angular_core.WritableSignal<string>;
|
|
@@ -47,6 +47,7 @@ declare class SparkPoFormComponent {
|
|
|
47
47
|
groupsForTab(tab: AttributeTab): AttributeGroup[];
|
|
48
48
|
attrsForGroup(group: AttributeGroup): EntityAttributeDefinition[];
|
|
49
49
|
referenceVisibleAttributes: _angular_core.Signal<EntityAttributeDefinition[]>;
|
|
50
|
+
referenceModalRows: _angular_core.Signal<PersistentObject[]>;
|
|
50
51
|
filteredLookupItems: _angular_core.Signal<LookupReferenceValue[]>;
|
|
51
52
|
constructor();
|
|
52
53
|
private toRecord;
|
|
@@ -1,46 +1,56 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
2
|
import { TemplateRef, Type } from '@angular/core';
|
|
3
3
|
import { Color } from '@mintplayer/ng-bootstrap';
|
|
4
|
-
import { DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { PersistentObject, SparkQuery, EntityType, LookupReference, EntityAttributeDefinition } from '@mintplayer/ng-spark/models';
|
|
4
|
+
import { BsDatatableFetch, DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';
|
|
5
|
+
import { SparkLanguageService } from '@mintplayer/ng-spark/services';
|
|
6
|
+
import { PersistentObject, CustomActionDefinition, SparkQuery, EntityType, LookupReference, EntityAttributeDefinition } from '@mintplayer/ng-spark/models';
|
|
8
7
|
|
|
9
8
|
declare class SparkQueryListComponent {
|
|
10
9
|
private readonly route;
|
|
11
10
|
private readonly router;
|
|
12
11
|
private readonly sparkService;
|
|
13
12
|
private readonly streamingService;
|
|
13
|
+
protected readonly lang: SparkLanguageService;
|
|
14
14
|
private readonly rendererRegistry;
|
|
15
15
|
private readonly destroyRef;
|
|
16
|
-
extraActionsTemplate: _angular_core.InputSignal<TemplateRef<void
|
|
16
|
+
extraActionsTemplate: _angular_core.InputSignal<TemplateRef<void> | null>;
|
|
17
|
+
showCustomActions: _angular_core.InputSignal<boolean>;
|
|
17
18
|
rowClicked: _angular_core.OutputEmitterRef<PersistentObject>;
|
|
18
19
|
createClicked: _angular_core.OutputEmitterRef<void>;
|
|
20
|
+
customActionExecuted: _angular_core.OutputEmitterRef<{
|
|
21
|
+
action: CustomActionDefinition;
|
|
22
|
+
}>;
|
|
19
23
|
colors: typeof Color;
|
|
20
|
-
errorMessage: _angular_core.WritableSignal<string>;
|
|
21
|
-
query: _angular_core.WritableSignal<SparkQuery>;
|
|
22
|
-
entityType: _angular_core.WritableSignal<EntityType>;
|
|
24
|
+
errorMessage: _angular_core.WritableSignal<string | null>;
|
|
25
|
+
query: _angular_core.WritableSignal<SparkQuery | null>;
|
|
26
|
+
entityType: _angular_core.WritableSignal<EntityType | null>;
|
|
23
27
|
allEntityTypes: _angular_core.WritableSignal<EntityType[]>;
|
|
24
28
|
lookupReferenceOptions: _angular_core.WritableSignal<Record<string, LookupReference>>;
|
|
25
|
-
|
|
29
|
+
resultCount: _angular_core.WritableSignal<number | null>;
|
|
26
30
|
searchTerm: string;
|
|
27
31
|
canRead: _angular_core.WritableSignal<boolean>;
|
|
28
32
|
canCreate: _angular_core.WritableSignal<boolean>;
|
|
33
|
+
customActions: _angular_core.WritableSignal<CustomActionDefinition[]>;
|
|
29
34
|
isStreaming: _angular_core.WritableSignal<boolean>;
|
|
30
35
|
private streamingSub;
|
|
31
36
|
private allItems;
|
|
32
|
-
|
|
37
|
+
streamItems: _angular_core.WritableSignal<PersistentObject[]>;
|
|
38
|
+
fetchFn: _angular_core.WritableSignal<BsDatatableFetch<PersistentObject> | null>;
|
|
33
39
|
settings: _angular_core.WritableSignal<DatatableSettings>;
|
|
34
|
-
virtualDataSource: _angular_core.WritableSignal<VirtualDatatableDataSource<PersistentObject>>;
|
|
35
|
-
virtualSettings: _angular_core.WritableSignal<DatatableSettings>;
|
|
36
40
|
constructor();
|
|
37
41
|
private onParamsChange;
|
|
42
|
+
onCustomAction(action: CustomActionDefinition): Promise<void>;
|
|
38
43
|
private resolveEntityTypeForQuery;
|
|
39
44
|
private extractSourceName;
|
|
40
45
|
private singularize;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Builds the server-side fetch callback the datatable invokes per page/sort.
|
|
48
|
+
* Reads `searchTerm` live, so a settings change (or a new fetchFn identity)
|
|
49
|
+
* refetches with the current search term.
|
|
50
|
+
*/
|
|
51
|
+
private makeFetch;
|
|
52
|
+
/** Force a refetch (e.g. after a custom action) without changing page/sort. */
|
|
53
|
+
private refresh;
|
|
44
54
|
onSearchChange(): void;
|
|
45
55
|
clearSearch(): void;
|
|
46
56
|
isVirtualScrolling: _angular_core.Signal<boolean>;
|
|
@@ -54,7 +64,7 @@ declare class SparkQueryListComponent {
|
|
|
54
64
|
private handleStreamingMessage;
|
|
55
65
|
private applyFilter;
|
|
56
66
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkQueryListComponent, never>;
|
|
57
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkQueryListComponent, "spark-query-list", never, { "extraActionsTemplate": { "alias": "extraActionsTemplate"; "required": false; "isSignal": true; }; }, { "rowClicked": "rowClicked"; "createClicked": "createClicked"; }, never, never, true, never>;
|
|
67
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkQueryListComponent, "spark-query-list", never, { "extraActionsTemplate": { "alias": "extraActionsTemplate"; "required": false; "isSignal": true; }; "showCustomActions": { "alias": "showCustomActions"; "required": false; "isSignal": true; }; }, { "rowClicked": "rowClicked"; "createClicked": "createClicked"; "customActionExecuted": "customActionExecuted"; }, never, never, true, never>;
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
export { SparkQueryListComponent };
|
|
@@ -1,14 +1,43 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
2
|
import { Color } from '@mintplayer/ng-bootstrap';
|
|
3
3
|
import { RetryActionService } from '@mintplayer/ng-spark/services';
|
|
4
|
+
import { EntityType } from '@mintplayer/ng-spark/models';
|
|
4
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Renders a retry-action popup. Before PRD §3 this component rendered title / message /
|
|
8
|
+
* option buttons only and silently forwarded the incoming <c>persistentObject</c> back to
|
|
9
|
+
* the server on submit — meaning any <c>Retry.Action(..., persistentObject)</c> flow had
|
|
10
|
+
* no UI to actually edit the PO. This component now embeds the shared PO form so every
|
|
11
|
+
* scalar / Reference / AsDetail attribute on the scaffolded Virtual PO is a real form
|
|
12
|
+
* field, and the values the user fills in flow back to the server via
|
|
13
|
+
* <c>RetryResult.PersistentObject</c>.
|
|
14
|
+
*/
|
|
5
15
|
declare class SparkRetryActionModalComponent {
|
|
6
16
|
protected readonly retryActionService: RetryActionService;
|
|
17
|
+
private readonly sparkService;
|
|
7
18
|
colors: typeof Color;
|
|
8
|
-
isOpen:
|
|
19
|
+
isOpen: _angular_core.Signal<boolean>;
|
|
20
|
+
/**
|
|
21
|
+
* EntityType definition for the incoming PO — fetched lazily via SparkService so the
|
|
22
|
+
* form knows which attributes are editable, their labels, rules, renderers, etc.
|
|
23
|
+
* `null` when the payload has no persistentObject or its objectTypeId doesn't match
|
|
24
|
+
* any registered entity type (renders the modal as a simple option picker).
|
|
25
|
+
*/
|
|
26
|
+
entityType: _angular_core.WritableSignal<EntityType | null>;
|
|
27
|
+
formData: _angular_core.WritableSignal<Record<string, any>>;
|
|
28
|
+
private allEntityTypes;
|
|
29
|
+
constructor();
|
|
30
|
+
private seedForm;
|
|
9
31
|
onOption(option: string): void;
|
|
10
|
-
|
|
11
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Builds the PO the server sees under <c>Retry.Result.PersistentObject</c>. If the
|
|
34
|
+
* form resolved an EntityType, rebuild from the schema + formData (identical to the
|
|
35
|
+
* po-edit save path — AsDetail recursion included). Otherwise forward the incoming
|
|
36
|
+
* PO unmodified so pre-§3 flows without editable attributes keep working.
|
|
37
|
+
*/
|
|
38
|
+
private populatedPersistentObject;
|
|
39
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SparkRetryActionModalComponent, never>;
|
|
40
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SparkRetryActionModalComponent, "spark-retry-action-modal", never, {}, {}, never, never, true, never>;
|
|
12
41
|
}
|
|
13
42
|
|
|
14
43
|
export { SparkRetryActionModalComponent };
|
|
@@ -6,7 +6,7 @@ import { SafeHtml } from '@angular/platform-browser';
|
|
|
6
6
|
|
|
7
7
|
declare class RetryActionService {
|
|
8
8
|
private resolveRetry;
|
|
9
|
-
payload: i0.WritableSignal<RetryActionPayload>;
|
|
9
|
+
payload: i0.WritableSignal<RetryActionPayload | null>;
|
|
10
10
|
show(payload: RetryActionPayload): Promise<RetryActionResult>;
|
|
11
11
|
respond(result: RetryActionResult): void;
|
|
12
12
|
static ɵfac: i0.ɵɵFactoryDeclaration<RetryActionService, never>;
|
|
@@ -46,6 +46,7 @@ declare class SparkService {
|
|
|
46
46
|
private readonly baseUrl;
|
|
47
47
|
private readonly http;
|
|
48
48
|
private readonly retryActionService;
|
|
49
|
+
private readonly dispatcher;
|
|
49
50
|
getEntityTypes(): Promise<EntityType[]>;
|
|
50
51
|
getEntityType(id: string): Promise<EntityType>;
|
|
51
52
|
getEntityTypeByClrType(clrType: string): Promise<EntityType | undefined>;
|
|
@@ -78,19 +79,44 @@ declare class SparkService {
|
|
|
78
79
|
addLookupReferenceValue(name: string, value: LookupReferenceValue): Promise<LookupReferenceValue>;
|
|
79
80
|
updateLookupReferenceValue(name: string, key: string, value: LookupReferenceValue): Promise<LookupReferenceValue>;
|
|
80
81
|
deleteLookupReferenceValue(name: string, key: string): Promise<void>;
|
|
81
|
-
private
|
|
82
|
-
private
|
|
83
|
-
private
|
|
84
|
-
private
|
|
82
|
+
private postWithEnvelope;
|
|
83
|
+
private putWithEnvelope;
|
|
84
|
+
private deleteWithEnvelope;
|
|
85
|
+
private sendWithEnvelope;
|
|
86
|
+
private handleEnvelopeRetryError;
|
|
85
87
|
static ɵfac: i0.ɵɵFactoryDeclaration<SparkService, never>;
|
|
86
88
|
static ɵprov: i0.ɵɵInjectableDeclaration<SparkService>;
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
/**
|
|
92
|
+
* R2-M12: SVG icon registry. The registry no longer accepts a raw string —
|
|
93
|
+
* apps must pre-sanitize via `DomSanitizer.bypassSecurityTrustHtml` (or
|
|
94
|
+
* `parseSvg` to validate) before calling `register`. Treating the parameter
|
|
95
|
+
* as `SafeHtml` puts the explicit bypass decision in the caller's hands so a
|
|
96
|
+
* developer wiring server-supplied SVG (per-tenant branding fetched from a
|
|
97
|
+
* JSON endpoint) doesn't accidentally trust a `<svg><script>...</script>`
|
|
98
|
+
* payload.
|
|
99
|
+
*
|
|
100
|
+
* The built-in icons baked into the package are still bypass-trusted internally
|
|
101
|
+
* because they're known-safe at build time.
|
|
102
|
+
*/
|
|
89
103
|
declare class SparkIconRegistry {
|
|
90
104
|
private sanitizer;
|
|
91
105
|
private icons;
|
|
92
106
|
constructor();
|
|
93
|
-
|
|
107
|
+
/**
|
|
108
|
+
* Registers a pre-sanitized SVG icon. Callers MUST validate or explicitly
|
|
109
|
+
* trust the SVG before passing — for example:
|
|
110
|
+
*
|
|
111
|
+
* ```ts
|
|
112
|
+
* const safe = sanitizer.bypassSecurityTrustHtml(svgFromBuildTimeConstant);
|
|
113
|
+
* registry.register('app-logo', safe);
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* For server-supplied SVG, prefer a strict allow-list parser (no `<script>`,
|
|
117
|
+
* no `on*` attributes, no `href="javascript:..."`) before trusting.
|
|
118
|
+
*/
|
|
119
|
+
register(name: string, svg: SafeHtml): void;
|
|
94
120
|
get(name: string): SafeHtml | undefined;
|
|
95
121
|
has(name: string): boolean;
|
|
96
122
|
static ɵfac: i0.ɵɵFactoryDeclaration<SparkIconRegistry, never>;
|