@zambon-dev/ui 0.0.0-stage → 1.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/CHANGELOG.md +2329 -0
- package/README.md +80 -2
- package/fesm2022/zambon-dev-ui-framework.mjs +5960 -0
- package/fesm2022/zambon-dev-ui-framework.mjs.map +1 -0
- package/fesm2022/zambon-dev-ui-library.mjs +5795 -0
- package/fesm2022/zambon-dev-ui-library.mjs.map +1 -0
- package/fesm2022/zambon-dev-ui-shared.mjs +2517 -0
- package/fesm2022/zambon-dev-ui-shared.mjs.map +1 -0
- package/fesm2022/zambon-dev-ui-testing.mjs +76 -0
- package/fesm2022/zambon-dev-ui-testing.mjs.map +1 -0
- package/fesm2022/zambon-dev-ui.mjs +3 -0
- package/i18n/framework/en.json +63 -0
- package/i18n/framework/pt.json +63 -0
- package/i18n/shared/external-content/en.json +12 -0
- package/i18n/shared/external-content/pt.json +12 -0
- package/i18n/shared/language-selector/en.json +5 -0
- package/i18n/shared/language-selector/pt.json +5 -0
- package/i18n/shared/login/en.json +14 -0
- package/i18n/shared/login/pt.json +14 -0
- package/i18n/shared/operations-history/en.json +5 -0
- package/i18n/shared/operations-history/pt.json +5 -0
- package/i18n/shared/services-history/en.json +14 -0
- package/i18n/shared/services-history/pt.json +14 -0
- package/i18n/shared/top-bar/en.json +7 -0
- package/i18n/shared/top-bar/pt.json +7 -0
- package/package.json +106 -4
- package/styles/common.scss +10 -0
- package/styles/components/button.scss +101 -0
- package/styles/components/card.scss +13 -0
- package/styles/components/dropdown-static.scss +35 -0
- package/styles/components/input-group.scss +44 -0
- package/styles/components/input.scss +99 -0
- package/styles/components/label.scss +3 -0
- package/styles/components/row.scss +48 -0
- package/styles/mixins/background.scss +31 -0
- package/styles/theme.css +75 -0
- package/styles/variables.scss +60 -0
- package/types/zambon-dev-ui-framework.d.ts +1496 -0
- package/types/zambon-dev-ui-library.d.ts +1675 -0
- package/types/zambon-dev-ui-shared.d.ts +675 -0
- package/types/zambon-dev-ui-testing.d.ts +51 -0
- package/types/zambon-dev-ui.d.ts +3 -0
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { AfterViewInit, ElementRef, EnvironmentProviders, InjectionToken, InputSignal, ModelSignal, OnDestroy, OnInit, OutputEmitterRef, PipeTransform, Provider, Signal, WritableSignal } from "@angular/core";
|
|
3
|
+
import * as i1 from "@angular/router";
|
|
4
|
+
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, Routes } from "@angular/router";
|
|
5
|
+
import { HttpBackend, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
|
|
6
|
+
import { Observable, Subject } from "rxjs";
|
|
7
|
+
import { FormBuilder, FormGroup } from "@angular/forms";
|
|
8
|
+
import { AuthService, ButtonFiltersComponent, ChildList, ModalBase, TabViewBase } from "@zambon-dev/ui/framework";
|
|
9
|
+
import { AngularAssetPattern, DataGridDataset, IGridColumn, IListParameters, SidebarMenu } from "@zambon-dev/ui/library";
|
|
10
|
+
import { SafeHtml, SafeResourceUrl } from "@angular/platform-browser";
|
|
11
|
+
import { MultiTranslateHttpLoader, TranslationResource } from "ngx-translate-multi-http-loader";
|
|
12
|
+
export declare class SharedAuthModule {
|
|
13
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SharedAuthModule, never>;
|
|
14
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<SharedAuthModule, never, [typeof i1.RouterModule], never>;
|
|
15
|
+
static ɵinj: i0.ɵɵInjectorDeclaration<SharedAuthModule>;
|
|
16
|
+
}
|
|
17
|
+
export declare class AuthGuard implements CanActivate {
|
|
18
|
+
private authenticationService;
|
|
19
|
+
private router;
|
|
20
|
+
canActivate(_: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean;
|
|
21
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AuthGuard, never>;
|
|
22
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
23
|
+
}
|
|
24
|
+
export declare class AuthInterceptor implements HttpInterceptor {
|
|
25
|
+
private authenticationService;
|
|
26
|
+
private config;
|
|
27
|
+
private jwtInterceptor;
|
|
28
|
+
private refreshToken$?;
|
|
29
|
+
private router;
|
|
30
|
+
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>>;
|
|
31
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AuthInterceptor, never>;
|
|
32
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
33
|
+
}
|
|
34
|
+
export declare abstract class FiltersBase implements OnInit, OnDestroy {
|
|
35
|
+
protected buttonFilters?: ButtonFiltersComponent;
|
|
36
|
+
protected destroy$: Subject<boolean>;
|
|
37
|
+
protected filterForm: FormGroup;
|
|
38
|
+
protected formBuilder: FormBuilder;
|
|
39
|
+
ngOnDestroy(): void;
|
|
40
|
+
ngOnInit(): void;
|
|
41
|
+
setFilters(filters: {
|
|
42
|
+
[key: string]: any;
|
|
43
|
+
}): void;
|
|
44
|
+
protected abstract formSetup(): FormGroup<any>;
|
|
45
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FiltersBase, never>;
|
|
46
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<FiltersBase, "ng-component", never, {}, {}, never, never, true, never>;
|
|
47
|
+
}
|
|
48
|
+
export interface ICurrentUserInfo {
|
|
49
|
+
costCenterName: string;
|
|
50
|
+
/**
|
|
51
|
+
* Optional e-mail address. Present only when the sign-in response includes it; it is one of the
|
|
52
|
+
* values behind the `{email}` placeholder in an external menu URL.
|
|
53
|
+
*/
|
|
54
|
+
email?: string;
|
|
55
|
+
name: string;
|
|
56
|
+
/** Optional avatar image URL. Falls back to initials when absent. */
|
|
57
|
+
pictureUrl?: string;
|
|
58
|
+
/** Optional job position/title shown under the user name. Line is hidden when absent. */
|
|
59
|
+
position?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Optional stable user identifier. Present only when the sign-in response includes it; it is
|
|
62
|
+
* the value behind the `{userId}` placeholder in an external menu URL.
|
|
63
|
+
*/
|
|
64
|
+
userID?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Login user name. Already carried by the persisted sign-in response; declared here because it
|
|
67
|
+
* is the value behind the `{userName}` placeholder in an external menu URL.
|
|
68
|
+
*/
|
|
69
|
+
username?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface IAuthResponse extends ICurrentUserInfo {
|
|
72
|
+
refreshToken: string;
|
|
73
|
+
refreshTokenExpiration: string;
|
|
74
|
+
token: string;
|
|
75
|
+
username: string;
|
|
76
|
+
}
|
|
77
|
+
/** First segment of the route that hosts embedded external content. */
|
|
78
|
+
export declare const EXTERNAL_CONTENT_ROUTE_PATH = "external-content";
|
|
79
|
+
/**
|
|
80
|
+
* Flat projection of an external menu item, used to restore an embedded tab.
|
|
81
|
+
*
|
|
82
|
+
* Deliberately not a `SidebarMenu`: that class carries a `parent` back-reference, so it is a
|
|
83
|
+
* circular structure that `JSON.stringify` refuses, and holding one would pin the whole menu tree.
|
|
84
|
+
*/
|
|
85
|
+
export interface IExternalContentEntry {
|
|
86
|
+
id: number;
|
|
87
|
+
label: string;
|
|
88
|
+
url: string;
|
|
89
|
+
}
|
|
90
|
+
export declare class ExternalContentConfigs {
|
|
91
|
+
/**
|
|
92
|
+
* Origins an embedded menu item may point at, for example `['https://reports.example.com']`.
|
|
93
|
+
* Empty — the default — allows any `http`/`https` origin.
|
|
94
|
+
*
|
|
95
|
+
* Populating it is the single highest-value control here after the scheme check: it narrows a
|
|
96
|
+
* compromised menu row from "frame anything on the internet" to "frame one of our report hosts".
|
|
97
|
+
*/
|
|
98
|
+
allowedOrigins: string[];
|
|
99
|
+
/** Milliseconds to wait for the frame's first `load` before hinting that framing may be refused. */
|
|
100
|
+
slowFrameHintDelay: number;
|
|
101
|
+
constructor(options?: Partial<ExternalContentConfigs>);
|
|
102
|
+
}
|
|
103
|
+
export declare const EXTERNAL_CONTENT_CONFIGS: InjectionToken<ExternalContentConfigs>;
|
|
104
|
+
export interface INotification {
|
|
105
|
+
/** Short heading for the notification. */
|
|
106
|
+
title: string;
|
|
107
|
+
/** Longer descriptive text. */
|
|
108
|
+
description: string;
|
|
109
|
+
/** Icon class shown next to the notification (e.g. a Font Awesome class like `fa-solid fa-envelope`). */
|
|
110
|
+
icon: string;
|
|
111
|
+
/** Optional call-to-action URL. When present, clicking the notification navigates to it. */
|
|
112
|
+
callToActionUrl?: string;
|
|
113
|
+
/** Whether the notification has been read. */
|
|
114
|
+
isRead: boolean;
|
|
115
|
+
}
|
|
116
|
+
export interface IOperationsHistoryList {
|
|
117
|
+
/** Capitalised `ID` is intentional: the backend property is `EntityID`, and the camelCase
|
|
118
|
+
* serialization policy only lowercases a leading run of capitals — so the trailing ones survive. */
|
|
119
|
+
entityID?: number;
|
|
120
|
+
entityName?: string;
|
|
121
|
+
id: number;
|
|
122
|
+
newValues?: string;
|
|
123
|
+
oldValues?: string;
|
|
124
|
+
operationType?: string;
|
|
125
|
+
tableName?: string;
|
|
126
|
+
}
|
|
127
|
+
export interface IServicesHistoryList {
|
|
128
|
+
changedByName: string;
|
|
129
|
+
changedOn: Date;
|
|
130
|
+
id: number;
|
|
131
|
+
name: string;
|
|
132
|
+
}
|
|
133
|
+
export declare class AuthenticationService extends AuthService {
|
|
134
|
+
adminAction: string;
|
|
135
|
+
private config;
|
|
136
|
+
private readonly BASE_URL;
|
|
137
|
+
private http;
|
|
138
|
+
constructor();
|
|
139
|
+
authenticate(model: {
|
|
140
|
+
username: string;
|
|
141
|
+
password: string;
|
|
142
|
+
rememberMe: boolean;
|
|
143
|
+
}): Observable<void>;
|
|
144
|
+
getActions(): Observable<string[]>;
|
|
145
|
+
getUserInfo(): ICurrentUserInfo | null;
|
|
146
|
+
tryRefreshToken(): Observable<string>;
|
|
147
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AuthenticationService, never>;
|
|
148
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Remembers which external destination sits behind an embedded tab's `/external-content/:menuID`
|
|
152
|
+
* route, and resolves it back when the view is created.
|
|
153
|
+
*
|
|
154
|
+
* The destination never travels in the route, so the id has to be resolved to a URL somehow. That
|
|
155
|
+
* happens in three steps, cheapest first:
|
|
156
|
+
*
|
|
157
|
+
* 1. the in-memory registry — the item was clicked in this browsing session;
|
|
158
|
+
* 2. `sessionStorage` — the user pressed F5 on the embedded tab;
|
|
159
|
+
* 3. the application's `SidebarService.getMenuFromUrl()` — a cold deep link.
|
|
160
|
+
*
|
|
161
|
+
* Step 3 reuses the abstract hook every application already implements, so nothing new is required
|
|
162
|
+
* of a consumer: an application whose menu endpoint cannot resolve `/external-content/:id` simply
|
|
163
|
+
* gets the unavailable state on a cold deep link, which is the documented behaviour.
|
|
164
|
+
*/
|
|
165
|
+
export declare class ExternalContentService {
|
|
166
|
+
private readonly maxEntries;
|
|
167
|
+
private readonly storageKey;
|
|
168
|
+
private registry;
|
|
169
|
+
private sidebarService;
|
|
170
|
+
/** Resolves the destination behind an embedded tab, or `undefined` when it cannot be recovered. */
|
|
171
|
+
find(menuID: number): Observable<IExternalContentEntry | undefined>;
|
|
172
|
+
/** Remembers a menu so its embedded tab survives a page refresh. */
|
|
173
|
+
register(menu: SidebarMenu): void;
|
|
174
|
+
private readAllFromStorage;
|
|
175
|
+
private readFromStorage;
|
|
176
|
+
private toEntry;
|
|
177
|
+
private writeToStorage;
|
|
178
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ExternalContentService, never>;
|
|
179
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Resolves the runtime placeholders in an external menu URL, and vets the result before it is
|
|
183
|
+
* handed to the browser.
|
|
184
|
+
*
|
|
185
|
+
* Placeholder syntax is `{name}`, case-sensitive, drawn from a **closed** set:
|
|
186
|
+
*
|
|
187
|
+
* | Token | Source |
|
|
188
|
+
* |--------------|-----------------------------------------------------|
|
|
189
|
+
* | `{email}` | `ICurrentUserInfo.email` |
|
|
190
|
+
* | `{language}` | `TranslateService.currentLang`, then `defaultLang` |
|
|
191
|
+
* | `{userId}` | `ICurrentUserInfo.userID` |
|
|
192
|
+
* | `{userName}` | `ICurrentUserInfo.username` |
|
|
193
|
+
*
|
|
194
|
+
* The set is closed by construction rather than reflected off the stored user info, and that is a
|
|
195
|
+
* security property, not a style choice: `AuthenticationService` persists the entire sign-in
|
|
196
|
+
* response under `userInfo`, tokens included, so a reflective implementation would let a menu URL
|
|
197
|
+
* configured as `?t={token}` hand the JWT to a third party. No authentication token is ever
|
|
198
|
+
* substituted.
|
|
199
|
+
*/
|
|
200
|
+
export declare class ExternalUrlResolverService {
|
|
201
|
+
private authenticationService;
|
|
202
|
+
private translate;
|
|
203
|
+
/** Placeholder grammar, used only to *detect* tokens this version does not know. */
|
|
204
|
+
private readonly unknownPlaceholderPattern;
|
|
205
|
+
/**
|
|
206
|
+
* Whether `url` is an absolute `http`/`https` address.
|
|
207
|
+
*
|
|
208
|
+
* Rejects relative paths, malformed values, protocol-relative `//host/path` (which throws
|
|
209
|
+
* without a base), and the schemes that would execute rather than navigate: `javascript:`,
|
|
210
|
+
* `data:`, `blob:`, `file:`.
|
|
211
|
+
*/
|
|
212
|
+
isAllowed(url: string): boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Substitutes every known placeholder, URL-encoding each value.
|
|
215
|
+
*
|
|
216
|
+
* Because every value is percent-encoded, a placeholder must occupy one *whole* value — a full
|
|
217
|
+
* path segment, or a full query-parameter value. Encoding is what stops a display name that
|
|
218
|
+
* contains `&` from injecting an extra query parameter into the destination.
|
|
219
|
+
*
|
|
220
|
+
* A known placeholder with no value becomes an empty string; an unrecognized `{…}` is left
|
|
221
|
+
* exactly as configured, so a report URL that legitimately contains braces is not corrupted.
|
|
222
|
+
*/
|
|
223
|
+
resolve(url: string): string;
|
|
224
|
+
private getPlaceholderValues;
|
|
225
|
+
private warnAboutUnknownPlaceholders;
|
|
226
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ExternalUrlResolverService, never>;
|
|
227
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Streams top-bar notifications from a SignalR hub.
|
|
231
|
+
*
|
|
232
|
+
* The hub is configured via `AppConfig.notificationsEnabled` and `AppConfig.notificationsUrl`.
|
|
233
|
+
* When enabled, {@link start} opens a connection (authenticated with the current JWT) and
|
|
234
|
+
* listens for the server to push the notification list via the `ReceiveNotifications` client
|
|
235
|
+
* method. Consuming apps do not interact with this service directly — the top bar drives it.
|
|
236
|
+
*/
|
|
237
|
+
export declare class NotificationsService {
|
|
238
|
+
private authService;
|
|
239
|
+
private config;
|
|
240
|
+
private connection?;
|
|
241
|
+
private notifications$;
|
|
242
|
+
/** Whether the notifications feature is enabled (toggled on and given a hub URL). */
|
|
243
|
+
get isEnabled(): boolean;
|
|
244
|
+
/** Emits the current list of notifications. */
|
|
245
|
+
getNotifications(): Observable<INotification[]>;
|
|
246
|
+
/** Emits the number of unread notifications. */
|
|
247
|
+
getUnreadCount(): Observable<number>;
|
|
248
|
+
/** Marks every notification as read and notifies the hub. */
|
|
249
|
+
markAllAsRead(): void;
|
|
250
|
+
/** Marks a single notification as read (optimistically; the server reconciles on the next push). */
|
|
251
|
+
markAsRead(notification: INotification): void;
|
|
252
|
+
/** Opens the SignalR connection and starts receiving notifications. Idempotent and a no-op when disabled. */
|
|
253
|
+
start(): void;
|
|
254
|
+
/** Closes the SignalR connection. */
|
|
255
|
+
stop(): Promise<void>;
|
|
256
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NotificationsService, never>;
|
|
257
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
258
|
+
}
|
|
259
|
+
export declare class OperationsHistoryService {
|
|
260
|
+
private config;
|
|
261
|
+
private http;
|
|
262
|
+
list(controllerName: string, entityID: number, serviceHistoryID: number, parameters: IListParameters): Observable<IOperationsHistoryList[]>;
|
|
263
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<OperationsHistoryService, never>;
|
|
264
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
265
|
+
}
|
|
266
|
+
export declare class ServicesHistoryService {
|
|
267
|
+
private config;
|
|
268
|
+
private http;
|
|
269
|
+
list(controllerName: string, entityID: number, parameters: IListParameters): Observable<IServicesHistoryList[]>;
|
|
270
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ServicesHistoryService, never>;
|
|
271
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
272
|
+
}
|
|
273
|
+
export declare class OperationsHistoryDataset extends DataGridDataset {
|
|
274
|
+
columns: IGridColumn[];
|
|
275
|
+
controllerName?: string;
|
|
276
|
+
protected operationsHistoryService: OperationsHistoryService;
|
|
277
|
+
private _serviceID?;
|
|
278
|
+
set serviceId(value: number | undefined);
|
|
279
|
+
constructor();
|
|
280
|
+
getData(params: IListParameters): Observable<IOperationsHistoryList[]>;
|
|
281
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<OperationsHistoryDataset, never>;
|
|
282
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
283
|
+
}
|
|
284
|
+
export declare class ServicesHistoryDataset extends DataGridDataset {
|
|
285
|
+
columns: IGridColumn[];
|
|
286
|
+
controllerName?: string;
|
|
287
|
+
protected servicesHistoryService: ServicesHistoryService;
|
|
288
|
+
constructor();
|
|
289
|
+
getData(params: IListParameters): Observable<IServicesHistoryList[]>;
|
|
290
|
+
/**
|
|
291
|
+
* Widens the picked dates to whole local days and sends them as UTC instants.
|
|
292
|
+
*
|
|
293
|
+
* A date input yields `YYYY-MM-DD` -- no time, no zone -- while the history stores UTC instants
|
|
294
|
+
* and the backend compares what it is given. Sent as they are, "from the 5th to the 5th" is the
|
|
295
|
+
* single instant at midnight and matches nothing, and in a zone behind UTC it does not even
|
|
296
|
+
* cover the right day.
|
|
297
|
+
*
|
|
298
|
+
* Done here rather than in the filter form because the form is what the modal shows: reopening
|
|
299
|
+
* it patches these values straight back into the fields, which have to keep reading as the dates
|
|
300
|
+
* the person picked. This is the boundary where the request is built, so it is also the last
|
|
301
|
+
* point that sees every caller.
|
|
302
|
+
*/
|
|
303
|
+
private withUtcPeriod;
|
|
304
|
+
/**
|
|
305
|
+
* The UTC wall clock of one end of a local day, written without a zone designator.
|
|
306
|
+
*
|
|
307
|
+
* Without one on purpose. `DateTime.TryParse` on the server reads a trailing `Z` as an instant
|
|
308
|
+
* and hands back the *machine's* local time for it, so the same request would mean different
|
|
309
|
+
* things on a server in UTC and one in UTC-3, and the stored column is plain UTC either way.
|
|
310
|
+
* Dropping the designator leaves the numbers alone, which is what the column holds.
|
|
311
|
+
*/
|
|
312
|
+
private static toUtcInstant;
|
|
313
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ServicesHistoryDataset, never>;
|
|
314
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Displays an external destination inside an application tab.
|
|
318
|
+
*
|
|
319
|
+
* Routed as `/external-content/:menuID` — the destination itself never travels in the URL, so no
|
|
320
|
+
* one can hand-craft a link that makes the application frame an arbitrary site.
|
|
321
|
+
*
|
|
322
|
+
* A `TabViewBase` like any other screen, so its actions live in the ribbon rather than in a
|
|
323
|
+
* bar of its own: it must be routed under `DefaultTabViewComponent`, which is what renders the
|
|
324
|
+
* `#ribbon` template this view publishes. Use the exported `externalContentRoutes`.
|
|
325
|
+
*/
|
|
326
|
+
export declare class ExternalContentComponent extends TabViewBase implements OnInit, OnDestroy {
|
|
327
|
+
protected readonly frameUrl: WritableSignal<SafeResourceUrl | undefined>;
|
|
328
|
+
protected readonly isBlocked: WritableSignal<boolean>;
|
|
329
|
+
protected readonly isFrameLoading: WritableSignal<boolean>;
|
|
330
|
+
protected readonly isInsecure: WritableSignal<boolean>;
|
|
331
|
+
protected readonly isSlow: WritableSignal<boolean>;
|
|
332
|
+
protected readonly isUnavailable: WritableSignal<boolean>;
|
|
333
|
+
protected readonly label: WritableSignal<string>;
|
|
334
|
+
protected readonly resolvedUrl: WritableSignal<string>;
|
|
335
|
+
private activatedRoute;
|
|
336
|
+
private configs;
|
|
337
|
+
private document;
|
|
338
|
+
private externalContentService;
|
|
339
|
+
private externalUrlResolverService;
|
|
340
|
+
private sanitizer;
|
|
341
|
+
private slowHintTimeout?;
|
|
342
|
+
private tabService;
|
|
343
|
+
constructor();
|
|
344
|
+
ngOnDestroy(): void;
|
|
345
|
+
ngOnInit(): void;
|
|
346
|
+
protected onFrameLoad(): void;
|
|
347
|
+
protected onOpenInNewTab(): void;
|
|
348
|
+
protected onReload(): void;
|
|
349
|
+
private clearSlowHint;
|
|
350
|
+
private isMixedContent;
|
|
351
|
+
private isOriginAllowed;
|
|
352
|
+
private show;
|
|
353
|
+
private displayFrame;
|
|
354
|
+
private startSlowHint;
|
|
355
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ExternalContentComponent, never>;
|
|
356
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ExternalContentComponent, "shared-external-content", never, {}, {}, never, never, true, never>;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Route table for embedded external content. Spread it into `MainLayoutComponent`'s children:
|
|
360
|
+
*
|
|
361
|
+
* ```ts
|
|
362
|
+
* { path: '', component: MainLayoutComponent, canActivate: [AuthGuard], children: [
|
|
363
|
+
* ...externalContentRoutes,
|
|
364
|
+
* // the application's own features
|
|
365
|
+
* ] }
|
|
366
|
+
* ```
|
|
367
|
+
*
|
|
368
|
+
* Three things about the shape are load-bearing and must not be "simplified" away:
|
|
369
|
+
*
|
|
370
|
+
* - The path is nested one segment per route. `RouteHelper.getRouteURL` and
|
|
371
|
+
* `CustomReuseStrategy.getUrlFromRoute` collect segments walking up the parent chain and then
|
|
372
|
+
* reverse the flat list, so a route declared `'external-content/:menuID'` rebuilds as
|
|
373
|
+
* `/:menuID/external-content` and every tab URL is wrong.
|
|
374
|
+
* - `DefaultTabViewComponent` hosts the view. It is what renders the `#ribbon` template the
|
|
375
|
+
* component publishes, so dropping it leaves the Reload and Open-in-a-new-browser-tab actions
|
|
376
|
+
* with nowhere to appear.
|
|
377
|
+
* - `FRAMEWORK_VIEW_TYPE` must be present. `TabsComponent` re-creates the tab after a page refresh
|
|
378
|
+
* by looking for a `Details` or `List` view in the activated route tree, and navigates to `/`
|
|
379
|
+
* when it finds neither — the embedded tab would vanish on F5.
|
|
380
|
+
*/
|
|
381
|
+
export declare const externalContentRoutes: Routes;
|
|
382
|
+
export declare class OperationsHistoryChildListComponent extends ChildList<any> implements AfterViewInit {
|
|
383
|
+
private readonly modal;
|
|
384
|
+
private readonly operationTemplate;
|
|
385
|
+
set controllerName(value: string);
|
|
386
|
+
/**
|
|
387
|
+
* Filters to send with the list.
|
|
388
|
+
*
|
|
389
|
+
* The audit view applies its filters to the services grid and hands the same set here, because
|
|
390
|
+
* one of them -- whether to list only the audited record's own operations -- belongs to this
|
|
391
|
+
* list. The rest mean nothing to it, and the backend reads only what it recognises.
|
|
392
|
+
*
|
|
393
|
+
* `setFilters` refreshes the grid itself. With no service selected the dataset answers with an
|
|
394
|
+
* empty list rather than calling the backend, so a refresh then costs nothing.
|
|
395
|
+
*/
|
|
396
|
+
set filters(value: {
|
|
397
|
+
[key: string]: string;
|
|
398
|
+
} | undefined);
|
|
399
|
+
set serviceID(value: number | undefined);
|
|
400
|
+
readonly selectedNewValues: WritableSignal<any | null>;
|
|
401
|
+
readonly selectedOldValues: WritableSignal<any | null>;
|
|
402
|
+
ngAfterViewInit(): void;
|
|
403
|
+
openModal(): void;
|
|
404
|
+
selectedRowChanged(): void;
|
|
405
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<OperationsHistoryChildListComponent, never>;
|
|
406
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<OperationsHistoryChildListComponent, "shared-operations-history-child-list", never, {
|
|
407
|
+
"controllerName": {
|
|
408
|
+
"alias": "controllerName";
|
|
409
|
+
"required": false;
|
|
410
|
+
};
|
|
411
|
+
"filters": {
|
|
412
|
+
"alias": "filters";
|
|
413
|
+
"required": false;
|
|
414
|
+
};
|
|
415
|
+
"serviceID": {
|
|
416
|
+
"alias": "serviceID";
|
|
417
|
+
"required": false;
|
|
418
|
+
};
|
|
419
|
+
}, {}, never, never, true, never>;
|
|
420
|
+
}
|
|
421
|
+
export declare class OperationsHistoryModalComponent extends ModalBase {
|
|
422
|
+
private readonly modal;
|
|
423
|
+
readonly newValues: InputSignal<string | undefined>;
|
|
424
|
+
readonly oldValues: InputSignal<string | undefined>;
|
|
425
|
+
/** Delegates to the inner modal; a signal query, so it re-runs once that child resolves. */
|
|
426
|
+
readonly isModalShown: Signal<boolean>;
|
|
427
|
+
toggle(): void;
|
|
428
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<OperationsHistoryModalComponent, never>;
|
|
429
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<OperationsHistoryModalComponent, "shared-operations-history-modal", never, {
|
|
430
|
+
"newValues": {
|
|
431
|
+
"alias": "newValues";
|
|
432
|
+
"required": false;
|
|
433
|
+
"isSignal": true;
|
|
434
|
+
};
|
|
435
|
+
"oldValues": {
|
|
436
|
+
"alias": "oldValues";
|
|
437
|
+
"required": false;
|
|
438
|
+
"isSignal": true;
|
|
439
|
+
};
|
|
440
|
+
}, {}, never, never, true, never>;
|
|
441
|
+
}
|
|
442
|
+
export declare class ServicesHistoryChildListComponent extends ChildList<any> implements AfterViewInit, OnInit {
|
|
443
|
+
private readonly serviceTemplate;
|
|
444
|
+
set controllerName(value: string);
|
|
445
|
+
/** Re-emits the grid's own filter changes, for a sibling list that has to follow them. */
|
|
446
|
+
readonly filtersChanged: OutputEmitterRef<{
|
|
447
|
+
[key: string]: string;
|
|
448
|
+
} | undefined>;
|
|
449
|
+
readonly selectedServiceID: WritableSignal<number | undefined>;
|
|
450
|
+
ngAfterViewInit(): void;
|
|
451
|
+
ngOnInit(): void;
|
|
452
|
+
selectedRowChanged(): void;
|
|
453
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ServicesHistoryChildListComponent, never>;
|
|
454
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ServicesHistoryChildListComponent, "shared-services-history-child-list", never, {
|
|
455
|
+
"controllerName": {
|
|
456
|
+
"alias": "controllerName";
|
|
457
|
+
"required": false;
|
|
458
|
+
};
|
|
459
|
+
}, {
|
|
460
|
+
"filtersChanged": "filtersChanged";
|
|
461
|
+
}, never, never, true, never>;
|
|
462
|
+
}
|
|
463
|
+
export declare class ServicesHistoryFilterComponent extends FiltersBase implements OnInit {
|
|
464
|
+
/**
|
|
465
|
+
* Catalog that resolves the people who can appear as the author of a change.
|
|
466
|
+
*
|
|
467
|
+
* There is no such catalog in this library -- who a user is belongs to the application -- so the
|
|
468
|
+
* author filter is offered only when one is supplied.
|
|
469
|
+
*/
|
|
470
|
+
readonly usersCatalogEndpoint: InputSignal<string | undefined>;
|
|
471
|
+
protected readonly hasUsersCatalog: Signal<boolean>;
|
|
472
|
+
private get changedOnFromControl();
|
|
473
|
+
private get changedOnToControl();
|
|
474
|
+
ngOnInit(): void;
|
|
475
|
+
/**
|
|
476
|
+
* The control names are the filter names the backend reads, case insensitively: `name`,
|
|
477
|
+
* `changedByID`, `changedOnFrom`, `changedOnTo` and `onlyCurrentEntity` reach `AuditFilters` in
|
|
478
|
+
* ZWebAPI. The two dates are sent as picked and turned into UTC instants by
|
|
479
|
+
* {@link ServicesHistoryDataset}, which is the boundary where the request is built.
|
|
480
|
+
*/
|
|
481
|
+
protected formSetup(): FormGroup<any>;
|
|
482
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ServicesHistoryFilterComponent, never>;
|
|
483
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ServicesHistoryFilterComponent, "shared-services-history-filter", never, {
|
|
484
|
+
"usersCatalogEndpoint": {
|
|
485
|
+
"alias": "usersCatalogEndpoint";
|
|
486
|
+
"required": false;
|
|
487
|
+
"isSignal": true;
|
|
488
|
+
};
|
|
489
|
+
}, {}, never, never, true, never>;
|
|
490
|
+
}
|
|
491
|
+
export declare class ServicesHistoryViewComponent extends TabViewBase {
|
|
492
|
+
readonly controllerName: ModelSignal<string>;
|
|
493
|
+
readonly entityID: ModelSignal<number | undefined>;
|
|
494
|
+
/**
|
|
495
|
+
* Catalog resolving the people who can appear as the author of a change, for the filter.
|
|
496
|
+
*
|
|
497
|
+
* Supplied through the route's `usersCatalogEndpoint` data, or bound directly. Without it the
|
|
498
|
+
* author filter is not offered -- see {@link ServicesHistoryFilterComponent}.
|
|
499
|
+
*/
|
|
500
|
+
readonly usersCatalogEndpoint: ModelSignal<string | undefined>;
|
|
501
|
+
/**
|
|
502
|
+
* The filters applied to the services grid, forwarded to the operations grid.
|
|
503
|
+
*
|
|
504
|
+
* Only `onlyCurrentEntity` means anything to the operations list, and the backend reads only what
|
|
505
|
+
* it recognises, so the set is passed whole rather than picked apart here: a filter added later
|
|
506
|
+
* then reaches both lists without this having to learn about it.
|
|
507
|
+
*/
|
|
508
|
+
protected readonly operationsFilters: WritableSignal<{
|
|
509
|
+
[key: string]: string;
|
|
510
|
+
} | undefined>;
|
|
511
|
+
private activatedRoute;
|
|
512
|
+
private dataProviderService;
|
|
513
|
+
constructor();
|
|
514
|
+
protected onFiltersChanged(filters?: {
|
|
515
|
+
[key: string]: string;
|
|
516
|
+
}): void;
|
|
517
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ServicesHistoryViewComponent, never>;
|
|
518
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ServicesHistoryViewComponent, "shared-services-history-view", never, {
|
|
519
|
+
"controllerName": {
|
|
520
|
+
"alias": "controllerName";
|
|
521
|
+
"required": false;
|
|
522
|
+
"isSignal": true;
|
|
523
|
+
};
|
|
524
|
+
"entityID": {
|
|
525
|
+
"alias": "entityID";
|
|
526
|
+
"required": false;
|
|
527
|
+
"isSignal": true;
|
|
528
|
+
};
|
|
529
|
+
"usersCatalogEndpoint": {
|
|
530
|
+
"alias": "usersCatalogEndpoint";
|
|
531
|
+
"required": false;
|
|
532
|
+
"isSignal": true;
|
|
533
|
+
};
|
|
534
|
+
}, {
|
|
535
|
+
"controllerName": "controllerNameChange";
|
|
536
|
+
"entityID": "entityIDChange";
|
|
537
|
+
"usersCatalogEndpoint": "usersCatalogEndpointChange";
|
|
538
|
+
}, never, never, true, never>;
|
|
539
|
+
}
|
|
540
|
+
export declare const ZAMBON_SHARED_I18N_ASSET_PATH = "assets/i18n/zambon-dev/shared";
|
|
541
|
+
export declare const ZAMBON_SHARED_I18N_ASSET: AngularAssetPattern;
|
|
542
|
+
export declare const ZAMBON_SHARED_I18N_RESOURCES: TranslationResource[];
|
|
543
|
+
export interface ZambonSharedTranslateConfig {
|
|
544
|
+
defaultLanguage?: string;
|
|
545
|
+
appResources?: (string | TranslationResource)[];
|
|
546
|
+
}
|
|
547
|
+
export declare function createZambonSharedTranslateLoader(httpBackend: HttpBackend, appResources?: (string | TranslationResource)[]): MultiTranslateHttpLoader;
|
|
548
|
+
export declare function provideZambonSharedTranslateLoader(appResources?: (string | TranslationResource)[]): Provider;
|
|
549
|
+
export declare function provideZambonSharedTranslateService(config?: ZambonSharedTranslateConfig): EnvironmentProviders;
|
|
550
|
+
export declare class LoginLayoutComponent {
|
|
551
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<LoginLayoutComponent, never>;
|
|
552
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<LoginLayoutComponent, "shared-login-layout", never, {}, {}, never, never, true, never>;
|
|
553
|
+
}
|
|
554
|
+
export declare class MainLayoutComponent implements OnInit, OnDestroy {
|
|
555
|
+
private readonly logoutModal;
|
|
556
|
+
private authenticationService;
|
|
557
|
+
private destroy$;
|
|
558
|
+
private externalContentService;
|
|
559
|
+
private externalUrlResolverService;
|
|
560
|
+
private router;
|
|
561
|
+
private sidebarService;
|
|
562
|
+
private tabService;
|
|
563
|
+
/** Application version (from AppConfig) projected into the sidebar footer. */
|
|
564
|
+
protected appVersion: string;
|
|
565
|
+
ngOnDestroy(): void;
|
|
566
|
+
ngOnInit(): void;
|
|
567
|
+
onLogoutClick(): void;
|
|
568
|
+
onLogoutConfirm(): void;
|
|
569
|
+
private openExternalMenu;
|
|
570
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MainLayoutComponent, never>;
|
|
571
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MainLayoutComponent, "shared-main-layout", never, {}, {}, never, never, true, never>;
|
|
572
|
+
}
|
|
573
|
+
export declare class BrandComponent {
|
|
574
|
+
private config;
|
|
575
|
+
protected get appName(): string;
|
|
576
|
+
protected get companyName(): string;
|
|
577
|
+
protected get logoUrl(): string | undefined;
|
|
578
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BrandComponent, never>;
|
|
579
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BrandComponent, "shared-brand", never, {}, {}, never, never, true, never>;
|
|
580
|
+
}
|
|
581
|
+
export declare class EnvironmentBadgeComponent {
|
|
582
|
+
private config;
|
|
583
|
+
/** CSS modifier class for the current environment, falling back to a neutral style. */
|
|
584
|
+
protected get badgeClass(): string;
|
|
585
|
+
/** Normalized environment key (uppercase, trimmed). */
|
|
586
|
+
protected get environment(): string;
|
|
587
|
+
/** The badge is hidden in production and when no environment is configured. */
|
|
588
|
+
protected get isVisible(): boolean;
|
|
589
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<EnvironmentBadgeComponent, never>;
|
|
590
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<EnvironmentBadgeComponent, "shared-environment-badge", never, {}, {}, never, never, true, never>;
|
|
591
|
+
}
|
|
592
|
+
export declare class NotificationsComponent implements OnInit {
|
|
593
|
+
readonly dropdown: Signal<ElementRef<HTMLDivElement> | undefined>;
|
|
594
|
+
private notificationsService;
|
|
595
|
+
private router;
|
|
596
|
+
protected notifications$: Observable<INotification[]>;
|
|
597
|
+
protected readonly showDropdown: WritableSignal<boolean>;
|
|
598
|
+
protected unreadCount$: Observable<number>;
|
|
599
|
+
/** Whether the notifications feature is enabled; when false the bell is not rendered. */
|
|
600
|
+
get isEnabled(): boolean;
|
|
601
|
+
ngOnInit(): void;
|
|
602
|
+
onDropdownClick(): void;
|
|
603
|
+
onMarkAllAsRead(): void;
|
|
604
|
+
onNotificationClick(notification: INotification): void;
|
|
605
|
+
protected documentClick(event: MouseEvent): void;
|
|
606
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NotificationsComponent, never>;
|
|
607
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<NotificationsComponent, "shared-notifications", never, {}, {}, never, never, true, never>;
|
|
608
|
+
}
|
|
609
|
+
export declare class TopBarComponent {
|
|
610
|
+
/** Emitted when the logout button is clicked. */
|
|
611
|
+
readonly logout: OutputEmitterRef<void>;
|
|
612
|
+
onLogoutClick(): void;
|
|
613
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TopBarComponent, never>;
|
|
614
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TopBarComponent, "shared-top-bar", never, {}, {
|
|
615
|
+
"logout": "logout";
|
|
616
|
+
}, never, never, true, never>;
|
|
617
|
+
}
|
|
618
|
+
export declare class UserProfileComponent implements OnInit {
|
|
619
|
+
private authenticationService;
|
|
620
|
+
protected readonly user: WritableSignal<ICurrentUserInfo | null>;
|
|
621
|
+
/** Up to two uppercase initials derived from the user's name, used when no picture is set. */
|
|
622
|
+
protected get initials(): string;
|
|
623
|
+
protected get name(): string;
|
|
624
|
+
protected get pictureUrl(): string | undefined;
|
|
625
|
+
protected get position(): string;
|
|
626
|
+
ngOnInit(): void;
|
|
627
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UserProfileComponent, never>;
|
|
628
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UserProfileComponent, "shared-user-profile", never, {}, {}, never, never, true, never>;
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Pipe that bypasses Angular's built-in HTML sanitization.
|
|
632
|
+
*
|
|
633
|
+
* **WARNING: This pipe introduces XSS (Cross-Site Scripting) risk.**
|
|
634
|
+
* It marks the provided HTML string as trusted, meaning Angular will
|
|
635
|
+
* render it without any sanitization. Malicious content such as
|
|
636
|
+
* `<script>` tags, inline event handlers (`onerror`, `onclick`, etc.),
|
|
637
|
+
* and `javascript:` URLs will be executed in the user's browser.
|
|
638
|
+
*
|
|
639
|
+
* ### Safe usage
|
|
640
|
+
* - Server-rendered HTML from **trusted, internal APIs** that never
|
|
641
|
+
* include user-generated content (e.g., admin-authored rich text
|
|
642
|
+
* that is sanitized server-side before storage).
|
|
643
|
+
* - Static HTML snippets defined in application code.
|
|
644
|
+
*
|
|
645
|
+
* ### Unsafe usage (DO NOT use for these)
|
|
646
|
+
* - Any value that originates from user input (form fields, query
|
|
647
|
+
* params, URL fragments, file uploads).
|
|
648
|
+
* - Third-party API responses whose content you do not control.
|
|
649
|
+
* - Database fields that may contain unsanitized user submissions.
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* // Safe — trusted server content
|
|
653
|
+
* <div [innerHTML]="trustedServerHtml | bypassHtmlSanitizer"></div>
|
|
654
|
+
*
|
|
655
|
+
* // UNSAFE — user-provided content (use Angular’s default sanitization instead)
|
|
656
|
+
* <div [innerHTML]="comment.body | bypassHtmlSanitizer"></div> // ❌ XSS risk
|
|
657
|
+
* <div [innerHTML]="comment.body"></div> // ✅ Angular sanitizes automatically
|
|
658
|
+
*/
|
|
659
|
+
export declare class BypassHtmlSanitizerPipe implements PipeTransform {
|
|
660
|
+
private sanitizer;
|
|
661
|
+
transform(html: string): SafeHtml;
|
|
662
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BypassHtmlSanitizerPipe, never>;
|
|
663
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<BypassHtmlSanitizerPipe, "bypassHtmlSanitizer", true>;
|
|
664
|
+
}
|
|
665
|
+
export declare class EnumLabelPipe implements PipeTransform {
|
|
666
|
+
transform(value?: number, enumType?: any): string;
|
|
667
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<EnumLabelPipe, never>;
|
|
668
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<EnumLabelPipe, "enumLabel", true>;
|
|
669
|
+
}
|
|
670
|
+
export declare class UtcDatePipe implements PipeTransform {
|
|
671
|
+
private static readonly timeZoneMarker;
|
|
672
|
+
transform(value?: Date | string): Date | null;
|
|
673
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UtcDatePipe, never>;
|
|
674
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<UtcDatePipe, "utcDate", true>;
|
|
675
|
+
}
|