@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
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { InjectionToken, Provider, Signal } from "@angular/core";
|
|
3
|
+
import { QueryResultItem } from "@mintplayer/ng-spark/models";
|
|
4
|
+
import { ConnectedPosition } from "@angular/cdk/overlay";
|
|
5
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
6
|
+
/** The `Notification` entity type of `MintPlayer.Spark.Notifications` (`App_Data/Model/Notification.json`). */
|
|
7
|
+
export declare const SPARK_NOTIFICATION_TYPE_ID = "411e3be6-5da0-5d84-bc21-001888fafc6d";
|
|
8
|
+
/** `MyNotifications` (alias `notifications`): the caller's notifications, newest first. Live. */
|
|
9
|
+
export declare const SPARK_MY_NOTIFICATIONS_QUERY_ID = "7123c201-9aed-50f9-9d9a-ede2491af7f9";
|
|
10
|
+
/** `UnreadNotifications` (alias `unread-notifications`): the caller's unread ones. Live. */
|
|
11
|
+
export declare const SPARK_UNREAD_NOTIFICATIONS_QUERY_ID = "a205d3e5-ff6e-5260-ac9e-e5c6b16644c9";
|
|
12
|
+
/** One notification as the bell lists it: a row of `MyNotifications`. */
|
|
13
|
+
export interface SparkNotification {
|
|
14
|
+
id: string;
|
|
15
|
+
title: string;
|
|
16
|
+
body: string | null;
|
|
17
|
+
/**
|
|
18
|
+
* The link, when the row carries it. `Url` is a detail-only attribute in the shipped model, so a row
|
|
19
|
+
* usually does not, and {@link SparkNotificationsService.open} loads it from the object instead.
|
|
20
|
+
*/
|
|
21
|
+
url: string | null;
|
|
22
|
+
isRead: boolean;
|
|
23
|
+
createdAt: Date | null;
|
|
24
|
+
}
|
|
25
|
+
/** A query row of `MyNotifications` as a {@link SparkNotification}. */
|
|
26
|
+
export declare function toSparkNotification(item: QueryResultItem): SparkNotification;
|
|
27
|
+
/** Options of the notification bell and service. */
|
|
28
|
+
export interface SparkNotificationsOptions {
|
|
29
|
+
/** How many of the latest notifications the bell lists. Default 8. */
|
|
30
|
+
recentCount: number;
|
|
31
|
+
/** Where "All notifications" goes: a router link. Default `['/query', 'notifications']` (the `MyNotifications` alias). */
|
|
32
|
+
listLink: string | readonly unknown[];
|
|
33
|
+
}
|
|
34
|
+
export declare const SPARK_NOTIFICATIONS_OPTIONS: InjectionToken<SparkNotificationsOptions>;
|
|
35
|
+
/** Overrides {@link SparkNotificationsOptions}; anything left out keeps its default. */
|
|
36
|
+
export declare function provideSparkNotifications(options?: Partial<SparkNotificationsOptions>): Provider;
|
|
37
|
+
/** The browser's Notification API, as far as push needs it. */
|
|
38
|
+
export interface SparkNotificationPermissions {
|
|
39
|
+
readonly permission: NotificationPermission;
|
|
40
|
+
requestPermission(): Promise<NotificationPermission>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* What the browser offers for Web Push: the Notification API, or `null` when there is no Notification,
|
|
44
|
+
* no `PushManager` or no service worker. That is the case in Safari on iPhone and iPad until the app is
|
|
45
|
+
* added to the Home Screen, so `null` reads as "install the app first". Replaceable for tests.
|
|
46
|
+
*/
|
|
47
|
+
export declare const SPARK_PUSH_PERMISSIONS: InjectionToken<SparkNotificationPermissions | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Web Push on this device: `unsupported` (no service worker, no PushManager or no Notification API:
|
|
50
|
+
* an iPhone/iPad needs the app on its Home Screen), `denied` (blocked in the browser's settings),
|
|
51
|
+
* `off` or `on`.
|
|
52
|
+
*/
|
|
53
|
+
export type SparkPushState = 'unsupported' | 'denied' | 'off' | 'on';
|
|
54
|
+
/**
|
|
55
|
+
* The client of `MintPlayer.Spark.Notifications` (`docs/seo_analyzer_PRD.md` X10, D20, D30).
|
|
56
|
+
*
|
|
57
|
+
* - **In-app**: {@link unreadCount} and {@link recent} follow the live queries `UnreadNotifications`
|
|
58
|
+
* (one row, for its `totalItems`) and `MyNotifications` (the latest few) over the ONE `/spark/live`
|
|
59
|
+
* socket of {@link SparkLiveService}. Nothing polls and there is no second channel: a new, read or
|
|
60
|
+
* deleted notification arrives as a patch. The subscriptions start again whenever `SPARK_AUTH_STATE`
|
|
61
|
+
* changes (sign-in, sign-out), so a page opened before signing in still counts afterwards.
|
|
62
|
+
* - **Web Push**: {@link enablePush} / {@link disablePush} subscribe this device through Angular's
|
|
63
|
+
* `SwPush` and register it at `/spark/notifications/push/*`. It needs `provideSparkServiceWorker()`
|
|
64
|
+
* (or `provideServiceWorker`) with the worker enabled; without it {@link pushState} is `unsupported`.
|
|
65
|
+
*/
|
|
66
|
+
export declare class SparkNotificationsService {
|
|
67
|
+
private readonly http;
|
|
68
|
+
private readonly live;
|
|
69
|
+
private readonly spark;
|
|
70
|
+
private readonly router;
|
|
71
|
+
private readonly location;
|
|
72
|
+
private readonly document;
|
|
73
|
+
private readonly swPush;
|
|
74
|
+
private readonly permissions;
|
|
75
|
+
private readonly options;
|
|
76
|
+
private readonly baseUrl;
|
|
77
|
+
private readonly browser;
|
|
78
|
+
private readonly unread;
|
|
79
|
+
private readonly latest;
|
|
80
|
+
/** Unread notifications of the signed-in user; 0 until the first result and while signed out. */
|
|
81
|
+
readonly unreadCount: Signal<number>;
|
|
82
|
+
/** The latest notifications (read or not), newest first; empty until the first result. */
|
|
83
|
+
readonly recent: Signal<SparkNotification[]>;
|
|
84
|
+
/** Whether {@link recent} holds a result yet. */
|
|
85
|
+
readonly loaded: Signal<boolean>;
|
|
86
|
+
/** Whether this browser can receive Web Push here at all (see {@link SparkPushState}). */
|
|
87
|
+
readonly pushSupported: boolean;
|
|
88
|
+
private readonly permission;
|
|
89
|
+
private readonly subscribed;
|
|
90
|
+
private readonly configured;
|
|
91
|
+
private readonly busy;
|
|
92
|
+
private publicKey;
|
|
93
|
+
/** Web Push on this device. */
|
|
94
|
+
readonly pushState: Signal<SparkPushState>;
|
|
95
|
+
/**
|
|
96
|
+
* Whether the server sends Web Push (`GET /spark/notifications/push/key` answered a key): `null` while
|
|
97
|
+
* unknown, `false` when Web Push is not configured or nobody is signed in. Offer no push UI unless `true`.
|
|
98
|
+
*/
|
|
99
|
+
readonly pushConfigured: Signal<boolean | null>;
|
|
100
|
+
/** True while {@link enablePush} or {@link disablePush} runs. */
|
|
101
|
+
readonly pushBusy: Signal<boolean>;
|
|
102
|
+
constructor();
|
|
103
|
+
/**
|
|
104
|
+
* Marks notifications read: the given ids, or every unread one of the caller when `ids` is omitted.
|
|
105
|
+
* Resolves to how many changed. The live queries then deliver the new state; nothing is set locally.
|
|
106
|
+
*/
|
|
107
|
+
markRead(ids?: readonly string[]): Promise<number>;
|
|
108
|
+
/**
|
|
109
|
+
* Opens a notification: marks it read when it is not, then follows its link, in-app through the router
|
|
110
|
+
* for a URL on this origin, as a page load for another `http(s)` URL. A row without its `Url` (a
|
|
111
|
+
* detail-only attribute in the shipped model) is loaded once for it.
|
|
112
|
+
*/
|
|
113
|
+
open(notification: SparkNotification): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* Turns Web Push on for this device. Call it straight from a click handler: the permission prompt is
|
|
116
|
+
* requested before anything is awaited, because Safari only grants it to a user gesture. Resolves to
|
|
117
|
+
* whether the device is now subscribed; a refusal, a missing key or a subscription the server rejects
|
|
118
|
+
* (400: a push service outside its allow-list) is `false`.
|
|
119
|
+
*/
|
|
120
|
+
enablePush(): Promise<boolean>;
|
|
121
|
+
/** Turns Web Push off for this device: the server forgets it, then the browser unsubscribes. */
|
|
122
|
+
disablePush(): Promise<void>;
|
|
123
|
+
private follow;
|
|
124
|
+
private loadPublicKey;
|
|
125
|
+
private loadUrl;
|
|
126
|
+
private navigate;
|
|
127
|
+
/** A full page load (overridden in specs: jsdom cannot navigate). */
|
|
128
|
+
protected assign(href: string): void;
|
|
129
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkNotificationsService, never>;
|
|
130
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
131
|
+
}
|
|
132
|
+
/** English fallbacks of `notifications.spa.*`, shown until the server's translations arrive. */
|
|
133
|
+
export declare const SPARK_NOTIFICATION_TEXTS: Record<string, string>;
|
|
134
|
+
/**
|
|
135
|
+
* The Web Push opt-in for this device, on its own (an account or settings page); the notification bell
|
|
136
|
+
* shows the same control. Renders nothing unless the server sends Web Push. Otherwise: a button to turn
|
|
137
|
+
* it on or off, or why it cannot be (blocked in the browser, or a browser without push: on iPhone and
|
|
138
|
+
* iPad the app must be on the Home Screen first).
|
|
139
|
+
*/
|
|
140
|
+
export declare class SparkPushToggleComponent {
|
|
141
|
+
protected readonly notifications: SparkNotificationsService;
|
|
142
|
+
private readonly language;
|
|
143
|
+
protected t(key: string): string;
|
|
144
|
+
/** Synchronous up to the permission prompt: this is the click handler the prompt needs. */
|
|
145
|
+
protected enable(): void;
|
|
146
|
+
protected disable(): void;
|
|
147
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkPushToggleComponent, never>;
|
|
148
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkPushToggleComponent, "spark-push-toggle", never, {}, {}, never, never, true, never>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* The notification bell for an app's top bar (`docs/seo_analyzer_PRD.md` X10): the unread count as a
|
|
152
|
+
* badge, live; a menu with the latest notifications (title, message, relative time), "Mark all as read",
|
|
153
|
+
* a link to the full list and, where this browser can receive it, the Web Push opt-in. Choosing a
|
|
154
|
+
* notification marks it read and follows its link.
|
|
155
|
+
*/
|
|
156
|
+
export declare class SparkNotificationBellComponent {
|
|
157
|
+
protected readonly notifications: SparkNotificationsService;
|
|
158
|
+
private readonly language;
|
|
159
|
+
private readonly options;
|
|
160
|
+
protected readonly colors: typeof Color;
|
|
161
|
+
/** Where "All notifications" goes. Default: `provideSparkNotifications({ listLink })`, else the `notifications` query page. */
|
|
162
|
+
readonly allLink: import("@angular/core").InputSignal<string | readonly unknown[] | null>;
|
|
163
|
+
readonly open: import("@angular/core").WritableSignal<boolean>;
|
|
164
|
+
protected readonly listLink: import("@angular/core").Signal<string | readonly unknown[]>;
|
|
165
|
+
protected readonly countText: import("@angular/core").Signal<string>;
|
|
166
|
+
protected readonly ariaLabel: import("@angular/core").Signal<string>;
|
|
167
|
+
readonly positions: ConnectedPosition[];
|
|
168
|
+
protected t(key: string): string;
|
|
169
|
+
protected when(notification: SparkNotification): string;
|
|
170
|
+
close(): void;
|
|
171
|
+
/** A click outside closes the menu, except on the bell itself, whose own handler toggles it. */
|
|
172
|
+
onOutsideClick(event: MouseEvent, toggle: HTMLElement): void;
|
|
173
|
+
choose(notification: SparkNotification): Promise<void>;
|
|
174
|
+
markAllRead(): Promise<void>;
|
|
175
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkNotificationBellComponent, never>;
|
|
176
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkNotificationBellComponent, "spark-notification-bell", never, {
|
|
177
|
+
"allLink": {
|
|
178
|
+
"alias": "allLink";
|
|
179
|
+
"required": false;
|
|
180
|
+
"isSignal": true;
|
|
181
|
+
};
|
|
182
|
+
}, {}, never, never, true, never>;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* `date` relative to `now` in `language` ("5 minutes ago", "il y a 5 minutes", "5 minuten geleden"),
|
|
186
|
+
* through `Intl.RelativeTimeFormat`; "now" under a minute. Empty for a missing date.
|
|
187
|
+
*/
|
|
188
|
+
export declare function sparkRelativeTime(date: Date | null | undefined, now: number, language: string): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/** What `POST /spark/organizations/accept` answers. */
|
|
4
|
+
export interface SparkOrganizationAcceptance {
|
|
5
|
+
accepted: boolean;
|
|
6
|
+
organizationId: string | null;
|
|
7
|
+
organization: string | null;
|
|
8
|
+
problem: string | null;
|
|
9
|
+
/** Which refusal: `invalid` (any unknown, used or expired link) or `otherAddress` (D43). */
|
|
10
|
+
reason?: 'invalid' | 'otherAddress' | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The target of a mailed organization invitation or join request
|
|
14
|
+
* (`/organizations/accept/:token?id=<invitationId>`, `docs/seo_analyzer_PRD.md` D18). Accepting is an
|
|
15
|
+
* explicit click, never a side effect of opening the link (mail scanners open links). An invitation
|
|
16
|
+
* makes the signed-in account a member; a join request lets its requester in and needs an Owner or
|
|
17
|
+
* Admin. Every failure reads the same, except a valid invitation opened by an account that does not own
|
|
18
|
+
* the invited address (D43): the page says so, so the user can sign in with the right account.
|
|
19
|
+
*/
|
|
20
|
+
export declare class SparkAcceptOrganizationInvitationComponent {
|
|
21
|
+
private readonly http;
|
|
22
|
+
private readonly route;
|
|
23
|
+
private readonly translations;
|
|
24
|
+
protected readonly colors: typeof Color;
|
|
25
|
+
private readonly token;
|
|
26
|
+
private readonly invitationId;
|
|
27
|
+
/** A link without both values cannot be an invitation. */
|
|
28
|
+
protected readonly valid: boolean;
|
|
29
|
+
readonly busy: import("@angular/core").WritableSignal<boolean>;
|
|
30
|
+
readonly failed: import("@angular/core").WritableSignal<boolean>;
|
|
31
|
+
/** The refusal to show: a translation key under `organizations.spa`. */
|
|
32
|
+
readonly reason: import("@angular/core").WritableSignal<"invalid" | "otherAddress">;
|
|
33
|
+
/** The organization joined, once accepted. */
|
|
34
|
+
readonly joined: import("@angular/core").WritableSignal<SparkOrganizationAcceptance | null>;
|
|
35
|
+
/** The page's texts: `organizations.spa.*` in the organizations library's `translations.json`. */
|
|
36
|
+
protected t(key: string): string;
|
|
37
|
+
accept(): Promise<void>;
|
|
38
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkAcceptOrganizationInvitationComponent, never>;
|
|
39
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkAcceptOrganizationInvitationComponent, "spark-accept-organization-invitation", never, {}, {}, never, never, true, never>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { CanActivateFn } from "@angular/router";
|
|
2
|
+
import { SparkAuthRouteEntry } from "@mintplayer/ng-spark/auth/models";
|
|
3
|
+
import { SparkAuthRoutesFeature } from "@mintplayer/ng-spark/auth/routes";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import { OnInit } from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* The organizations package's one SPA page (`docs/seo_analyzer_PRD.md` X11): the target of a mailed
|
|
8
|
+
* invitation or join request, `organizations/accept/:token?id=<invitationId>`, as a `sparkAuthRoutes()`
|
|
9
|
+
* feature:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* sparkAuthRoutes(withExternalLogin(), withAccount(), withOrganizationRoutes())
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* The page needs a signed-in user: the guard (default `[sparkAuthGuard]`) sends everyone else to the
|
|
16
|
+
* sign-in page and back. Organizations, members and invitations themselves are the generic `po/:type`
|
|
17
|
+
* and `query/:id` screens. Moving the page means setting `Spark:Organizations:AcceptPath` to match, so
|
|
18
|
+
* the mailed links follow.
|
|
19
|
+
*/
|
|
20
|
+
export declare function withOrganizationRoutes(options?: {
|
|
21
|
+
canActivate?: CanActivateFn[];
|
|
22
|
+
accept?: SparkAuthRouteEntry;
|
|
23
|
+
}): SparkAuthRoutesFeature;
|
|
24
|
+
/** One organization the switcher offers (`GET /spark/organizations/current`). */
|
|
25
|
+
export interface SparkOrganizationChoice {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
isPersonal: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** What `/spark/organizations/current` answers: the chosen organization (`null`: all of them) and the caller's organizations. */
|
|
31
|
+
export interface SparkCurrentOrganization {
|
|
32
|
+
current: string | null;
|
|
33
|
+
organizations: SparkOrganizationChoice[];
|
|
34
|
+
}
|
|
35
|
+
/** English fallbacks of the switcher's texts (`organizations.spa.*` in the organizations package's translations). */
|
|
36
|
+
export declare const SPARK_ORGANIZATION_SWITCHER_TEXTS: Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* The organization switcher for an app's top bar (`docs/seo_analyzer_PRD.md` Q-M11a): "All organizations" or one
|
|
39
|
+
* of the caller's organizations. The server keeps the choice (a cookie it checks against the caller's memberships
|
|
40
|
+
* on every request), lists of organization-owned rows show only the chosen organization's, and a new row whose
|
|
41
|
+
* form names no organization lands in it. A detail page, a sub-query and the organization list are not narrowed.
|
|
42
|
+
*
|
|
43
|
+
* ```html
|
|
44
|
+
* @if (auth.isAuthenticated()) { <spark-organization-switcher /> }
|
|
45
|
+
* ```
|
|
46
|
+
*
|
|
47
|
+
* Renders nothing for a user in one organization (or none), so it can sit in the top bar unconditionally. A
|
|
48
|
+
* choice reloads the page (`reloadOnChange`), so every grid, live list and cached page reads the new scope.
|
|
49
|
+
*/
|
|
50
|
+
export declare class SparkOrganizationSwitcherComponent implements OnInit {
|
|
51
|
+
private readonly http;
|
|
52
|
+
private readonly language;
|
|
53
|
+
private readonly document;
|
|
54
|
+
/** Reload the page after a choice, so every list reads the new scope. Default true. */
|
|
55
|
+
readonly reloadOnChange: import("@angular/core").InputSignal<boolean>;
|
|
56
|
+
readonly state: import("@angular/core").WritableSignal<SparkCurrentOrganization | null>;
|
|
57
|
+
readonly busy: import("@angular/core").WritableSignal<boolean>;
|
|
58
|
+
ngOnInit(): Promise<void>;
|
|
59
|
+
protected t(key: string): string;
|
|
60
|
+
protected label(organization: SparkOrganizationChoice): string;
|
|
61
|
+
/** Reloads the page; a seam for tests. */
|
|
62
|
+
protected reload(): void;
|
|
63
|
+
choose(organizationId: string | null): Promise<void>;
|
|
64
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkOrganizationSwitcherComponent, never>;
|
|
65
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SparkOrganizationSwitcherComponent, "spark-organization-switcher", never, {
|
|
66
|
+
"reloadOnChange": {
|
|
67
|
+
"alias": "reloadOnChange";
|
|
68
|
+
"required": false;
|
|
69
|
+
"isSignal": true;
|
|
70
|
+
};
|
|
71
|
+
}, {}, never, never, true, never>;
|
|
72
|
+
}
|
|
@@ -119,6 +119,22 @@ export interface SparkQueryRowAction {
|
|
|
119
119
|
export declare const SPARK_QUERY_ROW_ACTIONS: InjectionToken<SparkQueryRowAction[]>;
|
|
120
120
|
/** Registers grid row actions (multi — every call adds). */
|
|
121
121
|
export declare function provideSparkQueryRowActions(...actions: SparkQueryRowAction[]): Provider[];
|
|
122
|
+
/**
|
|
123
|
+
* A layout that draws a detail page's attributes in place of the tabs and cards (#504), for objects it
|
|
124
|
+
* `matches`: Dashboards' tile layout for objects carrying `metadata.dashboard`. It must declare
|
|
125
|
+
* `context = input.required<SparkDetailContext>()`. The action bar, sub-queries, the extra content
|
|
126
|
+
* template and the detail panels stay; the first matching layout wins.
|
|
127
|
+
*/
|
|
128
|
+
export interface SparkDetailLayout {
|
|
129
|
+
id: string;
|
|
130
|
+
component: Type<unknown>;
|
|
131
|
+
/** Whether this layout draws `item`. Called on every change of the object, so keep it cheap. */
|
|
132
|
+
matches(item: PersistentObject, entityType: EntityType): boolean;
|
|
133
|
+
}
|
|
134
|
+
/** Multi-provider: layouts that replace the attribute cards of the routed detail page for the objects they match. */
|
|
135
|
+
export declare const SPARK_DETAIL_LAYOUTS: InjectionToken<SparkDetailLayout[]>;
|
|
136
|
+
/** Registers detail layouts (multi — every call adds). */
|
|
137
|
+
export declare function provideSparkDetailLayouts(...layouts: SparkDetailLayout[]): Provider[];
|
|
122
138
|
/** Multi-provider: panels under the attributes of the routed detail page. */
|
|
123
139
|
export declare const SPARK_DETAIL_PANELS: InjectionToken<SparkDetailPanel[]>;
|
|
124
140
|
/** Multi-provider: extra buttons in the routed detail page's action bar. */
|
|
@@ -46,6 +46,16 @@ export declare class AttributeValuePipe implements PipeTransform {
|
|
|
46
46
|
static ɵfac: i0.ɵɵFactoryDeclaration<AttributeValuePipe, never>;
|
|
47
47
|
static ɵpipe: i0.ɵɵPipeDeclaration<AttributeValuePipe, "attributeValue", true>;
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* A displayed value, or `-` when there is none: `null`, `undefined` or an empty (or blank) string. Unlike
|
|
51
|
+
* `value || '-'` it keeps the falsy values that are data: the number `0` (a page at depth 0, a count of 0) and `false`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function sparkOrDash(value: unknown): unknown;
|
|
54
|
+
export declare class OrDashPipe implements PipeTransform {
|
|
55
|
+
transform(value: unknown): unknown;
|
|
56
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<OrDashPipe, never>;
|
|
57
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<OrDashPipe, "orDash", true>;
|
|
58
|
+
}
|
|
49
59
|
export declare class RawAttributeValuePipe implements PipeTransform {
|
|
50
60
|
transform(attrName: string, item: PersistentObject | null): any;
|
|
51
61
|
static ɵfac: i0.ɵɵFactoryDeclaration<RawAttributeValuePipe, never>;
|
|
@@ -12,6 +12,7 @@ export declare class SparkPoDetailComponent {
|
|
|
12
12
|
private readonly returnNavigation;
|
|
13
13
|
private readonly queryRefresh;
|
|
14
14
|
private readonly attributeRefresh;
|
|
15
|
+
private readonly live;
|
|
15
16
|
protected readonly lang: SparkLanguageService;
|
|
16
17
|
private readonly clientMethods;
|
|
17
18
|
protected readonly rendererRegistry: import("@mintplayer/ng-spark/renderers").SparkAttributeRendererRegistration[];
|
|
@@ -22,6 +23,7 @@ export declare class SparkPoDetailComponent {
|
|
|
22
23
|
*/
|
|
23
24
|
protected readonly detailPanels: import("@mintplayer/ng-spark/panels").SparkDetailPanel[];
|
|
24
25
|
protected readonly detailActions: import("@mintplayer/ng-spark/panels").SparkDetailAction[];
|
|
26
|
+
private readonly detailLayouts;
|
|
25
27
|
showCustomActions: import("@angular/core").InputSignal<boolean>;
|
|
26
28
|
extraActionsTemplate: import("@angular/core").InputSignal<TemplateRef<void> | null>;
|
|
27
29
|
extraContentTemplate: import("@angular/core").InputSignal<TemplateRef<{
|
|
@@ -45,12 +47,17 @@ export declare class SparkPoDetailComponent {
|
|
|
45
47
|
queryActionsTemplate: import("@angular/core").InputSignal<TemplateRef<any> | null>;
|
|
46
48
|
edited: import("@angular/core").OutputEmitterRef<void>;
|
|
47
49
|
deleted: import("@angular/core").OutputEmitterRef<void>;
|
|
50
|
+
/** After an action succeeded; `result` is what it handed to `CustomActionArgs.SetResult` (a download url, a new id). */
|
|
48
51
|
customActionExecuted: import("@angular/core").OutputEmitterRef<{
|
|
49
52
|
action: CustomActionDefinition;
|
|
50
53
|
item: PersistentObject;
|
|
54
|
+
result?: unknown;
|
|
51
55
|
}>;
|
|
52
56
|
colors: typeof Color;
|
|
57
|
+
/** The page could not be loaded: shown instead of the page. */
|
|
53
58
|
errorMessage: import("@angular/core").WritableSignal<string | null>;
|
|
59
|
+
/** A custom action failed or was refused: shown above the page, which stays (it used to replace the page). */
|
|
60
|
+
actionError: import("@angular/core").WritableSignal<string | null>;
|
|
54
61
|
entityType: import("@angular/core").WritableSignal<EntityType | null>;
|
|
55
62
|
/** The sub-queries rendered as cards below the form, in object form (#460, D17). */
|
|
56
63
|
protected readonly subQueries: import("@angular/core").Signal<import("@mintplayer/ng-spark/models").SparkSubQuery[]>;
|
|
@@ -80,6 +87,8 @@ export declare class SparkPoDetailComponent {
|
|
|
80
87
|
protected readonly isDeletedView: import("@angular/core").Signal<boolean>;
|
|
81
88
|
/** What every add-on panel and action receives; rebuilt whenever the object or rights change. */
|
|
82
89
|
protected readonly detailContext: import("@angular/core").Signal<SparkDetailContext | null>;
|
|
90
|
+
/** The registered layout that draws this object's attributes instead of the tabs (#504), if one matches. */
|
|
91
|
+
protected readonly detailLayout: import("@angular/core").Signal<import("@mintplayer/ng-spark/panels").SparkDetailLayout | null>;
|
|
83
92
|
/**
|
|
84
93
|
* The actions actually offered for the object on screen.
|
|
85
94
|
*
|
|
@@ -96,6 +105,21 @@ export declare class SparkPoDetailComponent {
|
|
|
96
105
|
*/
|
|
97
106
|
visibleCustomActions: import("@angular/core").Signal<CustomActionDefinition[]>;
|
|
98
107
|
constructor();
|
|
108
|
+
/** The live subscription of the object on screen, while its type is live; keyed so a reload keeps it. */
|
|
109
|
+
private liveSubscription;
|
|
110
|
+
private liveKey;
|
|
111
|
+
/** The catalogue and rights of the last load, so a pushed object re-derives its Edit/Delete/actions. */
|
|
112
|
+
private loadedActions;
|
|
113
|
+
/**
|
|
114
|
+
* Follows the object when its type is live: every push replaces the shown object and re-derives Edit,
|
|
115
|
+
* Delete and the custom actions from its own `can`/`disabledActions`, as a load does. `gone` (deleted, or
|
|
116
|
+
* no longer readable — one answer) shows the unavailable state. A subscription `error` stops following
|
|
117
|
+
* and keeps the loaded object: the page still shows what the HTTP load returned.
|
|
118
|
+
*/
|
|
119
|
+
private follow;
|
|
120
|
+
private stopFollowing;
|
|
121
|
+
/** The translation, or `fallback` while the key has none (`t` echoes a missing key). */
|
|
122
|
+
private translateOr;
|
|
99
123
|
/**
|
|
100
124
|
* Applies patched attribute values in place, without a re-fetch.
|
|
101
125
|
*
|
|
@@ -109,6 +133,11 @@ export declare class SparkPoDetailComponent {
|
|
|
109
133
|
private loadItem;
|
|
110
134
|
/** (Re)loads the object, its type, rights and actions. Also what add-ons call via `context.reload()`. */
|
|
111
135
|
load(): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Edit, Delete and the custom actions for `item`, from the last load's catalogue and rights: on a load,
|
|
138
|
+
* and again on every live push, since `can` and `disabledActions` travel with the object.
|
|
139
|
+
*/
|
|
140
|
+
private deriveActions;
|
|
112
141
|
/**
|
|
113
142
|
* Drawn from the loaded object's own `showedOn`, falling back to the model's (#264, G-Q3): an action sets
|
|
114
143
|
* it per object in `OnLoadAsync` — a stolen car's police report number is shown, the model says `None`.
|
|
@@ -133,6 +133,7 @@ export declare class SparkPoEditComponent {
|
|
|
133
133
|
private readonly route;
|
|
134
134
|
private readonly router;
|
|
135
135
|
private readonly sparkService;
|
|
136
|
+
private readonly live;
|
|
136
137
|
private readonly language;
|
|
137
138
|
/** `SparkConfig.conflictDialog.showChangedBy`: whether the conflict notice may name a user at all. */
|
|
138
139
|
private readonly showChangedBy;
|
|
@@ -186,6 +187,36 @@ export declare class SparkPoEditComponent {
|
|
|
186
187
|
private readonly form;
|
|
187
188
|
private readonly locale;
|
|
188
189
|
constructor();
|
|
190
|
+
private liveSubscription;
|
|
191
|
+
/** The newest version pushed while this form is open; considered whenever the form can take it. */
|
|
192
|
+
private latestPushed;
|
|
193
|
+
/**
|
|
194
|
+
* A newer version someone else saved while the user has unsaved edits: the form is left alone and a
|
|
195
|
+
* banner offers to review it. Null when there is none (or it has been adopted or reviewed).
|
|
196
|
+
*/
|
|
197
|
+
readonly liveTheirs: import("@angular/core").WritableSignal<PersistentObject | null>;
|
|
198
|
+
protected readonly liveChangedText: import("@angular/core").Signal<string>;
|
|
199
|
+
protected readonly liveReviewText: import("@angular/core").Signal<string>;
|
|
200
|
+
/**
|
|
201
|
+
* Watches the object while the form is open, when its type is live. A newer version (another etag) is
|
|
202
|
+
* adopted silently while the form is untouched — base and form replaced, so the next save posts the new
|
|
203
|
+
* etag — and only offered (banner, then the three-way merge) once the user has edited. `gone` reads as a
|
|
204
|
+
* 409 `deleted`. The 409 on save stays the server-side guarantee; this only brings it forward.
|
|
205
|
+
*/
|
|
206
|
+
private follow;
|
|
207
|
+
private stopFollowing;
|
|
208
|
+
/** Adopts the latest pushed version when the form is clean, or offers it when the form is dirty. */
|
|
209
|
+
private considerLivePush;
|
|
210
|
+
/** Whether the form holds edits: it differs from the object it was built from. */
|
|
211
|
+
isDirty(): boolean;
|
|
212
|
+
/**
|
|
213
|
+
* The banner's Review: the existing three-way merge of the loaded base, the user's edits and the pushed
|
|
214
|
+
* version. Nothing conflicts → applied, and their etag adopted; conflicts → the conflict dialog. Nothing
|
|
215
|
+
* is saved either way.
|
|
216
|
+
*/
|
|
217
|
+
reviewLiveChange(): void;
|
|
218
|
+
/** The translation, or `fallback` while the key has none (`t` echoes a missing key). */
|
|
219
|
+
private translateOr;
|
|
189
220
|
private onParamsChange;
|
|
190
221
|
initFormData(): void;
|
|
191
222
|
/**
|
|
@@ -239,6 +270,12 @@ export declare class SparkPoEditComponent {
|
|
|
239
270
|
* reviews and saves, and the server's validation and business rules run again on the result.
|
|
240
271
|
*/
|
|
241
272
|
private resolveConcurrencyConflict;
|
|
273
|
+
/**
|
|
274
|
+
* Merges this form onto `theirs`, three-way against the object as loaded: disjoint edits are applied
|
|
275
|
+
* and their etag adopted (with a notice); true conflicts open the dialog. Shared by the 409 path and
|
|
276
|
+
* the live banner's Review.
|
|
277
|
+
*/
|
|
278
|
+
private mergeWith;
|
|
242
279
|
/**
|
|
243
280
|
* Reference labels for the dialog, by id. The form keeps only ids; the labels are on the two reads
|
|
244
281
|
* (theirs first: it is the fresher) and, for a reference the user just picked, in the candidate
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
import { EnvironmentProviders, InjectionToken } from "@angular/core";
|
|
3
3
|
import { SwRegistrationOptions } from "@angular/service-worker";
|
|
4
|
+
import { Location } from "@angular/common";
|
|
4
5
|
export interface SparkServiceWorkerOptions {
|
|
5
6
|
/** Whether the worker registers. Default: `!isDevMode()`, so only production builds register it. */
|
|
6
7
|
enabled?: boolean;
|
|
@@ -11,7 +12,8 @@ export interface SparkServiceWorkerOptions {
|
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
14
|
* Registers Angular's service worker with Spark's update policy (#464, Q1b); see
|
|
14
|
-
* {@link SparkServiceWorkerUpdates} for what happens when a new version is deployed
|
|
15
|
+
* {@link SparkServiceWorkerUpdates} for what happens when a new version is deployed, and
|
|
16
|
+
* {@link SparkNotificationClicks} for a push notification clicked while the application is open.
|
|
15
17
|
*
|
|
16
18
|
* The application also needs an `ngsw-config.json` with Spark's navigation exclusions and
|
|
17
19
|
* `serviceWorker` in its production build configuration; see `docs/guide-pwa.md`.
|
|
@@ -86,4 +88,48 @@ export declare class SparkServiceWorkerUpdates {
|
|
|
86
88
|
private writeReloadedFor;
|
|
87
89
|
static ɵfac: i0.ɵɵFactoryDeclaration<SparkServiceWorkerUpdates, never>;
|
|
88
90
|
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
89
|
-
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Notification clicks while the application is open (`docs/seo_analyzer_PRD.md` X10, D30): a click on
|
|
94
|
+
* a push whose `notification.data.url` is on this origin becomes an in-app router navigation, so the
|
|
95
|
+
* page keeps its state instead of loading again.
|
|
96
|
+
*
|
|
97
|
+
* What it does NOT do, because Angular's service worker (ngsw) already does it: show the push, and
|
|
98
|
+
* open the page when the application is closed. The server sends Angular's payload,
|
|
99
|
+
* `{ notification: { title, body, tag, data: { url, notificationId, onActionClick: { default: {
|
|
100
|
+
* operation, url } } } } }`, and ngsw performs `onActionClick.default` itself on the click, then
|
|
101
|
+
* broadcasts the click to the open pages, which is what {@link SwPush.notificationClicks} reports here.
|
|
102
|
+
*
|
|
103
|
+
* ⚠️ The operation decides whether this handler matters. ngsw runs it BEFORE the broadcast:
|
|
104
|
+
* `navigateLastFocusedOrOpen` makes the focused page load the URL in full, so this handler then
|
|
105
|
+
* finds the router already there and does nothing; `focusLastFocusedOrOpen` focuses the open page
|
|
106
|
+
* without loading it (and opens the URL when no page is open), leaving the navigation to this handler.
|
|
107
|
+
*
|
|
108
|
+
* Active only in a browser with the service worker enabled; started by `provideSparkServiceWorker()`.
|
|
109
|
+
*/
|
|
110
|
+
export declare class SparkNotificationClicks {
|
|
111
|
+
private readonly swPush;
|
|
112
|
+
private readonly router;
|
|
113
|
+
private readonly location;
|
|
114
|
+
private readonly document;
|
|
115
|
+
private readonly platformId;
|
|
116
|
+
private readonly destroyRef;
|
|
117
|
+
private started;
|
|
118
|
+
/** Starts listening. Idempotent; called by the app initializer `provideSparkServiceWorker()` adds. */
|
|
119
|
+
start(): void;
|
|
120
|
+
private navigate;
|
|
121
|
+
/** A full page load (overridden in specs: jsdom cannot navigate). */
|
|
122
|
+
protected assign(href: string): void;
|
|
123
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SparkNotificationClicks, never>;
|
|
124
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The router URL for `url` when it points into this application, else `null`.
|
|
128
|
+
*
|
|
129
|
+
* `url` may be app-relative (`/runs/42`) or absolute. It is resolved against the document's base URI;
|
|
130
|
+
* only an `http(s)` URL on the page's own origin is in-app, and its path loses the `<base href>`
|
|
131
|
+
* (through `Location.normalize`) because the router works below it. Everything else (another origin,
|
|
132
|
+
* `javascript:`, `mailto:`, an unparseable value) is `null`, so a caller never hands data-borne URLs
|
|
133
|
+
* to the router or to `location.assign` unchecked.
|
|
134
|
+
*/
|
|
135
|
+
export declare function sparkInAppUrl(url: string | null | undefined, document: Document, location: Location | null): string | null;
|
|
@@ -3,7 +3,7 @@ import { TemplateRef } from "@angular/core";
|
|
|
3
3
|
import { Color } from "@mintplayer/ng-bootstrap";
|
|
4
4
|
import { SparkLanguageService } from "@mintplayer/ng-spark/services";
|
|
5
5
|
import { SparkQueryToolbarAction } from "@mintplayer/ng-spark/grid";
|
|
6
|
-
import { CustomActionDefinition,
|
|
6
|
+
import { CustomActionDefinition, QueryColumnFilter, QueryResultItem, SparkDeletedFilter, SparkSelectionModeSetting } from "@mintplayer/ng-spark/models";
|
|
7
7
|
import { SparkQueryListContext } from "@mintplayer/ng-spark/panels";
|
|
8
8
|
/**
|
|
9
9
|
* The routed query page: chrome around one {@link SparkQueryGridComponent}.
|
|
@@ -14,9 +14,11 @@ import { SparkQueryListContext } from "@mintplayer/ng-spark/panels";
|
|
|
14
14
|
* routes — `query/:queryId`, and `po/:type`, which resolves an entity type to a query. That
|
|
15
15
|
* second one is type-to-query resolution, not query rendering, and is why this component still
|
|
16
16
|
* exists rather than the router pointing at the grid.
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* - The action bar, the caption, the LIVE badge (the grid's `isLive()`), the search box and the
|
|
18
|
+
* New button.
|
|
19
|
+
*
|
|
20
|
+
* Live updates are the grid's (X4): a live query is followed by `spark-query-grid` itself, with
|
|
21
|
+
* server-side paging, sort and search, so every embedded grid follows it too — not only this page.
|
|
20
22
|
*
|
|
21
23
|
* The grid itself — columns, cells, paging, the row link, selection, custom-action execution —
|
|
22
24
|
* is the shared component. This page previously wrote out `<bs-datatable>` twice, once per
|
|
@@ -26,8 +28,6 @@ export declare class SparkQueryListComponent {
|
|
|
26
28
|
private readonly route;
|
|
27
29
|
private readonly router;
|
|
28
30
|
private readonly sparkService;
|
|
29
|
-
private readonly streamingService;
|
|
30
|
-
private readonly destroyRef;
|
|
31
31
|
protected readonly lang: SparkLanguageService;
|
|
32
32
|
extraActionsTemplate: import("@angular/core").InputSignal<TemplateRef<void> | null>;
|
|
33
33
|
showCustomActions: import("@angular/core").InputSignal<boolean>;
|
|
@@ -65,6 +65,8 @@ export declare class SparkQueryListComponent {
|
|
|
65
65
|
protected readonly resultCount: import("@angular/core").Signal<number | null>;
|
|
66
66
|
protected readonly isVirtualScrolling: import("@angular/core").Signal<boolean>;
|
|
67
67
|
protected readonly gridError: import("@angular/core").Signal<string | null>;
|
|
68
|
+
/** Whether the grid follows the query over `/spark/live` right now: the LIVE badge. */
|
|
69
|
+
protected readonly isLive: import("@angular/core").Signal<boolean>;
|
|
68
70
|
protected readonly permissions: import("@angular/core").Signal<import("@mintplayer/ng-spark/models").EntityPermissions | null>;
|
|
69
71
|
/** Add-on buttons for the action bar (#460, `SPARK_QUERY_LIST_ACTIONS`), e.g. the Deleted toggle. */
|
|
70
72
|
protected readonly listActions: import("@mintplayer/ng-spark/panels").SparkQueryListAction[];
|
|
@@ -89,19 +91,6 @@ export declare class SparkQueryListComponent {
|
|
|
89
91
|
protected toolbarActionUnavailableReason(action: SparkQueryToolbarAction): string | null;
|
|
90
92
|
protected runToolbarAction(action: SparkQueryToolbarAction): void;
|
|
91
93
|
protected isActionEnabled(action: CustomActionDefinition): boolean;
|
|
92
|
-
isStreaming: import("@angular/core").WritableSignal<boolean>;
|
|
93
|
-
private streamingSub;
|
|
94
|
-
/** Columns as sent with the stream's snapshot; empty until it arrives. */
|
|
95
|
-
protected readonly streamColumns: import("@angular/core").WritableSignal<QueryColumn[]>;
|
|
96
|
-
private readonly allItems;
|
|
97
|
-
private readonly streamItems;
|
|
98
|
-
/**
|
|
99
|
-
* Rows handed to the grid, or `null` to let it fetch for itself.
|
|
100
|
-
*
|
|
101
|
-
* Null for a normal query — an empty array would read as "here are no rows" and suppress the
|
|
102
|
-
* fetch entirely.
|
|
103
|
-
*/
|
|
104
|
-
protected readonly gridData: import("@angular/core").Signal<QueryResultItem[] | null>;
|
|
105
94
|
constructor();
|
|
106
95
|
/**
|
|
107
96
|
* The parent the URL scopes the query to (`?parentId=…&parentType=…`), sent exactly as a sub-query
|
|
@@ -138,10 +127,6 @@ export declare class SparkQueryListComponent {
|
|
|
138
127
|
protected onCustomAction(action: CustomActionDefinition): Promise<void>;
|
|
139
128
|
protected onCreate(): void;
|
|
140
129
|
protected clearSearch(): void;
|
|
141
|
-
private connectStreaming;
|
|
142
|
-
private disconnectStreaming;
|
|
143
|
-
private handleStreamingMessage;
|
|
144
|
-
private applyFilter;
|
|
145
130
|
static ɵfac: i0.ɵɵFactoryDeclaration<SparkQueryListComponent, never>;
|
|
146
131
|
static ɵcmp: i0.ɵɵComponentDeclaration<SparkQueryListComponent, "spark-query-list", never, {
|
|
147
132
|
"extraActionsTemplate": {
|