oip-common 0.2.1 → 0.3.1
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/assets/i18n/app-modules.en.json +23 -23
- package/assets/i18n/app-modules.ru.json +23 -23
- package/assets/i18n/en.json +11 -0
- package/assets/i18n/ru.json +11 -0
- package/assets/layout/_menu.scss +148 -159
- package/assets/oip-common.scss +6 -5
- package/fesm2022/oip-common.mjs +2026 -1275
- package/fesm2022/oip-common.mjs.map +1 -1
- package/index.d.ts +330 -300
- package/package.json +4 -1
- package/scripts/generate-api.mjs +3 -1
- package/templates/http-client.ejs +25 -13
package/fesm2022/oip-common.mjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject,
|
|
2
|
+
import { Injectable, inject, signal, computed, effect, DestroyRef, ChangeDetectorRef, Component, Input, InjectionToken, PLATFORM_ID, ViewChild, HostBinding, EventEmitter, Output, Renderer2, SecurityContext, ChangeDetectionStrategy, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
-
import * as i2$
|
|
4
|
+
import * as i2$3 from 'primeng/api';
|
|
5
5
|
import { MessageService, ConfirmationService, PrimeIcons, SharedModule } from 'primeng/api';
|
|
6
|
-
import { HttpErrorResponse, HttpClient as HttpClient$1,
|
|
6
|
+
import { HttpErrorResponse, HttpClient as HttpClient$1, provideHttpClient, withInterceptors, withFetch } from '@angular/common/http';
|
|
7
7
|
import * as i2$4 from '@ngx-translate/core';
|
|
8
|
-
import { TranslateService, TranslatePipe, TranslateModule } from '@ngx-translate/core';
|
|
9
|
-
import * as i1$
|
|
8
|
+
import { TranslateService, TranslatePipe, TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
|
9
|
+
import * as i1$4 from '@angular/router';
|
|
10
10
|
import { ActivatedRoute, Router, RouterModule, NavigationEnd, RouterLinkActive, RouterLink } from '@angular/router';
|
|
11
|
-
import {
|
|
12
|
-
import { filter, distinctUntilChanged, map, switchMap,
|
|
11
|
+
import { BehaviorSubject, Subject, of, tap, shareReplay, ReplaySubject, firstValueFrom, merge, from, finalize, filter as filter$1 } from 'rxjs';
|
|
12
|
+
import { tap as tap$1, catchError, filter, distinctUntilChanged, map, switchMap, take } from 'rxjs/operators';
|
|
13
13
|
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
14
14
|
import { PrimeNG } from 'primeng/config';
|
|
15
|
-
import { OidcSecurityService, PublicEventsService, EventTypes
|
|
15
|
+
import { OidcSecurityService, PublicEventsService, EventTypes } from 'angular-auth-oidc-client';
|
|
16
16
|
import * as i1 from 'primeng/multiselect';
|
|
17
17
|
import { MultiSelectModule } from 'primeng/multiselect';
|
|
18
18
|
import * as i2 from 'primeng/tooltip';
|
|
@@ -22,8 +22,8 @@ import { ButtonModule, Button } from 'primeng/button';
|
|
|
22
22
|
import * as i1$1 from '@angular/forms';
|
|
23
23
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
24
24
|
import * as i2$1 from '@angular/common';
|
|
25
|
-
import { isPlatformBrowser, CommonModule, NgComponentOutlet, NgClass, DatePipe } from '@angular/common';
|
|
26
|
-
import * as i3$
|
|
25
|
+
import { isPlatformBrowser, CommonModule, NgComponentOutlet, NgClass, DatePipe, PathLocationStrategy, LocationStrategy } from '@angular/common';
|
|
26
|
+
import * as i3$2 from 'primeng/styleclass';
|
|
27
27
|
import { StyleClassModule } from 'primeng/styleclass';
|
|
28
28
|
import { updatePreset, updateSurfacePalette, $t } from '@primeng/themes';
|
|
29
29
|
import Aura from '@primeng/themes/aura';
|
|
@@ -34,40 +34,44 @@ import { SelectButtonModule } from 'primeng/selectbutton';
|
|
|
34
34
|
import { Tabs, TabList, Tab } from 'primeng/tabs';
|
|
35
35
|
import * as i2$2 from 'primeng/avatar';
|
|
36
36
|
import { AvatarModule } from 'primeng/avatar';
|
|
37
|
-
import
|
|
37
|
+
import { ConfirmDialog } from 'primeng/confirmdialog';
|
|
38
|
+
import * as i1$3 from 'primeng/badge';
|
|
39
|
+
import { BadgeModule } from 'primeng/badge';
|
|
40
|
+
import * as i3$1 from 'primeng/paginator';
|
|
41
|
+
import { PaginatorModule } from 'primeng/paginator';
|
|
42
|
+
import * as i7 from 'primeng/popover';
|
|
43
|
+
import { Popover, PopoverModule } from 'primeng/popover';
|
|
44
|
+
import * as i4 from 'primeng/progressspinner';
|
|
45
|
+
import { ProgressSpinnerModule } from 'primeng/progressspinner';
|
|
46
|
+
import * as i9 from 'primeng/tag';
|
|
47
|
+
import { Tag, TagModule } from 'primeng/tag';
|
|
48
|
+
import * as signalR from '@microsoft/signalr';
|
|
49
|
+
import * as i1$5 from 'primeng/contextmenu';
|
|
38
50
|
import { ContextMenuModule, ContextMenu } from 'primeng/contextmenu';
|
|
39
|
-
import * as
|
|
51
|
+
import * as i3$4 from 'primeng/dialog';
|
|
40
52
|
import { DialogModule } from 'primeng/dialog';
|
|
41
|
-
import * as
|
|
53
|
+
import * as i4$1 from 'primeng/inputtext';
|
|
42
54
|
import { InputTextModule, InputText } from 'primeng/inputtext';
|
|
43
|
-
import
|
|
44
|
-
import * as i3$2 from 'primeng/ripple';
|
|
55
|
+
import * as i3$3 from 'primeng/ripple';
|
|
45
56
|
import { RippleModule } from 'primeng/ripple';
|
|
46
|
-
import
|
|
47
|
-
import * as i4 from 'primeng/select';
|
|
57
|
+
import * as i5 from 'primeng/select';
|
|
48
58
|
import { SelectModule, Select } from 'primeng/select';
|
|
49
|
-
import * as i1$
|
|
59
|
+
import * as i1$6 from 'primeng/fileupload';
|
|
50
60
|
import { FileUploadModule } from 'primeng/fileupload';
|
|
51
61
|
import { ImageModule } from 'primeng/image';
|
|
52
|
-
import * as i1$
|
|
62
|
+
import * as i1$7 from 'primeng/table';
|
|
53
63
|
import { TableModule } from 'primeng/table';
|
|
54
64
|
import * as i2$5 from 'primeng/toggleswitch';
|
|
55
65
|
import { ToggleSwitchModule } from 'primeng/toggleswitch';
|
|
56
|
-
import * as i9 from 'primeng/tag';
|
|
57
|
-
import { TagModule, Tag } from 'primeng/tag';
|
|
58
66
|
import { TextareaModule, Textarea } from 'primeng/textarea';
|
|
59
|
-
import * as i4$
|
|
67
|
+
import * as i4$2 from 'primeng/toolbar';
|
|
60
68
|
import { ToolbarModule } from 'primeng/toolbar';
|
|
61
|
-
import * as i5 from 'primeng/card';
|
|
69
|
+
import * as i5$1 from 'primeng/card';
|
|
62
70
|
import { CardModule } from 'primeng/card';
|
|
63
71
|
import { DividerModule } from 'primeng/divider';
|
|
64
72
|
import * as i6 from 'primeng/panel';
|
|
65
73
|
import { PanelModule } from 'primeng/panel';
|
|
66
|
-
import
|
|
67
|
-
import { PopoverModule } from 'primeng/popover';
|
|
68
|
-
import * as i8 from 'primeng/progressspinner';
|
|
69
|
-
import { ProgressSpinnerModule } from 'primeng/progressspinner';
|
|
70
|
-
import * as signalR from '@microsoft/signalr';
|
|
74
|
+
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
|
71
75
|
|
|
72
76
|
class TopBarService {
|
|
73
77
|
get availableTopBarItems() {
|
|
@@ -235,94 +239,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
235
239
|
args: [{ providedIn: 'root' }]
|
|
236
240
|
}] });
|
|
237
241
|
|
|
238
|
-
const DEFAULT_OIP_FRONTEND_CONFIG = {
|
|
239
|
-
appMode: 'standalone',
|
|
240
|
-
apiBaseUrl: '',
|
|
241
|
-
notificationHubUrl: ''
|
|
242
|
-
};
|
|
243
|
-
const OIP_FRONTEND_CONFIG = new InjectionToken('OIP_FRONTEND_CONFIG', {
|
|
244
|
-
factory: () => DEFAULT_OIP_FRONTEND_CONFIG
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* BaseDataService provides a unified interface for sending HTTP requests
|
|
249
|
-
* using Angular's HttpClient. It supports standard HTTP methods and automatic
|
|
250
|
-
* credential handling.
|
|
251
|
-
*/
|
|
252
|
-
class BaseDataService {
|
|
253
|
-
constructor() {
|
|
254
|
-
this.http = inject(HttpClient$1);
|
|
255
|
-
this.frontendConfig = inject(OIP_FRONTEND_CONFIG);
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Gets the base URL of the application from the HTML <base> tag.
|
|
259
|
-
*/
|
|
260
|
-
get baseUrl() {
|
|
261
|
-
return this.normalizeBaseUrl(this.frontendConfig.apiBaseUrl || document.getElementsByTagName('base')[0].href);
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Builds a fully-qualified application URL based on frontend mode.
|
|
265
|
-
*/
|
|
266
|
-
buildUrl(path) {
|
|
267
|
-
const normalizedPath = path.startsWith('/') ? path.substring(1) : path;
|
|
268
|
-
return `${this.baseUrl}${normalizedPath}`;
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Sends an HTTP request with the specified method and data.
|
|
272
|
-
*
|
|
273
|
-
* @template TResponse - Expected response type.
|
|
274
|
-
* @param url - The target URL for the HTTP request.
|
|
275
|
-
* @param method - The HTTP method to use (GET, PUT, POST, DELETE). Default is 'GET'.
|
|
276
|
-
* @param data - An object containing request parameters or payload.
|
|
277
|
-
* @returns A promise that resolves to the response of type TResponse.
|
|
278
|
-
*/
|
|
279
|
-
sendRequest(url, method = 'GET', data = {}) {
|
|
280
|
-
const httpOptions = { withCredentials: true };
|
|
281
|
-
let result;
|
|
282
|
-
switch (method) {
|
|
283
|
-
case 'GET':
|
|
284
|
-
result = this.http.get(url, { params: data });
|
|
285
|
-
break;
|
|
286
|
-
case 'PUT':
|
|
287
|
-
result = this.http.put(url, data, httpOptions);
|
|
288
|
-
break;
|
|
289
|
-
case 'POST':
|
|
290
|
-
result = this.http.post(url, data, httpOptions);
|
|
291
|
-
break;
|
|
292
|
-
case 'DELETE':
|
|
293
|
-
result = this.http.request('DELETE', url, {
|
|
294
|
-
body: data,
|
|
295
|
-
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
|
|
296
|
-
withCredentials: true
|
|
297
|
-
});
|
|
298
|
-
break;
|
|
299
|
-
}
|
|
300
|
-
return lastValueFrom(result);
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Sends a GET request and retrieves a response as a Blob.
|
|
304
|
-
*
|
|
305
|
-
* @param url - The target URL for the GET request.
|
|
306
|
-
* @returns A promise that resolves to a Object response.
|
|
307
|
-
*/
|
|
308
|
-
getBlob(url) {
|
|
309
|
-
const httpOptions = {
|
|
310
|
-
responseType: 'blob',
|
|
311
|
-
withCredentials: true
|
|
312
|
-
};
|
|
313
|
-
const result = this.http.get(url, httpOptions);
|
|
314
|
-
return lastValueFrom(result);
|
|
315
|
-
}
|
|
316
|
-
normalizeBaseUrl(baseUrl) {
|
|
317
|
-
return baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
318
|
-
}
|
|
319
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BaseDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
320
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BaseDataService }); }
|
|
321
|
-
}
|
|
322
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BaseDataService, decorators: [{
|
|
323
|
-
type: Injectable
|
|
324
|
-
}] });
|
|
325
|
-
|
|
326
242
|
/**
|
|
327
243
|
* Service to manage the application title.
|
|
328
244
|
*/
|
|
@@ -611,6 +527,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
611
527
|
class L10nService {
|
|
612
528
|
constructor() {
|
|
613
529
|
this.loadedTranslations = new Set();
|
|
530
|
+
this.loadingTranslations = new Map();
|
|
614
531
|
this.httpClient = inject(HttpClient$1);
|
|
615
532
|
this.translateService = inject(TranslateService);
|
|
616
533
|
this.primeNg = inject(PrimeNG);
|
|
@@ -621,8 +538,8 @@ class L10nService {
|
|
|
621
538
|
* @param component - Name of the component to load translations for
|
|
622
539
|
*/
|
|
623
540
|
loadComponentTranslations(component) {
|
|
624
|
-
const lang = this.translateService.currentLang;
|
|
625
|
-
this.loadTranslations(component, lang);
|
|
541
|
+
const lang = this.translateService.currentLang || this.layoutService.language() || 'en';
|
|
542
|
+
return this.loadTranslations(component, lang);
|
|
626
543
|
}
|
|
627
544
|
/**
|
|
628
545
|
* Gets the translated value of a key (or an array of keys)
|
|
@@ -640,19 +557,27 @@ class L10nService {
|
|
|
640
557
|
loadTranslations(component, lang) {
|
|
641
558
|
const key = `${component}.${lang}`;
|
|
642
559
|
if (this.loadedTranslations.has(key)) {
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
try {
|
|
646
|
-
this.httpClient.get(`./assets/i18n/${component}.${lang}.json`).subscribe((translations) => {
|
|
647
|
-
const current = this.translateService.translations[lang] || {};
|
|
648
|
-
this.translateService.setTranslation(lang, { ...current, ...translations }, true);
|
|
649
|
-
this.loadedTranslations.add(key);
|
|
650
|
-
});
|
|
560
|
+
return of(null);
|
|
651
561
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
562
|
+
const loading = this.loadingTranslations.get(key);
|
|
563
|
+
if (loading) {
|
|
564
|
+
return loading;
|
|
655
565
|
}
|
|
566
|
+
const request = this.httpClient.get(`./assets/i18n/${component}.${lang}.json`).pipe(tap((translations) => {
|
|
567
|
+
const current = this.translateService.translations[lang] || {};
|
|
568
|
+
this.translateService.setTranslation(lang, { ...current, ...translations }, true);
|
|
569
|
+
this.loadedTranslations.add(key);
|
|
570
|
+
this.loadingTranslations.delete(key);
|
|
571
|
+
}), shareReplay(1));
|
|
572
|
+
this.loadingTranslations.set(key, request);
|
|
573
|
+
request.subscribe({
|
|
574
|
+
error: (e) => {
|
|
575
|
+
this.loadingTranslations.delete(key);
|
|
576
|
+
console.error(`No translations found for ${component}.${lang}.json`);
|
|
577
|
+
console.error(e);
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
return request;
|
|
656
581
|
}
|
|
657
582
|
/**
|
|
658
583
|
* Changes the lang currently used
|
|
@@ -684,25 +609,131 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
684
609
|
args: [{ providedIn: 'root' }]
|
|
685
610
|
}] });
|
|
686
611
|
|
|
687
|
-
class
|
|
688
|
-
|
|
689
|
-
|
|
612
|
+
class SecurityService {
|
|
613
|
+
}
|
|
614
|
+
class BffSecurityService {
|
|
615
|
+
constructor() {
|
|
616
|
+
this.http = inject(HttpClient$1);
|
|
617
|
+
this.authenticated = new BehaviorSubject(null);
|
|
618
|
+
this.currentUser = new BehaviorSubject(null);
|
|
619
|
+
this.csrfToken = new ReplaySubject(1);
|
|
620
|
+
this.payload = new BehaviorSubject(null);
|
|
690
621
|
}
|
|
691
|
-
|
|
692
|
-
|
|
622
|
+
auth() {
|
|
623
|
+
this.http.get(this.buildUrl('api/security/get-current-auth-session'), {
|
|
624
|
+
withCredentials: true
|
|
625
|
+
}).pipe(tap$1((session) => this.applySession(session)), catchError(() => {
|
|
626
|
+
this.applyAnonymousSession();
|
|
627
|
+
return of(null);
|
|
628
|
+
})).subscribe();
|
|
629
|
+
}
|
|
630
|
+
logout() {
|
|
631
|
+
firstValueFrom(this.getCsrfToken()).then((csrfToken) => {
|
|
632
|
+
const form = this.createPostForm(this.buildUrl('api/security/delete-auth-session'));
|
|
633
|
+
if (csrfToken?.token) {
|
|
634
|
+
const tokenInput = document.createElement('input');
|
|
635
|
+
tokenInput.type = 'hidden';
|
|
636
|
+
tokenInput.name = '__RequestVerificationToken';
|
|
637
|
+
tokenInput.value = csrfToken.token;
|
|
638
|
+
form.appendChild(tokenInput);
|
|
639
|
+
}
|
|
640
|
+
document.body.appendChild(form);
|
|
641
|
+
form.submit();
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
isAuthenticated() {
|
|
645
|
+
return this.authenticated.asObservable().pipe(filter((value) => value !== null), distinctUntilChanged());
|
|
646
|
+
}
|
|
647
|
+
getAccessToken() {
|
|
648
|
+
return of('');
|
|
649
|
+
}
|
|
650
|
+
isTokenExpired() {
|
|
651
|
+
return of(false);
|
|
693
652
|
}
|
|
694
|
-
|
|
695
|
-
return this.
|
|
653
|
+
getCurrentUser() {
|
|
654
|
+
return this.currentUser.getValue();
|
|
655
|
+
}
|
|
656
|
+
getCurrentUser$() {
|
|
657
|
+
return this.currentUser.asObservable();
|
|
658
|
+
}
|
|
659
|
+
forceRefreshSession() {
|
|
660
|
+
this.auth();
|
|
661
|
+
return of({
|
|
662
|
+
isAuthenticated: this.authenticated.getValue() === true,
|
|
663
|
+
userData: this.currentUser.getValue()
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
getCsrfToken() {
|
|
667
|
+
this.http.get(this.buildUrl('api/security/get-auth-csrf-token'), {
|
|
668
|
+
withCredentials: true
|
|
669
|
+
}).pipe(catchError(() => of(null))).subscribe((token) => this.csrfToken.next(token));
|
|
670
|
+
return this.csrfToken.asObservable();
|
|
671
|
+
}
|
|
672
|
+
isAdmin() {
|
|
673
|
+
return this.payload.getValue()?.realm_access?.roles?.includes('admin') ?? false;
|
|
674
|
+
}
|
|
675
|
+
authorize() {
|
|
676
|
+
const form = this.createPostForm(this.buildUrl('api/security/create-auth-session'));
|
|
677
|
+
document.body.appendChild(form);
|
|
678
|
+
form.submit();
|
|
679
|
+
}
|
|
680
|
+
ngOnDestroy() {
|
|
681
|
+
this.authenticated.complete();
|
|
682
|
+
this.currentUser.complete();
|
|
683
|
+
this.payload.complete();
|
|
696
684
|
}
|
|
697
|
-
|
|
698
|
-
|
|
685
|
+
applySession(session) {
|
|
686
|
+
const roles = session.roles ?? [];
|
|
687
|
+
const user = this.createCurrentUser(session, roles);
|
|
688
|
+
this.authenticated.next(session.isAuthenticated);
|
|
689
|
+
this.currentUser.next(user);
|
|
690
|
+
this.payload.next({ realm_access: { roles }, ...user });
|
|
691
|
+
}
|
|
692
|
+
createCurrentUser(session, roles) {
|
|
693
|
+
const displayName = session.displayName || session.userName || session.email;
|
|
694
|
+
const nameParts = this.splitDisplayName(displayName);
|
|
695
|
+
return {
|
|
696
|
+
userName: session.userName,
|
|
697
|
+
displayName,
|
|
698
|
+
email: session.email,
|
|
699
|
+
roles,
|
|
700
|
+
preferred_username: session.userName,
|
|
701
|
+
name: displayName,
|
|
702
|
+
given_name: nameParts.givenName,
|
|
703
|
+
family_name: nameParts.familyName
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
splitDisplayName(displayName) {
|
|
707
|
+
const parts = displayName?.trim().split(/\s+/).filter(Boolean) ?? [];
|
|
708
|
+
return {
|
|
709
|
+
givenName: parts[0],
|
|
710
|
+
familyName: parts.length > 1 ? parts.slice(1).join(' ') : undefined
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
applyAnonymousSession() {
|
|
714
|
+
this.authenticated.next(false);
|
|
715
|
+
this.currentUser.next(null);
|
|
716
|
+
this.payload.next(null);
|
|
717
|
+
this.csrfToken.next(null);
|
|
718
|
+
}
|
|
719
|
+
createPostForm(action) {
|
|
720
|
+
const form = document.createElement('form');
|
|
721
|
+
form.method = 'post';
|
|
722
|
+
form.action = action;
|
|
723
|
+
form.style.display = 'none';
|
|
724
|
+
return form;
|
|
725
|
+
}
|
|
726
|
+
buildUrl(path) {
|
|
727
|
+
const baseUrl = document.getElementsByTagName('base')[0].href;
|
|
728
|
+
const normalizedBase = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
729
|
+
return `${normalizedBase}${path}`;
|
|
730
|
+
}
|
|
731
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BffSecurityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
732
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BffSecurityService }); }
|
|
699
733
|
}
|
|
700
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
734
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BffSecurityService, decorators: [{
|
|
701
735
|
type: Injectable
|
|
702
736
|
}] });
|
|
703
|
-
|
|
704
|
-
class SecurityService {
|
|
705
|
-
}
|
|
706
737
|
/**
|
|
707
738
|
* SecurityService extends OidcSecurityService to manage authentication,
|
|
708
739
|
* token handling, and user role access in an Angular application.
|
|
@@ -717,6 +748,11 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
717
748
|
*/
|
|
718
749
|
constructor() {
|
|
719
750
|
super();
|
|
751
|
+
this.refreshLockKeyPrefix = 'oip:keycloak-refresh-lock';
|
|
752
|
+
this.refreshResultKeyPrefix = 'oip:keycloak-refresh-result';
|
|
753
|
+
this.refreshLockTtlMs = 15000;
|
|
754
|
+
this.refreshWaitTimeoutMs = 10000;
|
|
755
|
+
this.refreshTabId = this.createRefreshTabId();
|
|
720
756
|
/**
|
|
721
757
|
* Handles angular OIDC events.
|
|
722
758
|
*/
|
|
@@ -742,7 +778,9 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
742
778
|
.registerForEvents()
|
|
743
779
|
.pipe(filter((event) => event.type === EventTypes.NewAuthenticationResult))
|
|
744
780
|
.subscribe(() => {
|
|
745
|
-
super.getAccessToken().subscribe(token => {
|
|
781
|
+
super.getAccessToken().subscribe(token => {
|
|
782
|
+
this.accessToken.next(token);
|
|
783
|
+
});
|
|
746
784
|
this.auth();
|
|
747
785
|
});
|
|
748
786
|
}
|
|
@@ -759,6 +797,17 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
759
797
|
getAccessToken(configId) {
|
|
760
798
|
return merge(super.getAccessToken(configId), this.accessToken.asObservable()).pipe(distinctUntilChanged());
|
|
761
799
|
}
|
|
800
|
+
forceRefreshSession(customParams, configId) {
|
|
801
|
+
if (!this.refreshSession$) {
|
|
802
|
+
this.refreshSession$ = from(this.runSynchronizedRefresh(customParams, configId)).pipe(finalize(() => {
|
|
803
|
+
this.refreshSession$ = undefined;
|
|
804
|
+
}), shareReplay({ bufferSize: 1, refCount: false }));
|
|
805
|
+
}
|
|
806
|
+
return this.refreshSession$;
|
|
807
|
+
}
|
|
808
|
+
getCsrfToken() {
|
|
809
|
+
return of(null);
|
|
810
|
+
}
|
|
762
811
|
/**
|
|
763
812
|
* Indicates whether the current user has the 'admin' role.
|
|
764
813
|
*
|
|
@@ -807,125 +856,480 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
807
856
|
return payload.exp < Math.floor(Date.now() / 1000);
|
|
808
857
|
}));
|
|
809
858
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
static { this.deleteRight = 'delete'; }
|
|
821
|
-
/**
|
|
822
|
-
* Updates local settings and persists them to local storage.
|
|
823
|
-
* @return {void}
|
|
824
|
-
*/
|
|
825
|
-
onConfigUpdate() {
|
|
826
|
-
if (Object.keys(this.localSettings()).length > 0) {
|
|
827
|
-
this._localSettings = { ...this.localSettings() };
|
|
828
|
-
this.localSettingsUpdate.next(this._localSettings);
|
|
829
|
-
localStorage.setItem(`Instance_${this.id}`, JSON.stringify(this._localSettings));
|
|
859
|
+
async runSynchronizedRefresh(customParams, configId) {
|
|
860
|
+
const webLocks = this.getWebLocks();
|
|
861
|
+
if (webLocks) {
|
|
862
|
+
return webLocks.request(this.getRefreshLockKey(configId), { mode: 'exclusive' }, async () => {
|
|
863
|
+
const currentState = await this.syncAuthState(configId);
|
|
864
|
+
if (!(await this.isCurrentAccessTokenExpired())) {
|
|
865
|
+
return currentState;
|
|
866
|
+
}
|
|
867
|
+
return this.refreshAsLockOwner(customParams, configId);
|
|
868
|
+
});
|
|
830
869
|
}
|
|
870
|
+
return this.runSynchronizedRefreshWithStorageLock(customParams, configId);
|
|
831
871
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
this.
|
|
872
|
+
async runSynchronizedRefreshWithStorageLock(customParams, configId) {
|
|
873
|
+
const startedAt = Date.now();
|
|
874
|
+
if (this.tryAcquireRefreshLock(configId)) {
|
|
875
|
+
try {
|
|
876
|
+
const currentState = await this.syncAuthState(configId);
|
|
877
|
+
if (!(await this.isCurrentAccessTokenExpired())) {
|
|
878
|
+
return currentState;
|
|
879
|
+
}
|
|
880
|
+
return await this.refreshAsLockOwner(customParams, configId);
|
|
837
881
|
}
|
|
838
|
-
|
|
839
|
-
this.
|
|
882
|
+
finally {
|
|
883
|
+
this.releaseRefreshLock(configId);
|
|
840
884
|
}
|
|
841
885
|
}
|
|
886
|
+
const waitResult = await this.waitForRefreshResult(startedAt, configId);
|
|
887
|
+
if (waitResult === 'success') {
|
|
888
|
+
return this.syncAuthState(configId);
|
|
889
|
+
}
|
|
890
|
+
if (waitResult === 'error') {
|
|
891
|
+
throw new Error('Token refresh failed in another tab.');
|
|
892
|
+
}
|
|
893
|
+
return this.runSynchronizedRefreshWithStorageLock(customParams, configId);
|
|
894
|
+
}
|
|
895
|
+
async refreshAsLockOwner(customParams, configId) {
|
|
896
|
+
try {
|
|
897
|
+
const response = await firstValueFrom(super.forceRefreshSession(customParams, configId));
|
|
898
|
+
await this.applyLoginResponse(response, configId);
|
|
899
|
+
this.publishRefreshResult('success', configId);
|
|
900
|
+
return response;
|
|
901
|
+
}
|
|
842
902
|
catch (error) {
|
|
843
|
-
this.
|
|
844
|
-
|
|
903
|
+
this.publishRefreshResult('error', configId);
|
|
904
|
+
throw error;
|
|
845
905
|
}
|
|
846
906
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
907
|
+
async syncAuthState(configId) {
|
|
908
|
+
const response = await firstValueFrom(super.checkAuth(undefined, configId));
|
|
909
|
+
await this.applyLoginResponse(response, configId);
|
|
910
|
+
return response;
|
|
911
|
+
}
|
|
912
|
+
async applyLoginResponse(response, configId) {
|
|
913
|
+
this.loginResponse.next(response);
|
|
914
|
+
this.currentUser.next(response.userData);
|
|
915
|
+
const token = await firstValueFrom(super.getAccessToken(configId));
|
|
916
|
+
this.accessToken.next(token);
|
|
917
|
+
const payload = await firstValueFrom(this.getPayloadFromAccessToken());
|
|
918
|
+
this.payload.next(payload);
|
|
919
|
+
}
|
|
920
|
+
async isCurrentAccessTokenExpired() {
|
|
921
|
+
const payload = await firstValueFrom(this.getPayloadFromAccessToken());
|
|
922
|
+
return !payload?.exp || payload.exp < Math.floor(Date.now() / 1000);
|
|
923
|
+
}
|
|
924
|
+
tryAcquireRefreshLock(configId) {
|
|
925
|
+
const lockKey = this.getRefreshLockKey(configId);
|
|
926
|
+
const now = Date.now();
|
|
927
|
+
const currentLock = this.readRefreshLock(lockKey);
|
|
928
|
+
if (currentLock && currentLock.ownerId !== this.refreshTabId && currentLock.expiresAt > now) {
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
const nextLock = {
|
|
932
|
+
ownerId: this.refreshTabId,
|
|
933
|
+
expiresAt: now + this.refreshLockTtlMs
|
|
934
|
+
};
|
|
935
|
+
localStorage.setItem(lockKey, JSON.stringify(nextLock));
|
|
936
|
+
return this.readRefreshLock(lockKey)?.ownerId === this.refreshTabId;
|
|
937
|
+
}
|
|
938
|
+
releaseRefreshLock(configId) {
|
|
939
|
+
const lockKey = this.getRefreshLockKey(configId);
|
|
940
|
+
const currentLock = this.readRefreshLock(lockKey);
|
|
941
|
+
if (currentLock?.ownerId === this.refreshTabId) {
|
|
942
|
+
localStorage.removeItem(lockKey);
|
|
943
|
+
}
|
|
853
944
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
945
|
+
waitForRefreshResult(startedAt, configId) {
|
|
946
|
+
const resultKey = this.getRefreshResultKey(configId);
|
|
947
|
+
return new Promise((resolve) => {
|
|
948
|
+
const timeoutId = window.setTimeout(() => {
|
|
949
|
+
cleanup();
|
|
950
|
+
resolve('timeout');
|
|
951
|
+
}, this.refreshWaitTimeoutMs);
|
|
952
|
+
const intervalId = window.setInterval(() => {
|
|
953
|
+
const result = this.tryResolveRefreshResult(resultKey, startedAt, configId);
|
|
954
|
+
if (result) {
|
|
955
|
+
cleanup();
|
|
956
|
+
resolve(result);
|
|
957
|
+
}
|
|
958
|
+
}, 250);
|
|
959
|
+
const onStorage = (event) => {
|
|
960
|
+
if (event.key === resultKey) {
|
|
961
|
+
const result = this.tryResolveRefreshResult(resultKey, startedAt, configId);
|
|
962
|
+
if (result) {
|
|
963
|
+
cleanup();
|
|
964
|
+
resolve(result);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
const cleanup = () => {
|
|
969
|
+
window.clearTimeout(timeoutId);
|
|
970
|
+
window.clearInterval(intervalId);
|
|
971
|
+
window.removeEventListener('storage', onStorage);
|
|
972
|
+
};
|
|
973
|
+
window.addEventListener('storage', onStorage);
|
|
974
|
+
const result = this.tryResolveRefreshResult(resultKey, startedAt, configId);
|
|
975
|
+
if (result) {
|
|
976
|
+
cleanup();
|
|
977
|
+
resolve(result);
|
|
978
|
+
}
|
|
979
|
+
});
|
|
860
980
|
}
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
return
|
|
981
|
+
tryResolveRefreshResult(resultKey, startedAt, configId) {
|
|
982
|
+
const result = this.readRefreshResult(resultKey);
|
|
983
|
+
if (!result || result.timestamp < startedAt || result.configId !== configId) {
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
986
|
+
return result.status;
|
|
987
|
+
}
|
|
988
|
+
publishRefreshResult(status, configId) {
|
|
989
|
+
const result = {
|
|
990
|
+
configId,
|
|
991
|
+
ownerId: this.refreshTabId,
|
|
992
|
+
status,
|
|
993
|
+
timestamp: Date.now()
|
|
994
|
+
};
|
|
995
|
+
localStorage.setItem(this.getRefreshResultKey(configId), JSON.stringify(result));
|
|
867
996
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
997
|
+
readRefreshLock(lockKey) {
|
|
998
|
+
try {
|
|
999
|
+
const value = localStorage.getItem(lockKey);
|
|
1000
|
+
return value ? JSON.parse(value) : null;
|
|
1001
|
+
}
|
|
1002
|
+
catch {
|
|
1003
|
+
return null;
|
|
1004
|
+
}
|
|
873
1005
|
}
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1006
|
+
readRefreshResult(resultKey) {
|
|
1007
|
+
try {
|
|
1008
|
+
const value = localStorage.getItem(resultKey);
|
|
1009
|
+
return value ? JSON.parse(value) : null;
|
|
1010
|
+
}
|
|
1011
|
+
catch {
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
getRefreshLockKey(configId) {
|
|
1016
|
+
return `${this.refreshLockKeyPrefix}:${configId ?? 'default'}`;
|
|
1017
|
+
}
|
|
1018
|
+
getRefreshResultKey(configId) {
|
|
1019
|
+
return `${this.refreshResultKeyPrefix}:${configId ?? 'default'}`;
|
|
1020
|
+
}
|
|
1021
|
+
getWebLocks() {
|
|
1022
|
+
return navigator.locks ?? null;
|
|
1023
|
+
}
|
|
1024
|
+
createRefreshTabId() {
|
|
1025
|
+
return window.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`;
|
|
1026
|
+
}
|
|
1027
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KeycloakSecurityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1028
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KeycloakSecurityService }); }
|
|
1029
|
+
}
|
|
1030
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KeycloakSecurityService, decorators: [{
|
|
1031
|
+
type: Injectable
|
|
1032
|
+
}], ctorParameters: () => [] });
|
|
1033
|
+
|
|
1034
|
+
/* eslint-disable */
|
|
1035
|
+
/* tslint:disable */
|
|
1036
|
+
// @ts-nocheck
|
|
1037
|
+
var ContentType;
|
|
1038
|
+
(function (ContentType) {
|
|
1039
|
+
ContentType["Json"] = "application/json";
|
|
1040
|
+
ContentType["JsonApi"] = "application/vnd.api+json";
|
|
1041
|
+
ContentType["FormData"] = "multipart/form-data";
|
|
1042
|
+
ContentType["UrlEncoded"] = "application/x-www-form-urlencoded";
|
|
1043
|
+
ContentType["Text"] = "text/plain";
|
|
1044
|
+
})(ContentType || (ContentType = {}));
|
|
1045
|
+
class HttpClient {
|
|
877
1046
|
constructor() {
|
|
878
|
-
this.isInitialized = false;
|
|
879
|
-
this.moduleInstanceReloadPromise = Promise.resolve();
|
|
880
|
-
this.destroyRef = inject(DestroyRef);
|
|
881
|
-
this.securityDataService = inject(SecurityDataService);
|
|
882
1047
|
this.securityService = inject(SecurityService);
|
|
883
|
-
/**
|
|
884
|
-
* Provide access to app settings
|
|
885
|
-
*/
|
|
886
1048
|
this.layoutService = inject(LayoutService);
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
this.
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
this.
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
1049
|
+
this.baseUrl = "";
|
|
1050
|
+
this.securityWorker = () => ({
|
|
1051
|
+
headers: {
|
|
1052
|
+
"Accept-language": this.layoutService.language()
|
|
1053
|
+
? this.layoutService.language()
|
|
1054
|
+
: "en",
|
|
1055
|
+
"X-Timezone": this.layoutService.timeZone(),
|
|
1056
|
+
},
|
|
1057
|
+
});
|
|
1058
|
+
this.abortControllers = new Map();
|
|
1059
|
+
this.customFetch = (...fetchParams) => fetch(...fetchParams);
|
|
1060
|
+
this.baseApiParams = {
|
|
1061
|
+
credentials: "same-origin",
|
|
1062
|
+
headers: {},
|
|
1063
|
+
redirect: "follow",
|
|
1064
|
+
referrerPolicy: "no-referrer",
|
|
1065
|
+
};
|
|
1066
|
+
this.setSecurityData = (data) => { };
|
|
1067
|
+
this.contentFormatters = {
|
|
1068
|
+
[ContentType.Json]: (input) => input !== null && (typeof input === "object" || typeof input === "string")
|
|
1069
|
+
? JSON.stringify(input)
|
|
1070
|
+
: input,
|
|
1071
|
+
[ContentType.JsonApi]: (input) => input !== null && (typeof input === "object" || typeof input === "string")
|
|
1072
|
+
? JSON.stringify(input)
|
|
1073
|
+
: input,
|
|
1074
|
+
[ContentType.Text]: (input) => input !== null && typeof input !== "string"
|
|
1075
|
+
? JSON.stringify(input)
|
|
1076
|
+
: input,
|
|
1077
|
+
[ContentType.FormData]: (input) => {
|
|
1078
|
+
if (input instanceof FormData) {
|
|
1079
|
+
return input;
|
|
1080
|
+
}
|
|
1081
|
+
return Object.keys(input || {}).reduce((formData, key) => {
|
|
1082
|
+
const property = input[key];
|
|
1083
|
+
formData.append(key, property instanceof Blob
|
|
1084
|
+
? property
|
|
1085
|
+
: typeof property === "object" && property !== null
|
|
1086
|
+
? JSON.stringify(property)
|
|
1087
|
+
: `${property}`);
|
|
1088
|
+
return formData;
|
|
1089
|
+
}, new FormData());
|
|
1090
|
+
},
|
|
1091
|
+
[ContentType.UrlEncoded]: (input) => this.toQueryString(input),
|
|
1092
|
+
};
|
|
1093
|
+
this.createAbortSignal = (cancelToken) => {
|
|
1094
|
+
if (this.abortControllers.has(cancelToken)) {
|
|
1095
|
+
const abortController = this.abortControllers.get(cancelToken);
|
|
1096
|
+
if (abortController) {
|
|
1097
|
+
return abortController.signal;
|
|
1098
|
+
}
|
|
1099
|
+
return void 0;
|
|
1100
|
+
}
|
|
1101
|
+
const abortController = new AbortController();
|
|
1102
|
+
this.abortControllers.set(cancelToken, abortController);
|
|
1103
|
+
return abortController.signal;
|
|
1104
|
+
};
|
|
1105
|
+
this.abortRequest = (cancelToken) => {
|
|
1106
|
+
const abortController = this.abortControllers.get(cancelToken);
|
|
1107
|
+
if (abortController) {
|
|
1108
|
+
abortController.abort();
|
|
1109
|
+
this.abortControllers.delete(cancelToken);
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
this.request = async ({ body, secure, path, type, query, format, baseUrl, cancelToken, ...params }) => {
|
|
1113
|
+
const secureParams = ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) &&
|
|
1114
|
+
this.securityWorker &&
|
|
1115
|
+
(await this.securityWorker(null))) ||
|
|
1116
|
+
{};
|
|
1117
|
+
const csrfParams = await this.getCsrfRequestParams(params.method, path);
|
|
1118
|
+
const requestParams = this.mergeRequestParams(this.mergeRequestParams(params, secureParams), csrfParams);
|
|
1119
|
+
const queryString = query && this.toQueryString(query);
|
|
1120
|
+
const payloadFormatter = this.contentFormatters[type || ContentType.Json];
|
|
1121
|
+
let responseFormat = format || requestParams.format;
|
|
1122
|
+
return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
|
|
1123
|
+
...requestParams,
|
|
1124
|
+
headers: {
|
|
1125
|
+
...(requestParams.headers || {}),
|
|
1126
|
+
...(type && type !== ContentType.FormData
|
|
1127
|
+
? { "Content-Type": type }
|
|
1128
|
+
: {}),
|
|
1129
|
+
},
|
|
1130
|
+
signal: (cancelToken
|
|
1131
|
+
? this.createAbortSignal(cancelToken)
|
|
1132
|
+
: requestParams.signal) || null,
|
|
1133
|
+
body: typeof body === "undefined" || body === null
|
|
1134
|
+
? null
|
|
1135
|
+
: payloadFormatter(body),
|
|
1136
|
+
}).then(async (response) => {
|
|
1137
|
+
const r = response;
|
|
1138
|
+
r.data = null;
|
|
1139
|
+
r.error = null;
|
|
1140
|
+
if (typeof E !== undefined && responseFormat === undefined)
|
|
1141
|
+
responseFormat = "json";
|
|
1142
|
+
const responseToParse = responseFormat ? response.clone() : response;
|
|
1143
|
+
const data = !responseFormat
|
|
1144
|
+
? r
|
|
1145
|
+
: await responseToParse[responseFormat]()
|
|
1146
|
+
.then((data) => {
|
|
1147
|
+
if (r.ok) {
|
|
1148
|
+
r.data = data;
|
|
1149
|
+
}
|
|
1150
|
+
else {
|
|
1151
|
+
r.error = data;
|
|
1152
|
+
}
|
|
1153
|
+
return r;
|
|
1154
|
+
})
|
|
1155
|
+
.catch((e) => {
|
|
1156
|
+
r.error = e;
|
|
1157
|
+
return r;
|
|
1158
|
+
});
|
|
1159
|
+
if (cancelToken) {
|
|
1160
|
+
this.abortControllers.delete(cancelToken);
|
|
1161
|
+
}
|
|
1162
|
+
if (!response.ok)
|
|
1163
|
+
throw data;
|
|
1164
|
+
return data.data;
|
|
1165
|
+
});
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
encodeQueryParam(key, value) {
|
|
1169
|
+
const encodedKey = encodeURIComponent(key);
|
|
1170
|
+
return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`;
|
|
1171
|
+
}
|
|
1172
|
+
addQueryParam(query, key) {
|
|
1173
|
+
return this.encodeQueryParam(key, query[key]);
|
|
1174
|
+
}
|
|
1175
|
+
addArrayQueryParam(query, key) {
|
|
1176
|
+
const value = query[key];
|
|
1177
|
+
return value.map((v) => this.encodeQueryParam(key, v)).join("&");
|
|
1178
|
+
}
|
|
1179
|
+
toQueryString(rawQuery) {
|
|
1180
|
+
const query = rawQuery || {};
|
|
1181
|
+
const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
|
|
1182
|
+
return keys
|
|
1183
|
+
.map((key) => Array.isArray(query[key])
|
|
1184
|
+
? this.addArrayQueryParam(query, key)
|
|
1185
|
+
: this.addQueryParam(query, key))
|
|
1186
|
+
.join("&");
|
|
1187
|
+
}
|
|
1188
|
+
addQueryParams(rawQuery) {
|
|
1189
|
+
const queryString = this.toQueryString(rawQuery);
|
|
1190
|
+
return queryString ? `?${queryString}` : "";
|
|
1191
|
+
}
|
|
1192
|
+
mergeRequestParams(params1, params2) {
|
|
1193
|
+
return {
|
|
1194
|
+
...this.baseApiParams,
|
|
1195
|
+
...params1,
|
|
1196
|
+
...(params2 || {}),
|
|
1197
|
+
headers: {
|
|
1198
|
+
...(this.baseApiParams.headers || {}),
|
|
1199
|
+
...(params1.headers || {}),
|
|
1200
|
+
...((params2 && params2.headers) || {}),
|
|
1201
|
+
},
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
async getCsrfRequestParams(method, path) {
|
|
1205
|
+
if (!method ||
|
|
1206
|
+
!["POST", "PUT", "PATCH", "DELETE"].includes(method.toUpperCase())) {
|
|
1207
|
+
return {};
|
|
1208
|
+
}
|
|
1209
|
+
if (path.includes("/api/security/create-auth-session") ||
|
|
1210
|
+
path.includes("/api/security/get-auth-csrf-token")) {
|
|
1211
|
+
return {};
|
|
1212
|
+
}
|
|
1213
|
+
const csrfToken = await firstValueFrom(this.securityService.getCsrfToken());
|
|
1214
|
+
return csrfToken?.token
|
|
1215
|
+
? { headers: { [csrfToken.headerName]: csrfToken.token } }
|
|
1216
|
+
: {};
|
|
1217
|
+
}
|
|
1218
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HttpClient, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1219
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HttpClient, providedIn: "root" }); }
|
|
1220
|
+
}
|
|
1221
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: HttpClient, decorators: [{
|
|
1222
|
+
type: Injectable,
|
|
1223
|
+
args: [{ providedIn: "root" }]
|
|
1224
|
+
}] });
|
|
1225
|
+
|
|
1226
|
+
class BaseModuleComponent {
|
|
1227
|
+
static { this.readRight = 'read'; }
|
|
1228
|
+
static { this.editRight = 'edit'; }
|
|
1229
|
+
static { this.deleteRight = 'delete'; }
|
|
1230
|
+
/**
|
|
1231
|
+
* Updates local settings and persists them to local storage.
|
|
1232
|
+
* @return {void}
|
|
1233
|
+
*/
|
|
1234
|
+
onConfigUpdate() {
|
|
1235
|
+
if (Object.keys(this.localSettings()).length > 0) {
|
|
1236
|
+
this._localSettings = { ...this.localSettings() };
|
|
1237
|
+
this.localSettingsUpdate.next(this._localSettings);
|
|
1238
|
+
localStorage.setItem(`Instance_${this.id}`, JSON.stringify(this._localSettings));
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
getLocalStorageSettings() {
|
|
1242
|
+
try {
|
|
1243
|
+
const localStorageSettingsString = localStorage.getItem(`Instance_${this.id}`);
|
|
1244
|
+
if (localStorageSettingsString != null) {
|
|
1245
|
+
this.localSettings.set(JSON.parse(localStorageSettingsString));
|
|
1246
|
+
}
|
|
1247
|
+
else {
|
|
1248
|
+
this.localSettings.set({});
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
catch (error) {
|
|
1252
|
+
this.msgService.error(error, 'Error parsing layoutConfig:');
|
|
1253
|
+
this.localSettings.set({});
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Checks if the content ID is present.
|
|
1258
|
+
* @returns {boolean} True if the content ID is present, false otherwise.
|
|
1259
|
+
*/
|
|
1260
|
+
get isContent() {
|
|
1261
|
+
return this.topBarService.checkId('content');
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Checks if the settings ID is present.
|
|
1265
|
+
* @returns {boolean} True if the settings ID is present, false otherwise.
|
|
1266
|
+
*/
|
|
1267
|
+
get isSettings() {
|
|
1268
|
+
return this.topBarService.checkId('settings');
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Checks if the security ID is present.
|
|
1272
|
+
* @returns {boolean} True if the security ID is present, false otherwise.
|
|
1273
|
+
*/
|
|
1274
|
+
get isSecurity() {
|
|
1275
|
+
return this.topBarService.checkId('security');
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Gets an instant translation for a key or an array of keys.
|
|
1279
|
+
*/
|
|
1280
|
+
t(key, interpolateParams) {
|
|
1281
|
+
return this.translateService.instant(key, interpolateParams);
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Initializes the component and subscribes to local settings updates.
|
|
1285
|
+
*/
|
|
1286
|
+
constructor() {
|
|
1287
|
+
this.isInitialized = false;
|
|
1288
|
+
this.moduleInstanceReloadPromise = Promise.resolve();
|
|
1289
|
+
this.destroyRef = inject(DestroyRef);
|
|
1290
|
+
this.securityService = inject(SecurityService);
|
|
1291
|
+
this.httpClient = inject(HttpClient);
|
|
1292
|
+
/**
|
|
1293
|
+
* Provide access to app settings
|
|
1294
|
+
*/
|
|
1295
|
+
this.layoutService = inject(LayoutService);
|
|
1296
|
+
/**
|
|
1297
|
+
* Provides access to topbar related functionality, such as managing visibility and content.
|
|
1298
|
+
* @type {TopBarService}
|
|
1299
|
+
*/
|
|
1300
|
+
this.topBarService = inject(TopBarService);
|
|
1301
|
+
/**
|
|
1302
|
+
* Provides access to information about the current route.
|
|
1303
|
+
* This includes route parameters, data, and the route's path.
|
|
1304
|
+
*/
|
|
1305
|
+
this.route = inject(ActivatedRoute);
|
|
1306
|
+
/**
|
|
1307
|
+
* Provides access to messaging services.
|
|
1308
|
+
*/
|
|
1309
|
+
this.msgService = inject(MsgService);
|
|
1310
|
+
/**
|
|
1311
|
+
* Provides access to translation functionality.
|
|
1312
|
+
*/
|
|
1313
|
+
this.translateService = inject(TranslateService);
|
|
1314
|
+
/**
|
|
1315
|
+
* Provides access to the application's title service.
|
|
1316
|
+
*/
|
|
1317
|
+
this.appTitleService = inject(AppTitleService);
|
|
1318
|
+
/**
|
|
1319
|
+
* Reference to the ChangeDetector. Used to trigger change detection manually.
|
|
1320
|
+
*/
|
|
1321
|
+
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
1322
|
+
/**
|
|
1323
|
+
* Represents a subscription to an observable.
|
|
1324
|
+
* Manages the lifecycle of receiving data from the observable and allows unsubscribing to stop receiving data.
|
|
1325
|
+
* @type {Subscription}
|
|
1326
|
+
*/
|
|
1327
|
+
this.subscriptions = [];
|
|
1328
|
+
/**
|
|
1329
|
+
* Configuration object for backend storage
|
|
1330
|
+
* @type {TBackendStoreSettings}
|
|
1331
|
+
*/
|
|
1332
|
+
this.settings = {};
|
|
929
1333
|
/**
|
|
930
1334
|
* Configuration object for local storage.
|
|
931
1335
|
* @type {TLocalStoreSettings}
|
|
@@ -1020,7 +1424,10 @@ class BaseModuleComponent {
|
|
|
1020
1424
|
*/
|
|
1021
1425
|
async getSettings() {
|
|
1022
1426
|
try {
|
|
1023
|
-
this.
|
|
1427
|
+
if (this.id == null) {
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
this.settings = await this.getModuleInstanceSettings();
|
|
1024
1431
|
}
|
|
1025
1432
|
catch (error) {
|
|
1026
1433
|
this.msgService.error(error);
|
|
@@ -1032,8 +1439,11 @@ class BaseModuleComponent {
|
|
|
1032
1439
|
* @return {Promise<void>} A promise that resolves when the settings are saved. Reject if an error occurs.
|
|
1033
1440
|
*/
|
|
1034
1441
|
async saveSettings(settings) {
|
|
1035
|
-
|
|
1036
|
-
.
|
|
1442
|
+
if (this.id == null) {
|
|
1443
|
+
this.msgService.error('Module id not passed!');
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
await this.saveModuleInstanceSettings({
|
|
1037
1447
|
id: this.id,
|
|
1038
1448
|
settings: settings
|
|
1039
1449
|
})
|
|
@@ -1065,7 +1475,7 @@ class BaseModuleComponent {
|
|
|
1065
1475
|
return;
|
|
1066
1476
|
}
|
|
1067
1477
|
this.rightsSubscription = this.securityService.payload
|
|
1068
|
-
.pipe(switchMap((payload) => from(this.
|
|
1478
|
+
.pipe(switchMap((payload) => from(this.getSecurity(controller, id)).pipe(map((securitySettings) => ({ payload, securitySettings })))), takeUntilDestroyed(this.destroyRef))
|
|
1069
1479
|
.subscribe({
|
|
1070
1480
|
next: ({ payload, securitySettings }) => {
|
|
1071
1481
|
const roles = payload?.realm_access?.roles ?? [];
|
|
@@ -1096,6 +1506,62 @@ class BaseModuleComponent {
|
|
|
1096
1506
|
.find((security) => security.code === code)
|
|
1097
1507
|
?.roles?.some((role) => roles.includes(role)) ?? false;
|
|
1098
1508
|
}
|
|
1509
|
+
getSecurity(controller = this.controller, id = this.id) {
|
|
1510
|
+
if (!controller || id == null) {
|
|
1511
|
+
return Promise.resolve([]);
|
|
1512
|
+
}
|
|
1513
|
+
return this.httpClient.request({
|
|
1514
|
+
path: `/api/${controller}/get-security`,
|
|
1515
|
+
method: 'GET',
|
|
1516
|
+
query: { id },
|
|
1517
|
+
secure: true,
|
|
1518
|
+
format: 'json'
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
saveSecurity(request, controller = this.controller) {
|
|
1522
|
+
return this.httpClient.request({
|
|
1523
|
+
path: `/api/${controller}/put-security`,
|
|
1524
|
+
method: 'PUT',
|
|
1525
|
+
body: request,
|
|
1526
|
+
secure: true,
|
|
1527
|
+
type: ContentType.Json
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
getModuleInstanceSettings(controller = this.controller, id = this.id) {
|
|
1531
|
+
return this.httpClient.request({
|
|
1532
|
+
path: `/api/${controller}/get-module-instance-settings`,
|
|
1533
|
+
method: 'GET',
|
|
1534
|
+
query: { id },
|
|
1535
|
+
secure: true,
|
|
1536
|
+
format: 'json'
|
|
1537
|
+
});
|
|
1538
|
+
}
|
|
1539
|
+
saveModuleInstanceSettings(request, controller = this.controller) {
|
|
1540
|
+
return this.httpClient.request({
|
|
1541
|
+
path: `/api/${controller}/put-module-instance-settings`,
|
|
1542
|
+
method: 'PUT',
|
|
1543
|
+
body: request,
|
|
1544
|
+
secure: true,
|
|
1545
|
+
type: ContentType.Json
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
getMigrations(controller = this.controller) {
|
|
1549
|
+
return this.httpClient.request({
|
|
1550
|
+
path: `/api/${controller}/get-migrations`,
|
|
1551
|
+
method: 'GET',
|
|
1552
|
+
secure: true,
|
|
1553
|
+
format: 'json'
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
applyModuleMigration(request, controller = this.controller) {
|
|
1557
|
+
return this.httpClient.request({
|
|
1558
|
+
path: `/api/${controller}/apply-migration`,
|
|
1559
|
+
method: 'POST',
|
|
1560
|
+
body: request,
|
|
1561
|
+
secure: true,
|
|
1562
|
+
type: ContentType.Json
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1099
1565
|
async reloadModuleInstance() {
|
|
1100
1566
|
this.moduleInstanceReloadPromise = this.moduleInstanceReloadPromise.then(async () => {
|
|
1101
1567
|
await this.getSettings();
|
|
@@ -1112,11 +1578,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1112
1578
|
args: [{ standalone: true, template: '' }]
|
|
1113
1579
|
}], ctorParameters: () => [] });
|
|
1114
1580
|
|
|
1581
|
+
/* eslint-disable */
|
|
1582
|
+
/* tslint:disable */
|
|
1583
|
+
// @ts-nocheck
|
|
1584
|
+
class SecurityApi extends HttpClient {
|
|
1585
|
+
constructor() {
|
|
1586
|
+
super(...arguments);
|
|
1587
|
+
this.getCurrentAuthSession = (params = {}) => this.request({
|
|
1588
|
+
path: `/api/security/get-current-auth-session`,
|
|
1589
|
+
method: "GET",
|
|
1590
|
+
secure: true,
|
|
1591
|
+
format: "json",
|
|
1592
|
+
...params,
|
|
1593
|
+
});
|
|
1594
|
+
this.createAuthSession = (params = {}) => this.request({
|
|
1595
|
+
path: `/api/security/create-auth-session`,
|
|
1596
|
+
method: "POST",
|
|
1597
|
+
secure: true,
|
|
1598
|
+
...params,
|
|
1599
|
+
});
|
|
1600
|
+
this.deleteAuthSession = (params = {}) => this.request({
|
|
1601
|
+
path: `/api/security/delete-auth-session`,
|
|
1602
|
+
method: "POST",
|
|
1603
|
+
secure: true,
|
|
1604
|
+
...params,
|
|
1605
|
+
});
|
|
1606
|
+
this.getAuthCsrfToken = (params = {}) => this.request({
|
|
1607
|
+
path: `/api/security/get-auth-csrf-token`,
|
|
1608
|
+
method: "GET",
|
|
1609
|
+
secure: true,
|
|
1610
|
+
format: "json",
|
|
1611
|
+
...params,
|
|
1612
|
+
});
|
|
1613
|
+
this.getKeycloakClientSettings = (params = {}) => this.request({
|
|
1614
|
+
path: `/api/security/get-keycloak-client-settings`,
|
|
1615
|
+
method: "GET",
|
|
1616
|
+
secure: true,
|
|
1617
|
+
format: "json",
|
|
1618
|
+
...params,
|
|
1619
|
+
});
|
|
1620
|
+
this.getRealmRoles = (params = {}) => this.request({
|
|
1621
|
+
path: `/api/security/get-realm-roles`,
|
|
1622
|
+
method: "GET",
|
|
1623
|
+
secure: true,
|
|
1624
|
+
format: "json",
|
|
1625
|
+
...params,
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1629
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityApi }); }
|
|
1630
|
+
}
|
|
1631
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityApi, decorators: [{
|
|
1632
|
+
type: Injectable
|
|
1633
|
+
}] });
|
|
1634
|
+
|
|
1115
1635
|
class SecurityComponent {
|
|
1116
1636
|
constructor() {
|
|
1117
1637
|
this.msgService = inject(MsgService);
|
|
1118
|
-
this.dataService = inject(SecurityDataService);
|
|
1119
1638
|
this.translateService = inject(TranslateService);
|
|
1639
|
+
this.httpClient = inject(HttpClient);
|
|
1640
|
+
this.securityApi = inject(SecurityApi);
|
|
1120
1641
|
this.securityLoadToken = 0;
|
|
1121
1642
|
this.securityData = [];
|
|
1122
1643
|
this.roles = [];
|
|
@@ -1130,7 +1651,7 @@ class SecurityComponent {
|
|
|
1130
1651
|
}
|
|
1131
1652
|
}
|
|
1132
1653
|
ngOnInit() {
|
|
1133
|
-
this.
|
|
1654
|
+
this.securityApi.getRealmRoles().then((result) => {
|
|
1134
1655
|
this.roles = result;
|
|
1135
1656
|
}, (error) => this.msgService.error(error));
|
|
1136
1657
|
}
|
|
@@ -1147,7 +1668,7 @@ class SecurityComponent {
|
|
|
1147
1668
|
id: this.id,
|
|
1148
1669
|
securities: this.securityData
|
|
1149
1670
|
};
|
|
1150
|
-
this.
|
|
1671
|
+
this.saveSecurity(this.controller, request).then((result) => {
|
|
1151
1672
|
this.msgService.success(this.translateService.instant('securityComponent.savedSecurity'));
|
|
1152
1673
|
}, (error) => this.msgService.error(error));
|
|
1153
1674
|
}
|
|
@@ -1165,7 +1686,7 @@ class SecurityComponent {
|
|
|
1165
1686
|
return;
|
|
1166
1687
|
}
|
|
1167
1688
|
try {
|
|
1168
|
-
const result = await this.
|
|
1689
|
+
const result = await this.getSecurity(controller, id);
|
|
1169
1690
|
if (loadToken === this.securityLoadToken) {
|
|
1170
1691
|
this.securityData = result;
|
|
1171
1692
|
}
|
|
@@ -1176,6 +1697,24 @@ class SecurityComponent {
|
|
|
1176
1697
|
}
|
|
1177
1698
|
}
|
|
1178
1699
|
}
|
|
1700
|
+
getSecurity(controller, id) {
|
|
1701
|
+
return this.httpClient.request({
|
|
1702
|
+
path: `/api/${controller}/get-security`,
|
|
1703
|
+
method: 'GET',
|
|
1704
|
+
query: { id },
|
|
1705
|
+
secure: true,
|
|
1706
|
+
format: 'json'
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
saveSecurity(controller, request) {
|
|
1710
|
+
return this.httpClient.request({
|
|
1711
|
+
path: `/api/${controller}/put-security`,
|
|
1712
|
+
method: 'PUT',
|
|
1713
|
+
body: request,
|
|
1714
|
+
secure: true,
|
|
1715
|
+
type: ContentType.Json
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1179
1718
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1180
1719
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: SecurityComponent, isStandalone: true, selector: "security", inputs: { id: "id", controller: "controller" }, usesOnChanges: true, ngImport: i0, template: `
|
|
1181
1720
|
<div class="flex flex-col md:flex-row gap-8">
|
|
@@ -1847,6 +2386,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1847
2386
|
}]
|
|
1848
2387
|
}] });
|
|
1849
2388
|
|
|
2389
|
+
/* eslint-disable */
|
|
2390
|
+
/* tslint:disable */
|
|
2391
|
+
// @ts-nocheck
|
|
2392
|
+
class UserProfileApi extends HttpClient {
|
|
2393
|
+
constructor() {
|
|
2394
|
+
super(...arguments);
|
|
2395
|
+
this.getUserPhoto = (query, params = {}) => this.request({
|
|
2396
|
+
path: `/api/user-profile/get-user-photo`,
|
|
2397
|
+
method: "GET",
|
|
2398
|
+
query: query,
|
|
2399
|
+
secure: true,
|
|
2400
|
+
format: "blob",
|
|
2401
|
+
...params,
|
|
2402
|
+
});
|
|
2403
|
+
this.postUserPhoto = (data, params = {}) => this.request({
|
|
2404
|
+
path: `/api/user-profile/post-user-photo`,
|
|
2405
|
+
method: "POST",
|
|
2406
|
+
body: data,
|
|
2407
|
+
secure: true,
|
|
2408
|
+
type: ContentType.FormData,
|
|
2409
|
+
...params,
|
|
2410
|
+
});
|
|
2411
|
+
this.getSettings = (params = {}) => this.request({
|
|
2412
|
+
path: `/api/user-profile/get-settings`,
|
|
2413
|
+
method: "GET",
|
|
2414
|
+
secure: true,
|
|
2415
|
+
format: "json",
|
|
2416
|
+
...params,
|
|
2417
|
+
});
|
|
2418
|
+
this.setSettings = (data, params = {}) => this.request({
|
|
2419
|
+
path: `/api/user-profile/set-settings`,
|
|
2420
|
+
method: "PUT",
|
|
2421
|
+
body: data,
|
|
2422
|
+
secure: true,
|
|
2423
|
+
type: ContentType.Json,
|
|
2424
|
+
...params,
|
|
2425
|
+
});
|
|
2426
|
+
}
|
|
2427
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserProfileApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2428
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserProfileApi }); }
|
|
2429
|
+
}
|
|
2430
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserProfileApi, decorators: [{
|
|
2431
|
+
type: Injectable
|
|
2432
|
+
}] });
|
|
2433
|
+
|
|
1850
2434
|
/**
|
|
1851
2435
|
* UserService is responsible for retrieving and handling user-related data,
|
|
1852
2436
|
* including the user's photo and short label for avatar display.
|
|
@@ -1854,7 +2438,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1854
2438
|
class UserService {
|
|
1855
2439
|
constructor() {
|
|
1856
2440
|
this.securityService = inject(SecurityService);
|
|
1857
|
-
this.
|
|
2441
|
+
this.userProfileApi = inject(UserProfileApi);
|
|
1858
2442
|
this.requestedPhotoEmail = null;
|
|
1859
2443
|
/**
|
|
1860
2444
|
* Stores the user's photo as a data URL or binary blob, depending on how it's processed.
|
|
@@ -1879,11 +2463,18 @@ class UserService {
|
|
|
1879
2463
|
const data = this.securityService.getCurrentUser();
|
|
1880
2464
|
const givenNameInitial = data?.given_name?.trim()?.[0];
|
|
1881
2465
|
const familyNameInitial = data?.family_name?.trim()?.[0];
|
|
1882
|
-
|
|
2466
|
+
const displayNameInitials = this.getInitials(data?.displayName ?? data?.name ?? data?.userName ?? data?.preferred_username);
|
|
2467
|
+
return `${givenNameInitial ?? ''}${familyNameInitial ?? ''}`.toUpperCase() || displayNameInitials;
|
|
1883
2468
|
}
|
|
1884
2469
|
get userName() {
|
|
1885
2470
|
const data = this.securityService.getCurrentUser();
|
|
1886
|
-
return [data?.given_name, data?.family_name].filter(Boolean).join(' ')
|
|
2471
|
+
return [data?.given_name, data?.family_name].filter(Boolean).join(' ')
|
|
2472
|
+
|| data?.displayName
|
|
2473
|
+
|| data?.name
|
|
2474
|
+
|| data?.userName
|
|
2475
|
+
|| data?.preferred_username
|
|
2476
|
+
|| data?.email
|
|
2477
|
+
|| '';
|
|
1887
2478
|
}
|
|
1888
2479
|
/**
|
|
1889
2480
|
* Initiates an HTTP request to fetch the user's photo based on their email,
|
|
@@ -1898,8 +2489,7 @@ class UserService {
|
|
|
1898
2489
|
return;
|
|
1899
2490
|
}
|
|
1900
2491
|
this.requestedPhotoEmail = email;
|
|
1901
|
-
|
|
1902
|
-
this.baseDataService.getBlob(url).then((data) => {
|
|
2492
|
+
this.userProfileApi.getUserPhoto({ email }, { format: 'blob' }).then((data) => {
|
|
1903
2493
|
this.createImageFromBlob(data);
|
|
1904
2494
|
this.photoLoaded = true;
|
|
1905
2495
|
}, (error) => {
|
|
@@ -1921,6 +2511,16 @@ class UserService {
|
|
|
1921
2511
|
reader.readAsDataURL(image);
|
|
1922
2512
|
}
|
|
1923
2513
|
}
|
|
2514
|
+
getInitials(value) {
|
|
2515
|
+
return value
|
|
2516
|
+
?.trim()
|
|
2517
|
+
.split(/\s+/)
|
|
2518
|
+
.filter(Boolean)
|
|
2519
|
+
.slice(0, 2)
|
|
2520
|
+
.map((part) => part[0])
|
|
2521
|
+
.join('')
|
|
2522
|
+
.toUpperCase() ?? '';
|
|
2523
|
+
}
|
|
1924
2524
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1925
2525
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserService }); }
|
|
1926
2526
|
}
|
|
@@ -2009,141 +2609,417 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2009
2609
|
args: [{ providedIn: 'root' }]
|
|
2010
2610
|
}] });
|
|
2011
2611
|
|
|
2012
|
-
|
|
2612
|
+
/* eslint-disable */
|
|
2613
|
+
/* tslint:disable */
|
|
2614
|
+
// @ts-nocheck
|
|
2615
|
+
class NotificationApi extends HttpClient {
|
|
2616
|
+
constructor() {
|
|
2617
|
+
super(...arguments);
|
|
2618
|
+
this.getNotificationByUser = (query, params = {}) => this.request({
|
|
2619
|
+
path: `/api/notification/get-notification-by-user`,
|
|
2620
|
+
method: "GET",
|
|
2621
|
+
query: query,
|
|
2622
|
+
secure: true,
|
|
2623
|
+
format: "json",
|
|
2624
|
+
...params,
|
|
2625
|
+
});
|
|
2626
|
+
this.getNotificationCountByUser = (params = {}) => this.request({
|
|
2627
|
+
path: `/api/notification/get-notification-count-by-user`,
|
|
2628
|
+
method: "GET",
|
|
2629
|
+
secure: true,
|
|
2630
|
+
format: "json",
|
|
2631
|
+
...params,
|
|
2632
|
+
});
|
|
2633
|
+
this.markNotificationAsRead = ({ id, ...query }, params = {}) => this.request({
|
|
2634
|
+
path: `/api/notification/mark-notification-as-read/${id}`,
|
|
2635
|
+
method: "POST",
|
|
2636
|
+
secure: true,
|
|
2637
|
+
...params,
|
|
2638
|
+
});
|
|
2639
|
+
this.getNotificationById = (query, params = {}) => this.request({
|
|
2640
|
+
path: `/api/notification/get-notification-by-id`,
|
|
2641
|
+
method: "GET",
|
|
2642
|
+
query: query,
|
|
2643
|
+
secure: true,
|
|
2644
|
+
format: "json",
|
|
2645
|
+
...params,
|
|
2646
|
+
});
|
|
2647
|
+
}
|
|
2648
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2649
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationApi }); }
|
|
2650
|
+
}
|
|
2651
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationApi, decorators: [{
|
|
2652
|
+
type: Injectable
|
|
2653
|
+
}] });
|
|
2654
|
+
|
|
2655
|
+
class NotificationService {
|
|
2013
2656
|
constructor() {
|
|
2014
2657
|
this.securityService = inject(SecurityService);
|
|
2015
|
-
this.
|
|
2016
|
-
this.
|
|
2017
|
-
this.
|
|
2018
|
-
this.
|
|
2658
|
+
this.msgService = inject(MsgService);
|
|
2659
|
+
this.notificationApi = inject(NotificationApi);
|
|
2660
|
+
this.unreadNotificationCount = signal(undefined, ...(ngDevMode ? [{ debugName: "unreadNotificationCount" }] : []));
|
|
2661
|
+
this.connection = new signalR.HubConnectionBuilder()
|
|
2662
|
+
.withUrl('/hubs/notification', {
|
|
2663
|
+
withCredentials: true,
|
|
2664
|
+
skipNegotiation: true,
|
|
2665
|
+
transport: signalR.HttpTransportType.WebSockets
|
|
2666
|
+
})
|
|
2667
|
+
.configureLogging(signalR.LogLevel.Error)
|
|
2668
|
+
.build();
|
|
2669
|
+
this.connection.on('ReceiveNotification', (notification) => {
|
|
2670
|
+
const opt = {
|
|
2671
|
+
severity: notification.severity,
|
|
2672
|
+
summary: notification.subject,
|
|
2673
|
+
detail: notification.message,
|
|
2674
|
+
life: 0
|
|
2675
|
+
};
|
|
2676
|
+
this.msgService.add(opt);
|
|
2677
|
+
this.unreadNotificationCount.update((count) => (count ?? 0) + 1);
|
|
2678
|
+
});
|
|
2679
|
+
this.securityService.isAuthenticated().subscribe((authenticated) => {
|
|
2680
|
+
if (!authenticated) {
|
|
2681
|
+
this.unreadNotificationCount.set(undefined);
|
|
2682
|
+
if (this.connection.state !== signalR.HubConnectionState.Disconnected) {
|
|
2683
|
+
this.connection.stop();
|
|
2684
|
+
}
|
|
2685
|
+
return;
|
|
2686
|
+
}
|
|
2687
|
+
this.loadUnreadNotificationCount();
|
|
2688
|
+
if (this.connection.state === signalR.HubConnectionState.Disconnected) {
|
|
2689
|
+
this.connection.start().catch((error) => console.error('Failed to start notification connection', error));
|
|
2690
|
+
return;
|
|
2691
|
+
}
|
|
2692
|
+
this.connection.stop().then(() => {
|
|
2693
|
+
this.connection.start().catch((error) => console.error('Failed to restart notification connection', error));
|
|
2694
|
+
});
|
|
2695
|
+
});
|
|
2019
2696
|
}
|
|
2020
|
-
|
|
2021
|
-
this.
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2697
|
+
loadUnreadNotificationCount() {
|
|
2698
|
+
this.notificationApi
|
|
2699
|
+
.getNotificationCountByUser()
|
|
2700
|
+
.then((response) => this.unreadNotificationCount.set(response.count ?? 0))
|
|
2701
|
+
.catch((error) => console.error('Failed to load notification count', error));
|
|
2025
2702
|
}
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2703
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2704
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationService, providedIn: 'root' }); }
|
|
2705
|
+
}
|
|
2706
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationService, decorators: [{
|
|
2707
|
+
type: Injectable,
|
|
2708
|
+
args: [{ providedIn: 'root' }]
|
|
2709
|
+
}], ctorParameters: () => [] });
|
|
2710
|
+
|
|
2711
|
+
class UserNotificationsComponent {
|
|
2712
|
+
constructor() {
|
|
2713
|
+
this.notifications = [];
|
|
2714
|
+
this.totalCount = 0;
|
|
2715
|
+
this.skip = 0;
|
|
2716
|
+
this.take = 5;
|
|
2717
|
+
this.loading = false;
|
|
2718
|
+
this.notificationApi = inject(NotificationApi);
|
|
2719
|
+
this.notificationService = inject(NotificationService);
|
|
2720
|
+
this.msgService = inject(MsgService);
|
|
2721
|
+
this.translateService = inject(TranslateService);
|
|
2722
|
+
this.unreadNotificationCount = computed(() => this.notificationService.unreadNotificationCount() ?? 0, ...(ngDevMode ? [{ debugName: "unreadNotificationCount" }] : []));
|
|
2723
|
+
this.unreadNotificationBadge = computed(() => {
|
|
2724
|
+
const count = this.unreadNotificationCount();
|
|
2725
|
+
return count > 99 ? '99+' : count.toString();
|
|
2726
|
+
}, ...(ngDevMode ? [{ debugName: "unreadNotificationBadge" }] : []));
|
|
2727
|
+
}
|
|
2728
|
+
async toggle(event) {
|
|
2729
|
+
this.popover?.toggle(event);
|
|
2730
|
+
await this.loadNotifications();
|
|
2731
|
+
}
|
|
2732
|
+
async loadNotifications() {
|
|
2733
|
+
this.loading = true;
|
|
2734
|
+
try {
|
|
2735
|
+
const response = await this.notificationApi.getNotificationByUser({
|
|
2736
|
+
skip: this.skip,
|
|
2737
|
+
take: this.take,
|
|
2738
|
+
unreadOnly: true
|
|
2739
|
+
});
|
|
2740
|
+
this.notifications = response.notifications ?? [];
|
|
2741
|
+
this.totalCount = response.totalCount ?? 0;
|
|
2742
|
+
}
|
|
2743
|
+
catch (error) {
|
|
2744
|
+
this.msgService.error(error);
|
|
2745
|
+
}
|
|
2746
|
+
finally {
|
|
2747
|
+
this.loading = false;
|
|
2029
2748
|
}
|
|
2030
2749
|
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
<i class="pi pi-bars"></i>
|
|
2036
|
-
</button>
|
|
2037
|
-
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
2038
|
-
<ng-container
|
|
2039
|
-
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
2040
|
-
<span>{{ 'app-info.title' | translate }}</span>
|
|
2041
|
-
</a>
|
|
2042
|
-
</div>
|
|
2043
|
-
|
|
2044
|
-
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
2045
|
-
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
2046
|
-
<p-tablist>
|
|
2047
|
-
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
2048
|
-
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
2049
|
-
<i class="pi {{ tab.icon }}"></i>
|
|
2050
|
-
<span class="ml-2">{{ tab.caption }}</span>
|
|
2051
|
-
</p-tab>
|
|
2052
|
-
}
|
|
2053
|
-
</p-tablist>
|
|
2054
|
-
</p-tabs>
|
|
2750
|
+
async onPageChange(event) {
|
|
2751
|
+
this.skip = event.first ?? 0;
|
|
2752
|
+
this.take = event.rows ?? this.take;
|
|
2753
|
+
await this.loadNotifications();
|
|
2055
2754
|
}
|
|
2056
|
-
|
|
2057
|
-
|
|
2755
|
+
async markAsRead(notification) {
|
|
2756
|
+
if (!notification.notificationUserId) {
|
|
2757
|
+
return;
|
|
2758
|
+
}
|
|
2759
|
+
this.readingNotificationId = notification.notificationUserId;
|
|
2760
|
+
try {
|
|
2761
|
+
await this.notificationApi.markNotificationAsRead({ id: notification.notificationUserId });
|
|
2762
|
+
this.msgService.success(this.translateService.instant('userNotifications.markedAsRead'));
|
|
2763
|
+
this.notificationService.loadUnreadNotificationCount();
|
|
2764
|
+
if (this.notifications.length === 1 && this.skip > 0) {
|
|
2765
|
+
this.skip = Math.max(this.skip - this.take, 0);
|
|
2766
|
+
}
|
|
2767
|
+
await this.loadNotifications();
|
|
2768
|
+
}
|
|
2769
|
+
catch (error) {
|
|
2770
|
+
this.msgService.error(error);
|
|
2771
|
+
}
|
|
2772
|
+
finally {
|
|
2773
|
+
this.readingNotificationId = undefined;
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
getImportanceSeverity(importance) {
|
|
2777
|
+
switch (importance) {
|
|
2778
|
+
case 'Critical':
|
|
2779
|
+
case 'High':
|
|
2780
|
+
return 'danger';
|
|
2781
|
+
case 'Medium':
|
|
2782
|
+
return 'warn';
|
|
2783
|
+
case 'Low':
|
|
2784
|
+
return 'info';
|
|
2785
|
+
default:
|
|
2786
|
+
return 'secondary';
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserNotificationsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2790
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: UserNotificationsComponent, isStandalone: true, selector: "app-user-notifications", viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], ngImport: i0, template: `
|
|
2791
|
+
<button
|
|
2792
|
+
class="layout-topbar-action relative"
|
|
2793
|
+
id="oip-app-topbar-notification-button"
|
|
2794
|
+
type="button"
|
|
2795
|
+
(click)="toggle($event)"
|
|
2796
|
+
[attr.aria-label]="'Notifications: ' + unreadNotificationCount()">
|
|
2797
|
+
<i class="pi pi-bell"></i>
|
|
2798
|
+
@if (unreadNotificationCount() > 0) {
|
|
2799
|
+
<p-badge
|
|
2800
|
+
class="absolute -top-1 -right-1"
|
|
2801
|
+
severity="danger"
|
|
2802
|
+
[badgeSize]="'small'"
|
|
2803
|
+
[value]="unreadNotificationBadge()" />
|
|
2804
|
+
}
|
|
2805
|
+
</button>
|
|
2806
|
+
|
|
2807
|
+
<p-popover #popover styleClass="w-[min(92vw,34rem)]">
|
|
2808
|
+
<div class="flex items-center justify-between gap-3 mb-4">
|
|
2809
|
+
<div class="font-semibold text-lg">
|
|
2810
|
+
{{ 'userNotifications.title' | translate }}
|
|
2811
|
+
</div>
|
|
2058
2812
|
<p-button
|
|
2059
|
-
|
|
2060
|
-
|
|
2813
|
+
icon="pi pi-refresh"
|
|
2814
|
+
rounded="true"
|
|
2061
2815
|
severity="secondary"
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
[
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
</
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2816
|
+
text="true"
|
|
2817
|
+
tooltipPosition="bottom"
|
|
2818
|
+
[disabled]="loading"
|
|
2819
|
+
[pTooltip]="'userNotifications.refresh' | translate"
|
|
2820
|
+
(onClick)="loadNotifications()"></p-button>
|
|
2821
|
+
</div>
|
|
2822
|
+
|
|
2823
|
+
@if (loading && notifications.length === 0) {
|
|
2824
|
+
<div class="flex justify-center py-8">
|
|
2825
|
+
<p-progressSpinner style="w-8 h-8"></p-progressSpinner>
|
|
2826
|
+
</div>
|
|
2827
|
+
} @else if (notifications.length === 0) {
|
|
2828
|
+
<div class="text-center py-8 text-surface-500">
|
|
2829
|
+
{{ 'userNotifications.empty' | translate }}
|
|
2830
|
+
</div>
|
|
2831
|
+
} @else {
|
|
2832
|
+
<div class="flex flex-col gap-3 max-h-[26rem] overflow-y-auto pr-1">
|
|
2833
|
+
@for (notification of notifications; track notification.notificationUserId) {
|
|
2834
|
+
<div class="border border-surface-200 dark:border-surface-700 rounded-md p-3">
|
|
2835
|
+
<div class="flex items-start justify-between gap-3">
|
|
2836
|
+
<div class="min-w-0">
|
|
2837
|
+
<div class="font-medium leading-snug break-words">
|
|
2838
|
+
{{ notification.subject }}
|
|
2839
|
+
</div>
|
|
2840
|
+
<div class="text-xs text-surface-500 mt-1">
|
|
2841
|
+
{{ notification.createdAt | date: 'dd.MM.yyyy HH:mm' }}
|
|
2842
|
+
</div>
|
|
2843
|
+
</div>
|
|
2844
|
+
@if (notification.importance) {
|
|
2845
|
+
<p-tag
|
|
2846
|
+
class="shrink-0"
|
|
2847
|
+
[severity]="getImportanceSeverity(notification.importance)"
|
|
2848
|
+
[value]="notification.importance"></p-tag>
|
|
2849
|
+
}
|
|
2850
|
+
</div>
|
|
2851
|
+
|
|
2852
|
+
<div class="text-sm text-surface-700 dark:text-surface-200 mt-3 whitespace-pre-line break-words">
|
|
2853
|
+
{{ notification.message }}
|
|
2854
|
+
</div>
|
|
2855
|
+
|
|
2856
|
+
<div class="flex justify-end mt-3">
|
|
2857
|
+
<p-button
|
|
2858
|
+
icon="pi pi-check"
|
|
2859
|
+
size="small"
|
|
2860
|
+
[label]="'userNotifications.markAsRead' | translate"
|
|
2861
|
+
[loading]="readingNotificationId === notification.notificationUserId"
|
|
2862
|
+
(onClick)="markAsRead(notification)"></p-button>
|
|
2863
|
+
</div>
|
|
2864
|
+
</div>
|
|
2865
|
+
}
|
|
2866
|
+
</div>
|
|
2867
|
+
|
|
2868
|
+
<p-paginator
|
|
2869
|
+
styleClass="mt-3"
|
|
2870
|
+
[first]="skip"
|
|
2871
|
+
[rows]="take"
|
|
2872
|
+
[totalRecords]="totalCount"
|
|
2873
|
+
[rowsPerPageOptions]="[5, 10, 20]"
|
|
2874
|
+
(onPageChange)="onPageChange($event)"></p-paginator>
|
|
2875
|
+
}
|
|
2876
|
+
</p-popover>
|
|
2877
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: BadgeModule }, { kind: "component", type: i1$3.Badge, selector: "p-badge", inputs: ["styleClass", "badgeSize", "size", "severity", "value", "badgeDisabled"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i3$1.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "styleClass", "alwaysShow", "dropdownAppendTo", "templateLeft", "templateRight", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "jumpToPageItemTemplate", "showPageLinks", "locale", "dropdownItemTemplate", "first", "appendTo"], outputs: ["onPageChange"] }, { kind: "component", type: Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: i2$1.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
2878
|
+
}
|
|
2879
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UserNotificationsComponent, decorators: [{
|
|
2880
|
+
type: Component,
|
|
2881
|
+
args: [{
|
|
2882
|
+
selector: 'app-user-notifications',
|
|
2883
|
+
standalone: true,
|
|
2884
|
+
imports: [CommonModule, BadgeModule, ButtonModule, PaginatorModule, Popover, ProgressSpinnerModule, Tag, Tooltip, TranslatePipe],
|
|
2885
|
+
template: `
|
|
2886
|
+
<button
|
|
2887
|
+
class="layout-topbar-action relative"
|
|
2888
|
+
id="oip-app-topbar-notification-button"
|
|
2889
|
+
type="button"
|
|
2890
|
+
(click)="toggle($event)"
|
|
2891
|
+
[attr.aria-label]="'Notifications: ' + unreadNotificationCount()">
|
|
2892
|
+
<i class="pi pi-bell"></i>
|
|
2893
|
+
@if (unreadNotificationCount() > 0) {
|
|
2894
|
+
<p-badge
|
|
2895
|
+
class="absolute -top-1 -right-1"
|
|
2896
|
+
severity="danger"
|
|
2897
|
+
[badgeSize]="'small'"
|
|
2898
|
+
[value]="unreadNotificationBadge()" />
|
|
2899
|
+
}
|
|
2900
|
+
</button>
|
|
2901
|
+
|
|
2902
|
+
<p-popover #popover styleClass="w-[min(92vw,34rem)]">
|
|
2903
|
+
<div class="flex items-center justify-between gap-3 mb-4">
|
|
2904
|
+
<div class="font-semibold text-lg">
|
|
2905
|
+
{{ 'userNotifications.title' | translate }}
|
|
2087
2906
|
</div>
|
|
2907
|
+
<p-button
|
|
2908
|
+
icon="pi pi-refresh"
|
|
2909
|
+
rounded="true"
|
|
2910
|
+
severity="secondary"
|
|
2911
|
+
text="true"
|
|
2912
|
+
tooltipPosition="bottom"
|
|
2913
|
+
[disabled]="loading"
|
|
2914
|
+
[pTooltip]="'userNotifications.refresh' | translate"
|
|
2915
|
+
(onClick)="loadNotifications()"></p-button>
|
|
2088
2916
|
</div>
|
|
2089
2917
|
|
|
2090
|
-
|
|
2091
|
-
class="
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
<
|
|
2100
|
-
|
|
2918
|
+
@if (loading && notifications.length === 0) {
|
|
2919
|
+
<div class="flex justify-center py-8">
|
|
2920
|
+
<p-progressSpinner style="w-8 h-8"></p-progressSpinner>
|
|
2921
|
+
</div>
|
|
2922
|
+
} @else if (notifications.length === 0) {
|
|
2923
|
+
<div class="text-center py-8 text-surface-500">
|
|
2924
|
+
{{ 'userNotifications.empty' | translate }}
|
|
2925
|
+
</div>
|
|
2926
|
+
} @else {
|
|
2927
|
+
<div class="flex flex-col gap-3 max-h-[26rem] overflow-y-auto pr-1">
|
|
2928
|
+
@for (notification of notifications; track notification.notificationUserId) {
|
|
2929
|
+
<div class="border border-surface-200 dark:border-surface-700 rounded-md p-3">
|
|
2930
|
+
<div class="flex items-start justify-between gap-3">
|
|
2931
|
+
<div class="min-w-0">
|
|
2932
|
+
<div class="font-medium leading-snug break-words">
|
|
2933
|
+
{{ notification.subject }}
|
|
2934
|
+
</div>
|
|
2935
|
+
<div class="text-xs text-surface-500 mt-1">
|
|
2936
|
+
{{ notification.createdAt | date: 'dd.MM.yyyy HH:mm' }}
|
|
2937
|
+
</div>
|
|
2938
|
+
</div>
|
|
2939
|
+
@if (notification.importance) {
|
|
2940
|
+
<p-tag
|
|
2941
|
+
class="shrink-0"
|
|
2942
|
+
[severity]="getImportanceSeverity(notification.importance)"
|
|
2943
|
+
[value]="notification.importance"></p-tag>
|
|
2944
|
+
}
|
|
2945
|
+
</div>
|
|
2101
2946
|
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
id="oip-app-topbar-user-avatar"
|
|
2117
|
-
shape="circle"
|
|
2118
|
-
size="normal"
|
|
2119
|
-
[image]="userService.photoLoaded ? userService.photo : null"
|
|
2120
|
-
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
2121
|
-
</p-avatar>
|
|
2122
|
-
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
2123
|
-
</button>
|
|
2947
|
+
<div class="text-sm text-surface-700 dark:text-surface-200 mt-3 whitespace-pre-line break-words">
|
|
2948
|
+
{{ notification.message }}
|
|
2949
|
+
</div>
|
|
2950
|
+
|
|
2951
|
+
<div class="flex justify-end mt-3">
|
|
2952
|
+
<p-button
|
|
2953
|
+
icon="pi pi-check"
|
|
2954
|
+
size="small"
|
|
2955
|
+
[label]="'userNotifications.markAsRead' | translate"
|
|
2956
|
+
[loading]="readingNotificationId === notification.notificationUserId"
|
|
2957
|
+
(onClick)="markAsRead(notification)"></p-button>
|
|
2958
|
+
</div>
|
|
2959
|
+
</div>
|
|
2960
|
+
}
|
|
2124
2961
|
</div>
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2962
|
+
|
|
2963
|
+
<p-paginator
|
|
2964
|
+
styleClass="mt-3"
|
|
2965
|
+
[first]="skip"
|
|
2966
|
+
[rows]="take"
|
|
2967
|
+
[totalRecords]="totalCount"
|
|
2968
|
+
[rowsPerPageOptions]="[5, 10, 20]"
|
|
2969
|
+
(onPageChange)="onPageChange($event)"></p-paginator>
|
|
2970
|
+
}
|
|
2971
|
+
</p-popover>
|
|
2972
|
+
`
|
|
2973
|
+
}]
|
|
2974
|
+
}], propDecorators: { popover: [{
|
|
2975
|
+
type: ViewChild,
|
|
2976
|
+
args: ['popover']
|
|
2977
|
+
}] } });
|
|
2978
|
+
|
|
2979
|
+
class AppTopbar {
|
|
2980
|
+
constructor() {
|
|
2981
|
+
this.securityService = inject(SecurityService);
|
|
2982
|
+
this.topBarService = inject(TopBarService);
|
|
2983
|
+
this.userService = inject(UserService);
|
|
2984
|
+
this.layoutService = inject(LayoutService);
|
|
2985
|
+
this.logoService = inject(LogoService);
|
|
2986
|
+
this.confirmationService = inject(ConfirmationService);
|
|
2987
|
+
this.translateService = inject(TranslateService);
|
|
2988
|
+
}
|
|
2989
|
+
toggleDarkMode() {
|
|
2990
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
2991
|
+
...state,
|
|
2992
|
+
darkTheme: !state.darkTheme
|
|
2993
|
+
}));
|
|
2994
|
+
}
|
|
2995
|
+
logoutKeyDown($event) {
|
|
2996
|
+
if ($event.key === 'Enter') {
|
|
2997
|
+
$event.preventDefault();
|
|
2998
|
+
this.confirmLogout();
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
3001
|
+
confirmLogout() {
|
|
3002
|
+
this.confirmationService.confirm({
|
|
3003
|
+
header: this.translateService.instant('topbar.logoutConfirmHeader'),
|
|
3004
|
+
message: this.translateService.instant('topbar.logoutConfirmMessage'),
|
|
3005
|
+
icon: 'pi pi-sign-out',
|
|
3006
|
+
rejectButtonProps: {
|
|
3007
|
+
label: this.translateService.instant('topbar.logoutConfirmCancel'),
|
|
3008
|
+
severity: 'secondary',
|
|
3009
|
+
outlined: true
|
|
3010
|
+
},
|
|
3011
|
+
acceptButtonProps: {
|
|
3012
|
+
label: this.translateService.instant('topbar.logoutConfirmAccept'),
|
|
3013
|
+
severity: 'danger'
|
|
3014
|
+
},
|
|
3015
|
+
accept: () => {
|
|
3016
|
+
this.securityService.logout();
|
|
3017
|
+
}
|
|
3018
|
+
});
|
|
3019
|
+
}
|
|
3020
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppTopbar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3021
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppTopbar, isStandalone: true, selector: "app-topbar", providers: [ConfirmationService], ngImport: i0, template: ` <div class="layout-topbar">
|
|
3022
|
+
<p-confirmDialog appendTo="body" />
|
|
2147
3023
|
<div class="layout-topbar-logo-container">
|
|
2148
3024
|
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
2149
3025
|
<i class="pi pi-bars"></i>
|
|
@@ -2169,6 +3045,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2169
3045
|
}
|
|
2170
3046
|
<div class="layout-topbar-actions">
|
|
2171
3047
|
<div class="layout-config-menu">
|
|
3048
|
+
<app-user-notifications />
|
|
2172
3049
|
<p-button
|
|
2173
3050
|
class="layout-topbar-action"
|
|
2174
3051
|
id="oip-app-topbar-theme-button"
|
|
@@ -2219,7 +3096,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2219
3096
|
class="layout-topbar-action"
|
|
2220
3097
|
id="oip-app-topbar-logout-button"
|
|
2221
3098
|
type="button"
|
|
2222
|
-
(click)="
|
|
3099
|
+
(click)="confirmLogout()"
|
|
2223
3100
|
(keydown)="logoutKeyDown($event)">
|
|
2224
3101
|
<i class="pi pi-sign-out"></i>
|
|
2225
3102
|
<span>{{ 'topbar.logout' | translate }}</span>
|
|
@@ -2238,232 +3115,167 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2238
3115
|
</div>
|
|
2239
3116
|
</div>
|
|
2240
3117
|
</div>
|
|
2241
|
-
</div
|
|
2242
|
-
}]
|
|
2243
|
-
}] });
|
|
2244
|
-
|
|
2245
|
-
class FooterComponent {
|
|
2246
|
-
constructor() {
|
|
2247
|
-
this.logoService = inject(LogoService);
|
|
2248
|
-
}
|
|
2249
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2250
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: FooterComponent, isStandalone: true, selector: "app-footer", ngImport: i0, template: `
|
|
2251
|
-
<div class="layout-footer">
|
|
2252
|
-
<div class="flex justify-center flex-1">
|
|
2253
|
-
<div class="mr-2 -my-0.5">
|
|
2254
|
-
<ng-container
|
|
2255
|
-
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 18, height: 18 }"></ng-container>
|
|
2256
|
-
</div>
|
|
2257
|
-
<span class="font-medium">{{ 'app-info.footer' | translate }}</span>
|
|
2258
|
-
</div>
|
|
2259
|
-
<p class="mr-auto">{{ 'app-info.version' | translate }}</p>
|
|
2260
|
-
</div>
|
|
2261
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3118
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$2.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }, { kind: "component", type: Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: TabList, selector: "p-tablist" }, { kind: "component", type: Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: UserNotificationsComponent, selector: "app-user-notifications" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
2262
3119
|
}
|
|
2263
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
3120
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppTopbar, decorators: [{
|
|
2264
3121
|
type: Component,
|
|
2265
3122
|
args: [{
|
|
2266
|
-
selector: 'app-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
"X-Timezone": this.layoutService.timeZone(),
|
|
2307
|
-
Authorization: `Bearer ${securityData}`,
|
|
2308
|
-
},
|
|
2309
|
-
});
|
|
2310
|
-
this.abortControllers = new Map();
|
|
2311
|
-
this.customFetch = (...fetchParams) => fetch(...fetchParams);
|
|
2312
|
-
this.baseApiParams = {
|
|
2313
|
-
credentials: "same-origin",
|
|
2314
|
-
headers: {},
|
|
2315
|
-
redirect: "follow",
|
|
2316
|
-
referrerPolicy: "no-referrer",
|
|
2317
|
-
};
|
|
2318
|
-
this.setSecurityData = (data) => {
|
|
2319
|
-
this.securityData = data;
|
|
2320
|
-
};
|
|
2321
|
-
this.contentFormatters = {
|
|
2322
|
-
[ContentType.Json]: (input) => input !== null && (typeof input === "object" || typeof input === "string")
|
|
2323
|
-
? JSON.stringify(input)
|
|
2324
|
-
: input,
|
|
2325
|
-
[ContentType.JsonApi]: (input) => input !== null && (typeof input === "object" || typeof input === "string")
|
|
2326
|
-
? JSON.stringify(input)
|
|
2327
|
-
: input,
|
|
2328
|
-
[ContentType.Text]: (input) => input !== null && typeof input !== "string"
|
|
2329
|
-
? JSON.stringify(input)
|
|
2330
|
-
: input,
|
|
2331
|
-
[ContentType.FormData]: (input) => {
|
|
2332
|
-
if (input instanceof FormData) {
|
|
2333
|
-
return input;
|
|
2334
|
-
}
|
|
2335
|
-
return Object.keys(input || {}).reduce((formData, key) => {
|
|
2336
|
-
const property = input[key];
|
|
2337
|
-
formData.append(key, property instanceof Blob
|
|
2338
|
-
? property
|
|
2339
|
-
: typeof property === "object" && property !== null
|
|
2340
|
-
? JSON.stringify(property)
|
|
2341
|
-
: `${property}`);
|
|
2342
|
-
return formData;
|
|
2343
|
-
}, new FormData());
|
|
2344
|
-
},
|
|
2345
|
-
[ContentType.UrlEncoded]: (input) => this.toQueryString(input),
|
|
2346
|
-
};
|
|
2347
|
-
this.createAbortSignal = (cancelToken) => {
|
|
2348
|
-
if (this.abortControllers.has(cancelToken)) {
|
|
2349
|
-
const abortController = this.abortControllers.get(cancelToken);
|
|
2350
|
-
if (abortController) {
|
|
2351
|
-
return abortController.signal;
|
|
2352
|
-
}
|
|
2353
|
-
return void 0;
|
|
2354
|
-
}
|
|
2355
|
-
const abortController = new AbortController();
|
|
2356
|
-
this.abortControllers.set(cancelToken, abortController);
|
|
2357
|
-
return abortController.signal;
|
|
2358
|
-
};
|
|
2359
|
-
this.abortRequest = (cancelToken) => {
|
|
2360
|
-
const abortController = this.abortControllers.get(cancelToken);
|
|
2361
|
-
if (abortController) {
|
|
2362
|
-
abortController.abort();
|
|
2363
|
-
this.abortControllers.delete(cancelToken);
|
|
2364
|
-
}
|
|
2365
|
-
};
|
|
2366
|
-
this.request = async ({ body, secure, path, type, query, format, baseUrl, cancelToken, ...params }) => {
|
|
2367
|
-
const secureParams = ((typeof secure === "boolean" ? secure : this.baseApiParams.secure) &&
|
|
2368
|
-
this.securityWorker &&
|
|
2369
|
-
(await this.securityWorker(this.securityData))) ||
|
|
2370
|
-
{};
|
|
2371
|
-
const requestParams = this.mergeRequestParams(params, secureParams);
|
|
2372
|
-
const queryString = query && this.toQueryString(query);
|
|
2373
|
-
const payloadFormatter = this.contentFormatters[type || ContentType.Json];
|
|
2374
|
-
let responseFormat = format || requestParams.format;
|
|
2375
|
-
return this.customFetch(`${baseUrl || this.baseUrl || ""}${path}${queryString ? `?${queryString}` : ""}`, {
|
|
2376
|
-
...requestParams,
|
|
2377
|
-
headers: {
|
|
2378
|
-
...(requestParams.headers || {}),
|
|
2379
|
-
...(type && type !== ContentType.FormData
|
|
2380
|
-
? { "Content-Type": type }
|
|
2381
|
-
: {}),
|
|
2382
|
-
},
|
|
2383
|
-
signal: (cancelToken
|
|
2384
|
-
? this.createAbortSignal(cancelToken)
|
|
2385
|
-
: requestParams.signal) || null,
|
|
2386
|
-
body: typeof body === "undefined" || body === null
|
|
2387
|
-
? null
|
|
2388
|
-
: payloadFormatter(body),
|
|
2389
|
-
}).then(async (response) => {
|
|
2390
|
-
const r = response;
|
|
2391
|
-
r.data = null;
|
|
2392
|
-
r.error = null;
|
|
2393
|
-
if (typeof E !== undefined && responseFormat === undefined)
|
|
2394
|
-
responseFormat = "json";
|
|
2395
|
-
const responseToParse = responseFormat ? response.clone() : response;
|
|
2396
|
-
const data = !responseFormat
|
|
2397
|
-
? r
|
|
2398
|
-
: await responseToParse[responseFormat]()
|
|
2399
|
-
.then((data) => {
|
|
2400
|
-
if (r.ok) {
|
|
2401
|
-
r.data = data;
|
|
2402
|
-
}
|
|
2403
|
-
else {
|
|
2404
|
-
r.error = data;
|
|
2405
|
-
}
|
|
2406
|
-
return r;
|
|
2407
|
-
})
|
|
2408
|
-
.catch((e) => {
|
|
2409
|
-
r.error = e;
|
|
2410
|
-
return r;
|
|
2411
|
-
});
|
|
2412
|
-
if (cancelToken) {
|
|
2413
|
-
this.abortControllers.delete(cancelToken);
|
|
2414
|
-
}
|
|
2415
|
-
if (!response.ok)
|
|
2416
|
-
throw data;
|
|
2417
|
-
return data.data;
|
|
2418
|
-
});
|
|
2419
|
-
};
|
|
2420
|
-
this.securityService.getAccessToken().subscribe((token) => {
|
|
2421
|
-
this.securityData = token;
|
|
2422
|
-
});
|
|
2423
|
-
}
|
|
2424
|
-
encodeQueryParam(key, value) {
|
|
2425
|
-
const encodedKey = encodeURIComponent(key);
|
|
2426
|
-
return `${encodedKey}=${encodeURIComponent(typeof value === "number" ? value : `${value}`)}`;
|
|
2427
|
-
}
|
|
2428
|
-
addQueryParam(query, key) {
|
|
2429
|
-
return this.encodeQueryParam(key, query[key]);
|
|
2430
|
-
}
|
|
2431
|
-
addArrayQueryParam(query, key) {
|
|
2432
|
-
const value = query[key];
|
|
2433
|
-
return value.map((v) => this.encodeQueryParam(key, v)).join("&");
|
|
2434
|
-
}
|
|
2435
|
-
toQueryString(rawQuery) {
|
|
2436
|
-
const query = rawQuery || {};
|
|
2437
|
-
const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
|
|
2438
|
-
return keys
|
|
2439
|
-
.map((key) => Array.isArray(query[key])
|
|
2440
|
-
? this.addArrayQueryParam(query, key)
|
|
2441
|
-
: this.addQueryParam(query, key))
|
|
2442
|
-
.join("&");
|
|
2443
|
-
}
|
|
2444
|
-
addQueryParams(rawQuery) {
|
|
2445
|
-
const queryString = this.toQueryString(rawQuery);
|
|
2446
|
-
return queryString ? `?${queryString}` : "";
|
|
3123
|
+
selector: 'app-topbar',
|
|
3124
|
+
standalone: true,
|
|
3125
|
+
imports: [
|
|
3126
|
+
RouterModule,
|
|
3127
|
+
CommonModule,
|
|
3128
|
+
StyleClassModule,
|
|
3129
|
+
AppConfiguratorComponent,
|
|
3130
|
+
Tabs,
|
|
3131
|
+
TabList,
|
|
3132
|
+
Tab,
|
|
3133
|
+
AvatarModule,
|
|
3134
|
+
ButtonModule,
|
|
3135
|
+
ConfirmDialog,
|
|
3136
|
+
UserNotificationsComponent,
|
|
3137
|
+
TranslatePipe
|
|
3138
|
+
],
|
|
3139
|
+
template: ` <div class="layout-topbar">
|
|
3140
|
+
<p-confirmDialog appendTo="body" />
|
|
3141
|
+
<div class="layout-topbar-logo-container">
|
|
3142
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
3143
|
+
<i class="pi pi-bars"></i>
|
|
3144
|
+
</button>
|
|
3145
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
3146
|
+
<ng-container
|
|
3147
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
3148
|
+
<span>{{ 'app-info.title' | translate }}</span>
|
|
3149
|
+
</a>
|
|
3150
|
+
</div>
|
|
3151
|
+
|
|
3152
|
+
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
3153
|
+
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
3154
|
+
<p-tablist>
|
|
3155
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
3156
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
3157
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
3158
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
3159
|
+
</p-tab>
|
|
3160
|
+
}
|
|
3161
|
+
</p-tablist>
|
|
3162
|
+
</p-tabs>
|
|
2447
3163
|
}
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
3164
|
+
<div class="layout-topbar-actions">
|
|
3165
|
+
<div class="layout-config-menu">
|
|
3166
|
+
<app-user-notifications />
|
|
3167
|
+
<p-button
|
|
3168
|
+
class="layout-topbar-action"
|
|
3169
|
+
id="oip-app-topbar-theme-button"
|
|
3170
|
+
severity="secondary"
|
|
3171
|
+
type="button"
|
|
3172
|
+
[rounded]="true"
|
|
3173
|
+
[text]="true"
|
|
3174
|
+
(click)="toggleDarkMode()">
|
|
3175
|
+
<i
|
|
3176
|
+
class="pi"
|
|
3177
|
+
[ngClass]="{
|
|
3178
|
+
'pi-moon': layoutService.isDarkTheme(),
|
|
3179
|
+
'pi-sun': !layoutService.isDarkTheme()
|
|
3180
|
+
}"></i>
|
|
3181
|
+
</p-button>
|
|
3182
|
+
<div class="relative">
|
|
3183
|
+
<p-button
|
|
3184
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
3185
|
+
enterActiveClass="animate-scalein"
|
|
3186
|
+
enterFromClass="hidden"
|
|
3187
|
+
id="oip-app-topbar-palette-button"
|
|
3188
|
+
leaveActiveClass="animate-fadeout"
|
|
3189
|
+
leaveToClass="hidden"
|
|
3190
|
+
pStyleClass="@next"
|
|
3191
|
+
[hideOnOutsideClick]="true"
|
|
3192
|
+
[rounded]="true">
|
|
3193
|
+
<i class="pi pi-palette"></i>
|
|
3194
|
+
</p-button>
|
|
3195
|
+
<app-configurator />
|
|
3196
|
+
</div>
|
|
3197
|
+
</div>
|
|
3198
|
+
|
|
3199
|
+
<button
|
|
3200
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
3201
|
+
enterActiveClass="animate-scalein"
|
|
3202
|
+
enterFromClass="hidden"
|
|
3203
|
+
id="oip-app-topbar-menu-expand-button"
|
|
3204
|
+
leaveActiveClass="animate-fadeout"
|
|
3205
|
+
leaveToClass="hidden"
|
|
3206
|
+
pStyleClass="@next"
|
|
3207
|
+
[hideOnOutsideClick]="true">
|
|
3208
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
3209
|
+
</button>
|
|
3210
|
+
|
|
3211
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
3212
|
+
<div class="layout-topbar-menu-content">
|
|
3213
|
+
<button
|
|
3214
|
+
class="layout-topbar-action"
|
|
3215
|
+
id="oip-app-topbar-logout-button"
|
|
3216
|
+
type="button"
|
|
3217
|
+
(click)="confirmLogout()"
|
|
3218
|
+
(keydown)="logoutKeyDown($event)">
|
|
3219
|
+
<i class="pi pi-sign-out"></i>
|
|
3220
|
+
<span>{{ 'topbar.logout' | translate }}</span>
|
|
3221
|
+
</button>
|
|
3222
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
3223
|
+
<p-avatar
|
|
3224
|
+
class="p-link flex align-items-center"
|
|
3225
|
+
id="oip-app-topbar-user-avatar"
|
|
3226
|
+
shape="circle"
|
|
3227
|
+
size="normal"
|
|
3228
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
3229
|
+
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
3230
|
+
</p-avatar>
|
|
3231
|
+
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
3232
|
+
</button>
|
|
3233
|
+
</div>
|
|
3234
|
+
</div>
|
|
3235
|
+
</div>
|
|
3236
|
+
</div>`,
|
|
3237
|
+
providers: [ConfirmationService]
|
|
3238
|
+
}]
|
|
3239
|
+
}] });
|
|
3240
|
+
|
|
3241
|
+
class FooterComponent {
|
|
3242
|
+
constructor() {
|
|
3243
|
+
this.logoService = inject(LogoService);
|
|
2459
3244
|
}
|
|
2460
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
2461
|
-
static { this.ɵ
|
|
3245
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3246
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: FooterComponent, isStandalone: true, selector: "app-footer", ngImport: i0, template: `
|
|
3247
|
+
<div class="layout-footer">
|
|
3248
|
+
<div class="flex justify-center flex-1">
|
|
3249
|
+
<div class="mr-2 -my-0.5">
|
|
3250
|
+
<ng-container
|
|
3251
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 18, height: 18 }"></ng-container>
|
|
3252
|
+
</div>
|
|
3253
|
+
<span class="font-medium">{{ 'app-info.footer' | translate }}</span>
|
|
3254
|
+
</div>
|
|
3255
|
+
<p class="mr-auto">{{ 'app-info.version' | translate }}</p>
|
|
3256
|
+
</div>
|
|
3257
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
2462
3258
|
}
|
|
2463
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
2464
|
-
type:
|
|
2465
|
-
args: [{
|
|
2466
|
-
|
|
3259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FooterComponent, decorators: [{
|
|
3260
|
+
type: Component,
|
|
3261
|
+
args: [{
|
|
3262
|
+
selector: 'app-footer',
|
|
3263
|
+
template: `
|
|
3264
|
+
<div class="layout-footer">
|
|
3265
|
+
<div class="flex justify-center flex-1">
|
|
3266
|
+
<div class="mr-2 -my-0.5">
|
|
3267
|
+
<ng-container
|
|
3268
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 18, height: 18 }"></ng-container>
|
|
3269
|
+
</div>
|
|
3270
|
+
<span class="font-medium">{{ 'app-info.footer' | translate }}</span>
|
|
3271
|
+
</div>
|
|
3272
|
+
<p class="mr-auto">{{ 'app-info.version' | translate }}</p>
|
|
3273
|
+
</div>
|
|
3274
|
+
`,
|
|
3275
|
+
standalone: true,
|
|
3276
|
+
imports: [TranslatePipe, NgComponentOutlet]
|
|
3277
|
+
}]
|
|
3278
|
+
}] });
|
|
2467
3279
|
|
|
2468
3280
|
/* eslint-disable */
|
|
2469
3281
|
/* tslint:disable */
|
|
@@ -2530,9 +3342,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2530
3342
|
type: Injectable
|
|
2531
3343
|
}] });
|
|
2532
3344
|
|
|
2533
|
-
class MenuService
|
|
3345
|
+
class MenuService {
|
|
2534
3346
|
constructor() {
|
|
2535
|
-
super(...arguments);
|
|
2536
3347
|
this.menuSource = new Subject();
|
|
2537
3348
|
this.resetSource = new Subject();
|
|
2538
3349
|
this.titleService = inject(AppTitleService);
|
|
@@ -2552,7 +3363,9 @@ class MenuService extends BaseDataService {
|
|
|
2552
3363
|
*/
|
|
2553
3364
|
onMenuStateChange(event) {
|
|
2554
3365
|
this.menuSource.next(event);
|
|
2555
|
-
|
|
3366
|
+
if (!event.item.items?.length) {
|
|
3367
|
+
this.titleService.setTitle(event.item.label);
|
|
3368
|
+
}
|
|
2556
3369
|
}
|
|
2557
3370
|
reset() {
|
|
2558
3371
|
this.resetSource.next(true);
|
|
@@ -2575,7 +3388,7 @@ class MenuService extends BaseDataService {
|
|
|
2575
3388
|
editModuleInstance(item) {
|
|
2576
3389
|
return this.menuDataService.editModuleInstance(item);
|
|
2577
3390
|
}
|
|
2578
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuService, deps:
|
|
3391
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2579
3392
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuService }); }
|
|
2580
3393
|
}
|
|
2581
3394
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuService, decorators: [{
|
|
@@ -2592,17 +3405,15 @@ class MenuItemComponent {
|
|
|
2592
3405
|
this.confirmationService = inject(ConfirmationService);
|
|
2593
3406
|
this.msgService = inject(MsgService);
|
|
2594
3407
|
this.menuDataService = inject(MenuApi);
|
|
3408
|
+
this.securityService = inject(SecurityService);
|
|
2595
3409
|
this.active = false;
|
|
2596
3410
|
this.subscriptions = [];
|
|
2597
3411
|
this.localization = {};
|
|
2598
3412
|
this.key = '';
|
|
2599
3413
|
this.subscriptions.push(this.menuService.menuSource$.subscribe((value) => {
|
|
2600
3414
|
Promise.resolve(null).then(() => {
|
|
2601
|
-
if (value.routeEvent) {
|
|
2602
|
-
this.active =
|
|
2603
|
-
}
|
|
2604
|
-
else if (value.key !== this.key && !value.key.startsWith(this.key + '-')) {
|
|
2605
|
-
this.active = false;
|
|
3415
|
+
if (value.routeEvent && (value.key === this.key || value.key.startsWith(this.key + '-'))) {
|
|
3416
|
+
this.active = true;
|
|
2606
3417
|
}
|
|
2607
3418
|
});
|
|
2608
3419
|
}));
|
|
@@ -2655,8 +3466,8 @@ class MenuItemComponent {
|
|
|
2655
3466
|
}
|
|
2656
3467
|
this.menuService.onMenuStateChange({ key: this.key, item: this.item });
|
|
2657
3468
|
}
|
|
2658
|
-
get
|
|
2659
|
-
return this.root || this.active
|
|
3469
|
+
get isSubmenuExpanded() {
|
|
3470
|
+
return this.root || this.active;
|
|
2660
3471
|
}
|
|
2661
3472
|
get activeClass() {
|
|
2662
3473
|
return this.active && !this.root;
|
|
@@ -2668,6 +3479,11 @@ class MenuItemComponent {
|
|
|
2668
3479
|
this.menuItemCreateDialogComponent.showDialog();
|
|
2669
3480
|
}
|
|
2670
3481
|
onContextMenu($event, item) {
|
|
3482
|
+
if (!this.securityService.isAdmin()) {
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
$event.stopPropagation();
|
|
3486
|
+
$event.preventDefault();
|
|
2671
3487
|
this.menuService.contextMenuItem = item;
|
|
2672
3488
|
this.contextMenu.model = [
|
|
2673
3489
|
{
|
|
@@ -2787,19 +3603,32 @@ class MenuItemComponent {
|
|
|
2787
3603
|
hasVisiblePrev(currentItem) {
|
|
2788
3604
|
const items = this.getItems(currentItem);
|
|
2789
3605
|
const currentIndex = items.findIndex((item) => item.moduleInstanceId == currentItem.moduleInstanceId);
|
|
2790
|
-
return currentIndex
|
|
3606
|
+
return this.findPrevVisibleItem(items, currentIndex) !== -1;
|
|
2791
3607
|
}
|
|
2792
3608
|
getItems(currentItem) {
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
3609
|
+
if (!currentItem.parentId) {
|
|
3610
|
+
return this.menuService.menu;
|
|
3611
|
+
}
|
|
3612
|
+
return this.findItemByModuleInstanceId(this.menuService.menu, currentItem.parentId)?.items ?? [];
|
|
3613
|
+
}
|
|
3614
|
+
findItemByModuleInstanceId(items, moduleInstanceId) {
|
|
3615
|
+
for (const item of items) {
|
|
3616
|
+
if (item.moduleInstanceId == moduleInstanceId) {
|
|
3617
|
+
return item;
|
|
3618
|
+
}
|
|
3619
|
+
const foundItem = this.findItemByModuleInstanceId(item.items ?? [], moduleInstanceId);
|
|
3620
|
+
if (foundItem) {
|
|
3621
|
+
return foundItem;
|
|
3622
|
+
}
|
|
3623
|
+
}
|
|
3624
|
+
return null;
|
|
2796
3625
|
}
|
|
2797
3626
|
hasVisibleNext(currentItem) {
|
|
2798
3627
|
const items = this.getItems(currentItem);
|
|
2799
3628
|
const currentIndex = items.findIndex((item) => item.moduleInstanceId == currentItem.moduleInstanceId);
|
|
2800
|
-
return currentIndex
|
|
3629
|
+
return this.findNextVisibleIndex(items, currentIndex) !== -1;
|
|
2801
3630
|
}
|
|
2802
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$
|
|
3631
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$4.Router }, { token: MenuService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2803
3632
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: MenuItemComponent, isStandalone: true, selector: "[app-menuitem]", inputs: { item: "item", index: "index", root: "root", parentKey: "parentKey", menuItemCreateDialogComponent: "menuItemCreateDialogComponent", menuItemEditDialogComponent: "menuItemEditDialogComponent", contextMenu: "contextMenu" }, host: { properties: { "class.layout-root-menuitem": "this.root", "class.active-menuitem": "this.activeClass" } }, providers: [ConfirmationService], ngImport: i0, template: `
|
|
2804
3633
|
<ng-container>
|
|
2805
3634
|
<p-confirm-dialog />
|
|
@@ -2815,7 +3644,8 @@ class MenuItemComponent {
|
|
|
2815
3644
|
[attr.href]="item.url"
|
|
2816
3645
|
[attr.target]="item.target"
|
|
2817
3646
|
[ngClass]="item.class"
|
|
2818
|
-
(click)="itemClick($event)"
|
|
3647
|
+
(click)="itemClick($event)"
|
|
3648
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2819
3649
|
<i class="layout-menuitem-icon" [ngClass]="item.icon"></i>
|
|
2820
3650
|
<span class="layout-menuitem-text">{{ item.label }}</span>
|
|
2821
3651
|
@if (item.items) {
|
|
@@ -2857,7 +3687,7 @@ class MenuItemComponent {
|
|
|
2857
3687
|
}
|
|
2858
3688
|
|
|
2859
3689
|
@if (item.items && item.visible !== false) {
|
|
2860
|
-
<ul
|
|
3690
|
+
<ul class="layout-submenu" [class.layout-submenu-expanded]="isSubmenuExpanded">
|
|
2861
3691
|
@for (child of item.items; track child; let i = $index) {
|
|
2862
3692
|
<li
|
|
2863
3693
|
app-menuitem
|
|
@@ -2872,17 +3702,7 @@ class MenuItemComponent {
|
|
|
2872
3702
|
</ul>
|
|
2873
3703
|
}
|
|
2874
3704
|
</ng-container>
|
|
2875
|
-
`, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i3$
|
|
2876
|
-
trigger('children', [
|
|
2877
|
-
state('collapsed', style({
|
|
2878
|
-
height: '0'
|
|
2879
|
-
})),
|
|
2880
|
-
state('expanded', style({
|
|
2881
|
-
height: '*'
|
|
2882
|
-
})),
|
|
2883
|
-
transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
|
|
2884
|
-
])
|
|
2885
|
-
] }); }
|
|
3705
|
+
`, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i3$3.Ripple, selector: "[pRipple]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }] }); }
|
|
2886
3706
|
}
|
|
2887
3707
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemComponent, decorators: [{
|
|
2888
3708
|
type: Component,
|
|
@@ -2904,7 +3724,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2904
3724
|
[attr.href]="item.url"
|
|
2905
3725
|
[attr.target]="item.target"
|
|
2906
3726
|
[ngClass]="item.class"
|
|
2907
|
-
(click)="itemClick($event)"
|
|
3727
|
+
(click)="itemClick($event)"
|
|
3728
|
+
(contextmenu)="onContextMenu($event, item)">
|
|
2908
3729
|
<i class="layout-menuitem-icon" [ngClass]="item.icon"></i>
|
|
2909
3730
|
<span class="layout-menuitem-text">{{ item.label }}</span>
|
|
2910
3731
|
@if (item.items) {
|
|
@@ -2946,7 +3767,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2946
3767
|
}
|
|
2947
3768
|
|
|
2948
3769
|
@if (item.items && item.visible !== false) {
|
|
2949
|
-
<ul
|
|
3770
|
+
<ul class="layout-submenu" [class.layout-submenu-expanded]="isSubmenuExpanded">
|
|
2950
3771
|
@for (child of item.items; track child; let i = $index) {
|
|
2951
3772
|
<li
|
|
2952
3773
|
app-menuitem
|
|
@@ -2962,21 +3783,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
2962
3783
|
}
|
|
2963
3784
|
</ng-container>
|
|
2964
3785
|
`,
|
|
2965
|
-
animations: [
|
|
2966
|
-
trigger('children', [
|
|
2967
|
-
state('collapsed', style({
|
|
2968
|
-
height: '0'
|
|
2969
|
-
})),
|
|
2970
|
-
state('expanded', style({
|
|
2971
|
-
height: '*'
|
|
2972
|
-
})),
|
|
2973
|
-
transition('collapsed <=> expanded', animate('400ms cubic-bezier(0.86, 0, 0.07, 1)'))
|
|
2974
|
-
])
|
|
2975
|
-
],
|
|
2976
3786
|
imports: [RippleModule, NgClass, RouterLinkActive, RouterLink, ContextMenuModule, ConfirmDialog],
|
|
2977
3787
|
providers: [ConfirmationService]
|
|
2978
3788
|
}]
|
|
2979
|
-
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$
|
|
3789
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$4.Router }, { type: MenuService }], propDecorators: { item: [{
|
|
2980
3790
|
type: Input
|
|
2981
3791
|
}], index: [{
|
|
2982
3792
|
type: Input
|
|
@@ -3002,9 +3812,21 @@ class MenuItemCreateDialogComponent {
|
|
|
3002
3812
|
constructor() {
|
|
3003
3813
|
this.menuService = inject(MenuService);
|
|
3004
3814
|
this.menu = inject(MenuApi);
|
|
3815
|
+
this.msgService = inject(MsgService);
|
|
3005
3816
|
this.visibleChange = new EventEmitter();
|
|
3006
3817
|
this.modules = [];
|
|
3818
|
+
this.iconOptions = Object.values(PrimeIcons)
|
|
3819
|
+
.filter((icon) => typeof icon === 'string')
|
|
3820
|
+
.map((icon) => ({
|
|
3821
|
+
label: icon.replace('pi pi-', ''),
|
|
3822
|
+
value: icon
|
|
3823
|
+
}))
|
|
3824
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
3007
3825
|
this.selectIcon = 'pi pi-box';
|
|
3826
|
+
this.saving = false;
|
|
3827
|
+
}
|
|
3828
|
+
get canSave() {
|
|
3829
|
+
return !this.saving && !!this.selectModule;
|
|
3008
3830
|
}
|
|
3009
3831
|
async ngOnInit() {
|
|
3010
3832
|
this.modules = await this.menu.getModules();
|
|
@@ -3014,15 +3836,30 @@ class MenuItemCreateDialogComponent {
|
|
|
3014
3836
|
this.visibleChange.emit(this.visible);
|
|
3015
3837
|
}
|
|
3016
3838
|
async save() {
|
|
3839
|
+
if (this.saving) {
|
|
3840
|
+
return;
|
|
3841
|
+
}
|
|
3842
|
+
if (!this.selectModule) {
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3017
3845
|
const item = {
|
|
3018
3846
|
moduleId: this.selectModule,
|
|
3019
3847
|
label: this.label,
|
|
3020
3848
|
icon: this.selectIcon,
|
|
3021
3849
|
parentId: this.menuService.contextMenuItem?.moduleInstanceId
|
|
3022
3850
|
};
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3851
|
+
this.saving = true;
|
|
3852
|
+
try {
|
|
3853
|
+
await this.menuService.addModuleInstance(item);
|
|
3854
|
+
await this.menuService.loadMenu();
|
|
3855
|
+
this.hide();
|
|
3856
|
+
}
|
|
3857
|
+
catch (error) {
|
|
3858
|
+
this.msgService.errorFromException(error, 'Unexpected error');
|
|
3859
|
+
}
|
|
3860
|
+
finally {
|
|
3861
|
+
this.saving = false;
|
|
3862
|
+
}
|
|
3026
3863
|
}
|
|
3027
3864
|
hide() {
|
|
3028
3865
|
this.visible = false;
|
|
@@ -3038,7 +3875,8 @@ class MenuItemCreateDialogComponent {
|
|
|
3038
3875
|
header="{{ 'menuItemCreateDialogComponent.header' | translate }}"
|
|
3039
3876
|
[modal]="true"
|
|
3040
3877
|
[style]="{ width: '40rem' }"
|
|
3041
|
-
[(visible)]="visible"
|
|
3878
|
+
[(visible)]="visible"
|
|
3879
|
+
(keydown.enter)="save()">
|
|
3042
3880
|
@if (menuService.contextMenuItem) {
|
|
3043
3881
|
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
3044
3882
|
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-parent-input">
|
|
@@ -3077,24 +3915,47 @@ class MenuItemCreateDialogComponent {
|
|
|
3077
3915
|
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-icon">
|
|
3078
3916
|
{{ 'menuItemCreateDialogComponent.icon' | translate }}
|
|
3079
3917
|
</label>
|
|
3080
|
-
<
|
|
3081
|
-
|
|
3918
|
+
<p-select
|
|
3919
|
+
appendTo="body"
|
|
3920
|
+
class="flex-auto"
|
|
3921
|
+
filterBy="label,value"
|
|
3922
|
+
id="oip-menu-item-create-dialog-icon"
|
|
3923
|
+
optionLabel="label"
|
|
3924
|
+
optionValue="value"
|
|
3925
|
+
scrollHeight="18rem"
|
|
3926
|
+
[filter]="true"
|
|
3927
|
+
[options]="iconOptions"
|
|
3928
|
+
[(ngModel)]="selectIcon">
|
|
3929
|
+
<ng-template let-icon pTemplate="selectedItem">
|
|
3930
|
+
<div class="flex items-center gap-2">
|
|
3931
|
+
<i [class]="icon.value"></i>
|
|
3932
|
+
<span>{{ icon.label }}</span>
|
|
3933
|
+
</div>
|
|
3934
|
+
</ng-template>
|
|
3935
|
+
<ng-template let-icon pTemplate="item">
|
|
3936
|
+
<div class="flex items-center gap-2">
|
|
3937
|
+
<i [class]="icon.value"></i>
|
|
3938
|
+
<span>{{ icon.label }}</span>
|
|
3939
|
+
</div>
|
|
3940
|
+
</ng-template>
|
|
3941
|
+
</p-select>
|
|
3082
3942
|
</div>
|
|
3083
3943
|
<div class="flex justify-end gap-2">
|
|
3084
3944
|
<p-button
|
|
3085
3945
|
id="oip-menu-item-create-cancel"
|
|
3086
3946
|
label="{{ 'menuItemCreateDialogComponent.cancel' | translate }}"
|
|
3087
3947
|
severity="secondary"
|
|
3088
|
-
|
|
3089
|
-
(
|
|
3948
|
+
[disabled]="saving"
|
|
3949
|
+
(click)="changeVisible()" />
|
|
3090
3950
|
<p-button
|
|
3091
3951
|
id="oip-menu-item-create-save"
|
|
3092
3952
|
label="{{ 'menuItemCreateDialogComponent.save' | translate }}"
|
|
3093
|
-
|
|
3094
|
-
|
|
3953
|
+
[disabled]="!canSave"
|
|
3954
|
+
[loading]="saving"
|
|
3955
|
+
(click)="save()" />
|
|
3095
3956
|
</div>
|
|
3096
3957
|
</p-dialog>
|
|
3097
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type:
|
|
3958
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i3$4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3098
3959
|
}
|
|
3099
3960
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemCreateDialogComponent, decorators: [{
|
|
3100
3961
|
type: Component,
|
|
@@ -3107,7 +3968,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3107
3968
|
header="{{ 'menuItemCreateDialogComponent.header' | translate }}"
|
|
3108
3969
|
[modal]="true"
|
|
3109
3970
|
[style]="{ width: '40rem' }"
|
|
3110
|
-
[(visible)]="visible"
|
|
3971
|
+
[(visible)]="visible"
|
|
3972
|
+
(keydown.enter)="save()">
|
|
3111
3973
|
@if (menuService.contextMenuItem) {
|
|
3112
3974
|
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
3113
3975
|
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-parent-input">
|
|
@@ -3146,21 +4008,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3146
4008
|
<label class="font-semibold w-1/3" for="oip-menu-item-create-dialog-icon">
|
|
3147
4009
|
{{ 'menuItemCreateDialogComponent.icon' | translate }}
|
|
3148
4010
|
</label>
|
|
3149
|
-
<
|
|
3150
|
-
|
|
4011
|
+
<p-select
|
|
4012
|
+
appendTo="body"
|
|
4013
|
+
class="flex-auto"
|
|
4014
|
+
filterBy="label,value"
|
|
4015
|
+
id="oip-menu-item-create-dialog-icon"
|
|
4016
|
+
optionLabel="label"
|
|
4017
|
+
optionValue="value"
|
|
4018
|
+
scrollHeight="18rem"
|
|
4019
|
+
[filter]="true"
|
|
4020
|
+
[options]="iconOptions"
|
|
4021
|
+
[(ngModel)]="selectIcon">
|
|
4022
|
+
<ng-template let-icon pTemplate="selectedItem">
|
|
4023
|
+
<div class="flex items-center gap-2">
|
|
4024
|
+
<i [class]="icon.value"></i>
|
|
4025
|
+
<span>{{ icon.label }}</span>
|
|
4026
|
+
</div>
|
|
4027
|
+
</ng-template>
|
|
4028
|
+
<ng-template let-icon pTemplate="item">
|
|
4029
|
+
<div class="flex items-center gap-2">
|
|
4030
|
+
<i [class]="icon.value"></i>
|
|
4031
|
+
<span>{{ icon.label }}</span>
|
|
4032
|
+
</div>
|
|
4033
|
+
</ng-template>
|
|
4034
|
+
</p-select>
|
|
3151
4035
|
</div>
|
|
3152
4036
|
<div class="flex justify-end gap-2">
|
|
3153
4037
|
<p-button
|
|
3154
4038
|
id="oip-menu-item-create-cancel"
|
|
3155
4039
|
label="{{ 'menuItemCreateDialogComponent.cancel' | translate }}"
|
|
3156
4040
|
severity="secondary"
|
|
3157
|
-
|
|
3158
|
-
(
|
|
4041
|
+
[disabled]="saving"
|
|
4042
|
+
(click)="changeVisible()" />
|
|
3159
4043
|
<p-button
|
|
3160
4044
|
id="oip-menu-item-create-save"
|
|
3161
4045
|
label="{{ 'menuItemCreateDialogComponent.save' | translate }}"
|
|
3162
|
-
|
|
3163
|
-
|
|
4046
|
+
[disabled]="!canSave"
|
|
4047
|
+
[loading]="saving"
|
|
4048
|
+
(click)="save()" />
|
|
3164
4049
|
</div>
|
|
3165
4050
|
</p-dialog>
|
|
3166
4051
|
`
|
|
@@ -3174,10 +4059,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3174
4059
|
class MenuItemEditDialogComponent {
|
|
3175
4060
|
constructor() {
|
|
3176
4061
|
this.menuService = inject(MenuService);
|
|
3177
|
-
this.
|
|
4062
|
+
this.securityApi = inject(SecurityApi);
|
|
4063
|
+
this.msgService = inject(MsgService);
|
|
3178
4064
|
this.visibleChange = new EventEmitter();
|
|
3179
4065
|
this.modules = [];
|
|
3180
4066
|
this.roles = [];
|
|
4067
|
+
this.iconOptions = Object.values(PrimeIcons)
|
|
4068
|
+
.filter((icon) => typeof icon === 'string')
|
|
4069
|
+
.map((icon) => ({
|
|
4070
|
+
label: icon.replace('pi pi-', ''),
|
|
4071
|
+
value: icon
|
|
4072
|
+
}))
|
|
4073
|
+
.sort((left, right) => left.label.localeCompare(right.label));
|
|
3181
4074
|
this.item = {
|
|
3182
4075
|
icon: '',
|
|
3183
4076
|
label: '',
|
|
@@ -3186,15 +4079,28 @@ class MenuItemEditDialogComponent {
|
|
|
3186
4079
|
moduleInstanceId: 0,
|
|
3187
4080
|
parentId: 0
|
|
3188
4081
|
};
|
|
4082
|
+
this.saving = false;
|
|
3189
4083
|
}
|
|
3190
4084
|
changeVisible() {
|
|
3191
4085
|
this.visible = !this.visible;
|
|
3192
4086
|
this.visibleChange.emit(this.visible);
|
|
3193
4087
|
}
|
|
3194
4088
|
async save() {
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
4089
|
+
if (this.saving) {
|
|
4090
|
+
return;
|
|
4091
|
+
}
|
|
4092
|
+
this.saving = true;
|
|
4093
|
+
try {
|
|
4094
|
+
await this.menuService.editModuleInstance(this.item);
|
|
4095
|
+
await this.menuService.loadMenu();
|
|
4096
|
+
this.hide();
|
|
4097
|
+
}
|
|
4098
|
+
catch (error) {
|
|
4099
|
+
this.msgService.error(error);
|
|
4100
|
+
}
|
|
4101
|
+
finally {
|
|
4102
|
+
this.saving = false;
|
|
4103
|
+
}
|
|
3198
4104
|
}
|
|
3199
4105
|
hide() {
|
|
3200
4106
|
this.visible = false;
|
|
@@ -3209,7 +4115,7 @@ class MenuItemEditDialogComponent {
|
|
|
3209
4115
|
icon: this.menuService.contextMenuItem?.icon,
|
|
3210
4116
|
viewRoles: this.menuService.contextMenuItem?.securities
|
|
3211
4117
|
};
|
|
3212
|
-
this.roles = await this.
|
|
4118
|
+
this.roles = await this.securityApi.getRealmRoles();
|
|
3213
4119
|
this.menuService.getModules().then((data) => {
|
|
3214
4120
|
this.modules = data;
|
|
3215
4121
|
});
|
|
@@ -3222,7 +4128,8 @@ class MenuItemEditDialogComponent {
|
|
|
3222
4128
|
header="{{ 'menuItemEditDialogComponent.header' | translate }}"
|
|
3223
4129
|
[modal]="true"
|
|
3224
4130
|
[style]="{ width: '40rem' }"
|
|
3225
|
-
[(visible)]="visible"
|
|
4131
|
+
[(visible)]="visible"
|
|
4132
|
+
(keydown.enter)="save()">
|
|
3226
4133
|
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
3227
4134
|
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-menu-input">
|
|
3228
4135
|
{{ 'menuItemEditDialogComponent.label' | translate }}
|
|
@@ -3239,8 +4146,30 @@ class MenuItemEditDialogComponent {
|
|
|
3239
4146
|
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-icon">
|
|
3240
4147
|
{{ 'menuItemEditDialogComponent.icon' | translate }}
|
|
3241
4148
|
</label>
|
|
3242
|
-
<
|
|
3243
|
-
|
|
4149
|
+
<p-select
|
|
4150
|
+
appendTo="body"
|
|
4151
|
+
class="flex-auto"
|
|
4152
|
+
filterBy="label,value"
|
|
4153
|
+
id="oip-menu-item-edit-dialog-icon"
|
|
4154
|
+
optionLabel="label"
|
|
4155
|
+
optionValue="value"
|
|
4156
|
+
scrollHeight="18rem"
|
|
4157
|
+
[filter]="true"
|
|
4158
|
+
[options]="iconOptions"
|
|
4159
|
+
[(ngModel)]="item.icon">
|
|
4160
|
+
<ng-template let-icon pTemplate="selectedItem">
|
|
4161
|
+
<div class="flex items-center gap-2">
|
|
4162
|
+
<i [class]="icon.value"></i>
|
|
4163
|
+
<span>{{ icon.label }}</span>
|
|
4164
|
+
</div>
|
|
4165
|
+
</ng-template>
|
|
4166
|
+
<ng-template let-icon pTemplate="item">
|
|
4167
|
+
<div class="flex items-center gap-2">
|
|
4168
|
+
<i [class]="icon.value"></i>
|
|
4169
|
+
<span>{{ icon.label }}</span>
|
|
4170
|
+
</div>
|
|
4171
|
+
</ng-template>
|
|
4172
|
+
</p-select>
|
|
3244
4173
|
</div>
|
|
3245
4174
|
|
|
3246
4175
|
<div class="flex items-center gap-4 mb-4">
|
|
@@ -3262,21 +4191,22 @@ class MenuItemEditDialogComponent {
|
|
|
3262
4191
|
id="oip-menu-item-edit-dialog-cancel-edit-button"
|
|
3263
4192
|
label="{{ 'menuItemEditDialogComponent.cancel' | translate }}"
|
|
3264
4193
|
severity="secondary"
|
|
3265
|
-
|
|
3266
|
-
(
|
|
4194
|
+
[disabled]="saving"
|
|
4195
|
+
(click)="changeVisible()" />
|
|
3267
4196
|
<p-button
|
|
3268
4197
|
id="oip-menu-item-edit-dialog-save-edit-button"
|
|
3269
4198
|
label="{{ 'menuItemEditDialogComponent.save' | translate }}"
|
|
3270
|
-
|
|
3271
|
-
|
|
4199
|
+
[disabled]="saving"
|
|
4200
|
+
[loading]="saving"
|
|
4201
|
+
(click)="save()" />
|
|
3272
4202
|
</div>
|
|
3273
4203
|
</p-dialog>
|
|
3274
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type:
|
|
4204
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: DialogModule }, { kind: "component", type: i3$4.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i1.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3275
4205
|
}
|
|
3276
4206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuItemEditDialogComponent, decorators: [{
|
|
3277
4207
|
type: Component,
|
|
3278
4208
|
args: [{
|
|
3279
|
-
imports: [ButtonModule, DialogModule, InputTextModule, FormsModule, TranslatePipe, MultiSelectModule],
|
|
4209
|
+
imports: [ButtonModule, DialogModule, InputTextModule, SelectModule, FormsModule, TranslatePipe, MultiSelectModule],
|
|
3280
4210
|
selector: 'menu-item-edit-dialog',
|
|
3281
4211
|
standalone: true,
|
|
3282
4212
|
template: `
|
|
@@ -3284,7 +4214,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3284
4214
|
header="{{ 'menuItemEditDialogComponent.header' | translate }}"
|
|
3285
4215
|
[modal]="true"
|
|
3286
4216
|
[style]="{ width: '40rem' }"
|
|
3287
|
-
[(visible)]="visible"
|
|
4217
|
+
[(visible)]="visible"
|
|
4218
|
+
(keydown.enter)="save()">
|
|
3288
4219
|
<div class="flex items-center gap-4 mb-4 mt-1">
|
|
3289
4220
|
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-menu-input">
|
|
3290
4221
|
{{ 'menuItemEditDialogComponent.label' | translate }}
|
|
@@ -3301,8 +4232,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3301
4232
|
<label class="font-semibold w-1/3" for="oip-menu-item-edit-dialog-icon">
|
|
3302
4233
|
{{ 'menuItemEditDialogComponent.icon' | translate }}
|
|
3303
4234
|
</label>
|
|
3304
|
-
<
|
|
3305
|
-
|
|
4235
|
+
<p-select
|
|
4236
|
+
appendTo="body"
|
|
4237
|
+
class="flex-auto"
|
|
4238
|
+
filterBy="label,value"
|
|
4239
|
+
id="oip-menu-item-edit-dialog-icon"
|
|
4240
|
+
optionLabel="label"
|
|
4241
|
+
optionValue="value"
|
|
4242
|
+
scrollHeight="18rem"
|
|
4243
|
+
[filter]="true"
|
|
4244
|
+
[options]="iconOptions"
|
|
4245
|
+
[(ngModel)]="item.icon">
|
|
4246
|
+
<ng-template let-icon pTemplate="selectedItem">
|
|
4247
|
+
<div class="flex items-center gap-2">
|
|
4248
|
+
<i [class]="icon.value"></i>
|
|
4249
|
+
<span>{{ icon.label }}</span>
|
|
4250
|
+
</div>
|
|
4251
|
+
</ng-template>
|
|
4252
|
+
<ng-template let-icon pTemplate="item">
|
|
4253
|
+
<div class="flex items-center gap-2">
|
|
4254
|
+
<i [class]="icon.value"></i>
|
|
4255
|
+
<span>{{ icon.label }}</span>
|
|
4256
|
+
</div>
|
|
4257
|
+
</ng-template>
|
|
4258
|
+
</p-select>
|
|
3306
4259
|
</div>
|
|
3307
4260
|
|
|
3308
4261
|
<div class="flex items-center gap-4 mb-4">
|
|
@@ -3324,13 +4277,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3324
4277
|
id="oip-menu-item-edit-dialog-cancel-edit-button"
|
|
3325
4278
|
label="{{ 'menuItemEditDialogComponent.cancel' | translate }}"
|
|
3326
4279
|
severity="secondary"
|
|
3327
|
-
|
|
3328
|
-
(
|
|
4280
|
+
[disabled]="saving"
|
|
4281
|
+
(click)="changeVisible()" />
|
|
3329
4282
|
<p-button
|
|
3330
4283
|
id="oip-menu-item-edit-dialog-save-edit-button"
|
|
3331
4284
|
label="{{ 'menuItemEditDialogComponent.save' | translate }}"
|
|
3332
|
-
|
|
3333
|
-
|
|
4285
|
+
[disabled]="saving"
|
|
4286
|
+
[loading]="saving"
|
|
4287
|
+
(click)="save()" />
|
|
3334
4288
|
</div>
|
|
3335
4289
|
</p-dialog>
|
|
3336
4290
|
`
|
|
@@ -3354,6 +4308,9 @@ class MenuComponent {
|
|
|
3354
4308
|
this.menuItemCreateDialogComponent.showDialog();
|
|
3355
4309
|
}
|
|
3356
4310
|
onContextMenu($event) {
|
|
4311
|
+
if (!this.securityService.isAdmin()) {
|
|
4312
|
+
return;
|
|
4313
|
+
}
|
|
3357
4314
|
this.menuService.contextMenuItem = null;
|
|
3358
4315
|
this.contextMenu.model = [
|
|
3359
4316
|
{
|
|
@@ -3385,11 +4342,11 @@ class MenuComponent {
|
|
|
3385
4342
|
}
|
|
3386
4343
|
</ul>
|
|
3387
4344
|
</div>
|
|
3388
|
-
<p-contextMenu [target]="empty"/>
|
|
3389
4345
|
@if (securityService.isAdmin()) {
|
|
4346
|
+
<p-contextMenu [target]="empty"/>
|
|
3390
4347
|
<menu-item-create-dialog/>
|
|
3391
4348
|
<menu-item-edit-dialog/>
|
|
3392
|
-
}`, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i1$
|
|
4349
|
+
}`, isInline: true, dependencies: [{ kind: "component", type: MenuItemComponent, selector: "[app-menuitem]", inputs: ["item", "index", "root", "parentKey", "menuItemCreateDialogComponent", "menuItemEditDialogComponent", "contextMenu"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "ngmodule", type: ContextMenuModule }, { kind: "component", type: i1$5.ContextMenu, selector: "p-contextMenu, p-contextmenu, p-context-menu", inputs: ["model", "triggerEvent", "target", "global", "style", "styleClass", "autoZIndex", "baseZIndex", "id", "breakpoint", "ariaLabel", "ariaLabelledBy", "pressDelay", "appendTo"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DialogModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "component", type: MenuItemCreateDialogComponent, selector: "menu-item-create-dialog", inputs: ["visible"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: MenuItemEditDialogComponent, selector: "menu-item-edit-dialog", inputs: ["visible"], outputs: ["visibleChange"] }] }); }
|
|
3393
4350
|
}
|
|
3394
4351
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuComponent, decorators: [{
|
|
3395
4352
|
type: Component,
|
|
@@ -3428,8 +4385,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3428
4385
|
}
|
|
3429
4386
|
</ul>
|
|
3430
4387
|
</div>
|
|
3431
|
-
<p-contextMenu [target]="empty"/>
|
|
3432
4388
|
@if (securityService.isAdmin()) {
|
|
4389
|
+
<p-contextMenu [target]="empty"/>
|
|
3433
4390
|
<menu-item-create-dialog/>
|
|
3434
4391
|
<menu-item-edit-dialog/>
|
|
3435
4392
|
}`
|
|
@@ -3550,7 +4507,7 @@ class AppLayoutComponent {
|
|
|
3550
4507
|
</div>
|
|
3551
4508
|
<div class="layout-mask animate-fadein"></div>
|
|
3552
4509
|
</div>
|
|
3553
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "app-topbar" }, { kind: "component", type: SidebarComponent, selector: "app-sidebar" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$
|
|
4510
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AppTopbar, selector: "app-topbar" }, { kind: "component", type: SidebarComponent, selector: "app-sidebar" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$4.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "component", type: FooterComponent, selector: "app-footer" }] }); }
|
|
3554
4511
|
}
|
|
3555
4512
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppLayoutComponent, decorators: [{
|
|
3556
4513
|
type: Component,
|
|
@@ -3617,7 +4574,7 @@ class AppFloatingConfiguratorComponent {
|
|
|
3617
4574
|
<app-configurator />
|
|
3618
4575
|
</div>
|
|
3619
4576
|
</div>
|
|
3620
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$
|
|
4577
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$2.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }] }); }
|
|
3621
4578
|
}
|
|
3622
4579
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppFloatingConfiguratorComponent, decorators: [{
|
|
3623
4580
|
type: Component,
|
|
@@ -3711,70 +4668,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3711
4668
|
|
|
3712
4669
|
class UnauthorizedComponent {
|
|
3713
4670
|
constructor() {
|
|
3714
|
-
this.securityService = inject(SecurityService);
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
<div>
|
|
3735
|
-
<
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
4671
|
+
this.securityService = inject(SecurityService);
|
|
4672
|
+
this.route = inject(ActivatedRoute);
|
|
4673
|
+
this.router = inject(Router);
|
|
4674
|
+
}
|
|
4675
|
+
signIn() {
|
|
4676
|
+
const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
|
|
4677
|
+
this.router.navigate(['/unauthorized'], {
|
|
4678
|
+
queryParams: { returnUrl },
|
|
4679
|
+
replaceUrl: true
|
|
4680
|
+
}).then(() => this.securityService.authorize());
|
|
4681
|
+
}
|
|
4682
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4683
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: UnauthorizedComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
|
|
4684
|
+
<app-floating-configurator />
|
|
4685
|
+
<div
|
|
4686
|
+
class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
|
4687
|
+
<div class="flex flex-col items-center justify-center">
|
|
4688
|
+
<div
|
|
4689
|
+
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
|
4690
|
+
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
|
4691
|
+
<div class="flex flex-col items-center justify-center">
|
|
4692
|
+
<logo [height]="96" [width]="96" />
|
|
4693
|
+
</div>
|
|
4694
|
+
<div class="text-center mb-8">
|
|
4695
|
+
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">
|
|
4696
|
+
{{ 'unauthorized.welcomeToOip' | translate }}
|
|
4697
|
+
</div>
|
|
4698
|
+
<span class="text-muted-color font-medium">{{ 'unauthorized.signInToContinue' | translate }}</span>
|
|
4699
|
+
</div>
|
|
4700
|
+
<div>
|
|
4701
|
+
<p-button
|
|
4702
|
+
id="oip-unauthorized-error-sign-in-button"
|
|
4703
|
+
label="{{ 'unauthorized.signIn' | translate }}"
|
|
4704
|
+
styleClass="w-full"
|
|
4705
|
+
(click)="signIn()"></p-button>
|
|
4706
|
+
</div>
|
|
4707
|
+
</div>
|
|
4708
|
+
</div>
|
|
4709
|
+
</div>
|
|
4710
|
+
</div>
|
|
3745
4711
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: RippleModule }, { kind: "component", type: LogoComponent, selector: "logo", inputs: ["width", "height"] }, { kind: "component", type: AppFloatingConfiguratorComponent, selector: "app-floating-configurator" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3746
4712
|
}
|
|
3747
4713
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: UnauthorizedComponent, decorators: [{
|
|
3748
4714
|
type: Component,
|
|
3749
4715
|
args: [{
|
|
3750
|
-
template: `
|
|
3751
|
-
<app-floating-configurator />
|
|
3752
|
-
<div
|
|
3753
|
-
class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
|
3754
|
-
<div class="flex flex-col items-center justify-center">
|
|
3755
|
-
<div
|
|
3756
|
-
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
|
3757
|
-
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
|
3758
|
-
<div class="flex flex-col items-center justify-center">
|
|
3759
|
-
<logo [height]="96" [width]="96" />
|
|
3760
|
-
</div>
|
|
3761
|
-
<div class="text-center mb-8">
|
|
3762
|
-
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">
|
|
3763
|
-
{{ 'unauthorized.welcomeToOip' | translate }}
|
|
3764
|
-
</div>
|
|
3765
|
-
<span class="text-muted-color font-medium">{{ 'unauthorized.signInToContinue' | translate }}</span>
|
|
3766
|
-
</div>
|
|
3767
|
-
<div>
|
|
3768
|
-
<p-button
|
|
3769
|
-
id="oip-unauthorized-error-sign-in-button"
|
|
3770
|
-
label="{{ 'unauthorized.signIn' | translate }}"
|
|
3771
|
-
styleClass="w-full"
|
|
3772
|
-
(click)="
|
|
3773
|
-
</div>
|
|
3774
|
-
</div>
|
|
3775
|
-
</div>
|
|
3776
|
-
</div>
|
|
3777
|
-
</div>
|
|
4716
|
+
template: `
|
|
4717
|
+
<app-floating-configurator />
|
|
4718
|
+
<div
|
|
4719
|
+
class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
|
4720
|
+
<div class="flex flex-col items-center justify-center">
|
|
4721
|
+
<div
|
|
4722
|
+
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
|
4723
|
+
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
|
4724
|
+
<div class="flex flex-col items-center justify-center">
|
|
4725
|
+
<logo [height]="96" [width]="96" />
|
|
4726
|
+
</div>
|
|
4727
|
+
<div class="text-center mb-8">
|
|
4728
|
+
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">
|
|
4729
|
+
{{ 'unauthorized.welcomeToOip' | translate }}
|
|
4730
|
+
</div>
|
|
4731
|
+
<span class="text-muted-color font-medium">{{ 'unauthorized.signInToContinue' | translate }}</span>
|
|
4732
|
+
</div>
|
|
4733
|
+
<div>
|
|
4734
|
+
<p-button
|
|
4735
|
+
id="oip-unauthorized-error-sign-in-button"
|
|
4736
|
+
label="{{ 'unauthorized.signIn' | translate }}"
|
|
4737
|
+
styleClass="w-full"
|
|
4738
|
+
(click)="signIn()"></p-button>
|
|
4739
|
+
</div>
|
|
4740
|
+
</div>
|
|
4741
|
+
</div>
|
|
4742
|
+
</div>
|
|
4743
|
+
</div>
|
|
3778
4744
|
`,
|
|
3779
4745
|
imports: [
|
|
3780
4746
|
ButtonModule,
|
|
@@ -3819,7 +4785,7 @@ class ErrorComponent {
|
|
|
3819
4785
|
</div>
|
|
3820
4786
|
</div>
|
|
3821
4787
|
</div>
|
|
3822
|
-
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i3$
|
|
4788
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i1$2.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "ngmodule", type: RippleModule }, { kind: "directive", type: i3$3.Ripple, selector: "[pRipple]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
|
|
3823
4789
|
}
|
|
3824
4790
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ErrorComponent, decorators: [{
|
|
3825
4791
|
type: Component,
|
|
@@ -3892,7 +4858,7 @@ class ProfileComponent {
|
|
|
3892
4858
|
[auto]="true"
|
|
3893
4859
|
(onUpload)="onBasicUploadAuto($event)" />
|
|
3894
4860
|
</div>
|
|
3895
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i1$
|
|
4861
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i1$6.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "ngmodule", type: ImageModule }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3896
4862
|
}
|
|
3897
4863
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ProfileComponent, decorators: [{
|
|
3898
4864
|
type: Component,
|
|
@@ -3932,7 +4898,6 @@ class ConfigComponent {
|
|
|
3932
4898
|
this.userService = inject(UserService);
|
|
3933
4899
|
this.securityService = inject(SecurityService);
|
|
3934
4900
|
this.menuService = inject(MenuService);
|
|
3935
|
-
this.l10n = {};
|
|
3936
4901
|
this.dateFormats = ['dd.MM.yyyy', 'dd.MM.yy', 'yyyy-MM-dd', 'dd.MMM.yyyy'];
|
|
3937
4902
|
this.timeFormats = ['HH:mm:ss', 'HH:mm'];
|
|
3938
4903
|
// @ts-ignore
|
|
@@ -3963,204 +4928,204 @@ class ConfigComponent {
|
|
|
3963
4928
|
await this.menuService.loadMenu();
|
|
3964
4929
|
}
|
|
3965
4930
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3966
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ConfigComponent, isStandalone: true, selector: "app-config", ngImport: i0, template: `
|
|
3967
|
-
<div class="flex flex-col md:flex-row gap-4">
|
|
3968
|
-
<div class="md:w-1/2">
|
|
3969
|
-
<div class="card flex flex-col gap-4">
|
|
3970
|
-
<div class="font-semibold text-xl">{{ 'config.profile' | translate }}</div>
|
|
3971
|
-
<div class="flex justify-content-end flex-wrap">
|
|
3972
|
-
{{ userService.userName }}
|
|
3973
|
-
</div>
|
|
3974
|
-
<label>
|
|
3975
|
-
{{ 'config.photo' | translate }}
|
|
3976
|
-
<span
|
|
3977
|
-
class="pi pi-question-circle"
|
|
3978
|
-
pTooltip="{{ 'config.usePhoto256x256Pixel' | translate }}"
|
|
3979
|
-
tooltipPosition="right"></span>
|
|
3980
|
-
</label>
|
|
3981
|
-
<div class="flex justify-content-end flex-wrap">
|
|
3982
|
-
<user-profile></user-profile>
|
|
3983
|
-
</div>
|
|
3984
|
-
</div>
|
|
3985
|
-
</div>
|
|
3986
|
-
<div class="md:w-1/2">
|
|
3987
|
-
<div class="card flex flex-col gap-4">
|
|
3988
|
-
<div class="font-semibold text-xl">{{ 'config.localization' | translate }}</div>
|
|
3989
|
-
<label> {{ 'config.selectLanguage' | translate }} </label>
|
|
3990
|
-
<div class="flex justify-content-end flex-wrap">
|
|
3991
|
-
<p-select
|
|
3992
|
-
class="w-full md:w-56"
|
|
3993
|
-
optionLabel="name"
|
|
3994
|
-
optionValue="code"
|
|
3995
|
-
qa-id="oip-app-config-language-select"
|
|
3996
|
-
[options]="l10nService.availableLanguages"
|
|
3997
|
-
[(ngModel)]="selectedLanguage"
|
|
3998
|
-
(onChange)="changeLanguage()">
|
|
3999
|
-
<ng-template #selectedItem let-selectedOption>
|
|
4000
|
-
<div class="flex items-center gap-2">
|
|
4001
|
-
<span [class]="selectedOption.icon"></span>
|
|
4002
|
-
<div>{{ selectedOption.name }}</div>
|
|
4003
|
-
</div>
|
|
4004
|
-
</ng-template>
|
|
4005
|
-
<ng-template #item let-languages>
|
|
4006
|
-
<div class="flex items-center gap-2">
|
|
4007
|
-
<span [class]="languages.icon"></span>
|
|
4008
|
-
<div>{{ languages.name }}</div>
|
|
4009
|
-
</div>
|
|
4010
|
-
</ng-template>
|
|
4011
|
-
</p-select>
|
|
4012
|
-
</div>
|
|
4013
|
-
<div class="flex flex-col gap-5">
|
|
4014
|
-
<div class="mt-5">{{ 'config.dateTimeFormat' | translate }}</div>
|
|
4015
|
-
<p-select
|
|
4016
|
-
class="w-full md:w-56"
|
|
4017
|
-
qa-id="oip-app-config-date-format-select"
|
|
4018
|
-
[options]="dateFormats"
|
|
4019
|
-
[placeholder]="'config.dateFormat' | translate"
|
|
4020
|
-
[(ngModel)]="selectedDateFormat"
|
|
4021
|
-
(onChange)="changeDateFormat()" />
|
|
4022
|
-
<p-select
|
|
4023
|
-
class="w-full md:w-56"
|
|
4024
|
-
qa-id="oip-app-config-time-format-select"
|
|
4025
|
-
[options]="timeFormats"
|
|
4026
|
-
[placeholder]="'config.timeFormat' | translate"
|
|
4027
|
-
[(ngModel)]="selectedTimeFormat"
|
|
4028
|
-
(onChange)="changeTimeFormat()" />
|
|
4029
|
-
<div class="mt-5">{{ 'config.timeZone' | translate }}</div>
|
|
4030
|
-
<p-select
|
|
4031
|
-
class="w-full md:w-56"
|
|
4032
|
-
qa-id="oip-app-config-timezone-select"
|
|
4033
|
-
[filter]="true"
|
|
4034
|
-
[options]="allTimeZones"
|
|
4035
|
-
[placeholder]="'config.timeZone' | translate"
|
|
4036
|
-
[virtualScroll]="true"
|
|
4037
|
-
[virtualScrollItemSize]="34"
|
|
4038
|
-
[(ngModel)]="selectedTimeZone"
|
|
4039
|
-
(onChange)="changeTimeZone()" />
|
|
4040
|
-
</div>
|
|
4041
|
-
</div>
|
|
4042
|
-
</div>
|
|
4043
|
-
@if (securityService.isAdmin()) {
|
|
4044
|
-
<div class="md:w-1/2">
|
|
4045
|
-
<div class="card flex flex-col gap-4">
|
|
4046
|
-
<div class="font-semibold text-xl">{{ 'config.menu' | translate }}</div>
|
|
4047
|
-
<div class="flex items-center gap-2">
|
|
4048
|
-
<label for="oip-app-config-admin-mode">{{ 'config.all' | translate }}</label>
|
|
4049
|
-
<p-toggle-switch
|
|
4050
|
-
id="oip-app-config-admin-mode"
|
|
4051
|
-
[(ngModel)]="menuService.adminMode"
|
|
4052
|
-
(onChange)="onSwitchChange()"></p-toggle-switch>
|
|
4053
|
-
</div>
|
|
4054
|
-
<div class="flex items-center gap-2">
|
|
4055
|
-
<label for="oip-app-config-admin-mode">{{ 'config.moduleManagement' | translate }}</label>
|
|
4056
|
-
<p-button icon="pi pi-cog" label="{{ 'config.goTo' | translate }}" routerLink="/modules" />
|
|
4057
|
-
</div>
|
|
4058
|
-
</div>
|
|
4059
|
-
</div>
|
|
4060
|
-
}
|
|
4061
|
-
</div>
|
|
4931
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: ConfigComponent, isStandalone: true, selector: "app-config", ngImport: i0, template: `
|
|
4932
|
+
<div class="flex flex-col md:flex-row gap-4">
|
|
4933
|
+
<div class="md:w-1/2">
|
|
4934
|
+
<div class="card flex flex-col gap-4">
|
|
4935
|
+
<div class="font-semibold text-xl">{{ 'config.profile' | translate }}</div>
|
|
4936
|
+
<div class="flex justify-content-end flex-wrap">
|
|
4937
|
+
{{ userService.userName }}
|
|
4938
|
+
</div>
|
|
4939
|
+
<label>
|
|
4940
|
+
{{ 'config.photo' | translate }}
|
|
4941
|
+
<span
|
|
4942
|
+
class="pi pi-question-circle"
|
|
4943
|
+
pTooltip="{{ 'config.usePhoto256x256Pixel' | translate }}"
|
|
4944
|
+
tooltipPosition="right"></span>
|
|
4945
|
+
</label>
|
|
4946
|
+
<div class="flex justify-content-end flex-wrap">
|
|
4947
|
+
<user-profile></user-profile>
|
|
4948
|
+
</div>
|
|
4949
|
+
</div>
|
|
4950
|
+
</div>
|
|
4951
|
+
<div class="md:w-1/2">
|
|
4952
|
+
<div class="card flex flex-col gap-4">
|
|
4953
|
+
<div class="font-semibold text-xl">{{ 'config.localization' | translate }}</div>
|
|
4954
|
+
<label> {{ 'config.selectLanguage' | translate }} </label>
|
|
4955
|
+
<div class="flex justify-content-end flex-wrap">
|
|
4956
|
+
<p-select
|
|
4957
|
+
class="w-full md:w-56"
|
|
4958
|
+
optionLabel="name"
|
|
4959
|
+
optionValue="code"
|
|
4960
|
+
qa-id="oip-app-config-language-select"
|
|
4961
|
+
[options]="l10nService.availableLanguages"
|
|
4962
|
+
[(ngModel)]="selectedLanguage"
|
|
4963
|
+
(onChange)="changeLanguage()">
|
|
4964
|
+
<ng-template #selectedItem let-selectedOption>
|
|
4965
|
+
<div class="flex items-center gap-2">
|
|
4966
|
+
<span [class]="selectedOption.icon"></span>
|
|
4967
|
+
<div>{{ selectedOption.name }}</div>
|
|
4968
|
+
</div>
|
|
4969
|
+
</ng-template>
|
|
4970
|
+
<ng-template #item let-languages>
|
|
4971
|
+
<div class="flex items-center gap-2">
|
|
4972
|
+
<span [class]="languages.icon"></span>
|
|
4973
|
+
<div>{{ languages.name }}</div>
|
|
4974
|
+
</div>
|
|
4975
|
+
</ng-template>
|
|
4976
|
+
</p-select>
|
|
4977
|
+
</div>
|
|
4978
|
+
<div class="flex flex-col gap-5">
|
|
4979
|
+
<div class="mt-5">{{ 'config.dateTimeFormat' | translate }}</div>
|
|
4980
|
+
<p-select
|
|
4981
|
+
class="w-full md:w-56"
|
|
4982
|
+
qa-id="oip-app-config-date-format-select"
|
|
4983
|
+
[options]="dateFormats"
|
|
4984
|
+
[placeholder]="'config.dateFormat' | translate"
|
|
4985
|
+
[(ngModel)]="selectedDateFormat"
|
|
4986
|
+
(onChange)="changeDateFormat()" />
|
|
4987
|
+
<p-select
|
|
4988
|
+
class="w-full md:w-56"
|
|
4989
|
+
qa-id="oip-app-config-time-format-select"
|
|
4990
|
+
[options]="timeFormats"
|
|
4991
|
+
[placeholder]="'config.timeFormat' | translate"
|
|
4992
|
+
[(ngModel)]="selectedTimeFormat"
|
|
4993
|
+
(onChange)="changeTimeFormat()" />
|
|
4994
|
+
<div class="mt-5">{{ 'config.timeZone' | translate }}</div>
|
|
4995
|
+
<p-select
|
|
4996
|
+
class="w-full md:w-56"
|
|
4997
|
+
qa-id="oip-app-config-timezone-select"
|
|
4998
|
+
[filter]="true"
|
|
4999
|
+
[options]="allTimeZones"
|
|
5000
|
+
[placeholder]="'config.timeZone' | translate"
|
|
5001
|
+
[virtualScroll]="true"
|
|
5002
|
+
[virtualScrollItemSize]="34"
|
|
5003
|
+
[(ngModel)]="selectedTimeZone"
|
|
5004
|
+
(onChange)="changeTimeZone()" />
|
|
5005
|
+
</div>
|
|
5006
|
+
</div>
|
|
5007
|
+
</div>
|
|
5008
|
+
@if (securityService.isAdmin()) {
|
|
5009
|
+
<div class="md:w-1/2">
|
|
5010
|
+
<div class="card flex flex-col gap-4">
|
|
5011
|
+
<div class="font-semibold text-xl">{{ 'config.menu' | translate }}</div>
|
|
5012
|
+
<div class="flex items-center gap-2">
|
|
5013
|
+
<label for="oip-app-config-admin-mode">{{ 'config.all' | translate }}</label>
|
|
5014
|
+
<p-toggle-switch
|
|
5015
|
+
id="oip-app-config-admin-mode"
|
|
5016
|
+
[(ngModel)]="menuService.adminMode"
|
|
5017
|
+
(onChange)="onSwitchChange()"></p-toggle-switch>
|
|
5018
|
+
</div>
|
|
5019
|
+
<div class="flex items-center gap-2">
|
|
5020
|
+
<label for="oip-app-config-admin-mode">{{ 'config.moduleManagement' | translate }}</label>
|
|
5021
|
+
<p-button icon="pi pi-cog" label="{{ 'config.goTo' | translate }}" routerLink="/modules" />
|
|
5022
|
+
</div>
|
|
5023
|
+
</div>
|
|
5024
|
+
</div>
|
|
5025
|
+
}
|
|
5026
|
+
</div>
|
|
4062
5027
|
`, isInline: true, dependencies: [{ kind: "component", type: ProfileComponent, selector: "user-profile" }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: TableModule }, { kind: "ngmodule", type: ToggleSwitchModule }, { kind: "component", type: i2$5.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
4063
5028
|
}
|
|
4064
5029
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: ConfigComponent, decorators: [{
|
|
4065
5030
|
type: Component,
|
|
4066
5031
|
args: [{
|
|
4067
5032
|
selector: 'app-config',
|
|
4068
|
-
template: `
|
|
4069
|
-
<div class="flex flex-col md:flex-row gap-4">
|
|
4070
|
-
<div class="md:w-1/2">
|
|
4071
|
-
<div class="card flex flex-col gap-4">
|
|
4072
|
-
<div class="font-semibold text-xl">{{ 'config.profile' | translate }}</div>
|
|
4073
|
-
<div class="flex justify-content-end flex-wrap">
|
|
4074
|
-
{{ userService.userName }}
|
|
4075
|
-
</div>
|
|
4076
|
-
<label>
|
|
4077
|
-
{{ 'config.photo' | translate }}
|
|
4078
|
-
<span
|
|
4079
|
-
class="pi pi-question-circle"
|
|
4080
|
-
pTooltip="{{ 'config.usePhoto256x256Pixel' | translate }}"
|
|
4081
|
-
tooltipPosition="right"></span>
|
|
4082
|
-
</label>
|
|
4083
|
-
<div class="flex justify-content-end flex-wrap">
|
|
4084
|
-
<user-profile></user-profile>
|
|
4085
|
-
</div>
|
|
4086
|
-
</div>
|
|
4087
|
-
</div>
|
|
4088
|
-
<div class="md:w-1/2">
|
|
4089
|
-
<div class="card flex flex-col gap-4">
|
|
4090
|
-
<div class="font-semibold text-xl">{{ 'config.localization' | translate }}</div>
|
|
4091
|
-
<label> {{ 'config.selectLanguage' | translate }} </label>
|
|
4092
|
-
<div class="flex justify-content-end flex-wrap">
|
|
4093
|
-
<p-select
|
|
4094
|
-
class="w-full md:w-56"
|
|
4095
|
-
optionLabel="name"
|
|
4096
|
-
optionValue="code"
|
|
4097
|
-
qa-id="oip-app-config-language-select"
|
|
4098
|
-
[options]="l10nService.availableLanguages"
|
|
4099
|
-
[(ngModel)]="selectedLanguage"
|
|
4100
|
-
(onChange)="changeLanguage()">
|
|
4101
|
-
<ng-template #selectedItem let-selectedOption>
|
|
4102
|
-
<div class="flex items-center gap-2">
|
|
4103
|
-
<span [class]="selectedOption.icon"></span>
|
|
4104
|
-
<div>{{ selectedOption.name }}</div>
|
|
4105
|
-
</div>
|
|
4106
|
-
</ng-template>
|
|
4107
|
-
<ng-template #item let-languages>
|
|
4108
|
-
<div class="flex items-center gap-2">
|
|
4109
|
-
<span [class]="languages.icon"></span>
|
|
4110
|
-
<div>{{ languages.name }}</div>
|
|
4111
|
-
</div>
|
|
4112
|
-
</ng-template>
|
|
4113
|
-
</p-select>
|
|
4114
|
-
</div>
|
|
4115
|
-
<div class="flex flex-col gap-5">
|
|
4116
|
-
<div class="mt-5">{{ 'config.dateTimeFormat' | translate }}</div>
|
|
4117
|
-
<p-select
|
|
4118
|
-
class="w-full md:w-56"
|
|
4119
|
-
qa-id="oip-app-config-date-format-select"
|
|
4120
|
-
[options]="dateFormats"
|
|
4121
|
-
[placeholder]="'config.dateFormat' | translate"
|
|
4122
|
-
[(ngModel)]="selectedDateFormat"
|
|
4123
|
-
(onChange)="changeDateFormat()" />
|
|
4124
|
-
<p-select
|
|
4125
|
-
class="w-full md:w-56"
|
|
4126
|
-
qa-id="oip-app-config-time-format-select"
|
|
4127
|
-
[options]="timeFormats"
|
|
4128
|
-
[placeholder]="'config.timeFormat' | translate"
|
|
4129
|
-
[(ngModel)]="selectedTimeFormat"
|
|
4130
|
-
(onChange)="changeTimeFormat()" />
|
|
4131
|
-
<div class="mt-5">{{ 'config.timeZone' | translate }}</div>
|
|
4132
|
-
<p-select
|
|
4133
|
-
class="w-full md:w-56"
|
|
4134
|
-
qa-id="oip-app-config-timezone-select"
|
|
4135
|
-
[filter]="true"
|
|
4136
|
-
[options]="allTimeZones"
|
|
4137
|
-
[placeholder]="'config.timeZone' | translate"
|
|
4138
|
-
[virtualScroll]="true"
|
|
4139
|
-
[virtualScrollItemSize]="34"
|
|
4140
|
-
[(ngModel)]="selectedTimeZone"
|
|
4141
|
-
(onChange)="changeTimeZone()" />
|
|
4142
|
-
</div>
|
|
4143
|
-
</div>
|
|
4144
|
-
</div>
|
|
4145
|
-
@if (securityService.isAdmin()) {
|
|
4146
|
-
<div class="md:w-1/2">
|
|
4147
|
-
<div class="card flex flex-col gap-4">
|
|
4148
|
-
<div class="font-semibold text-xl">{{ 'config.menu' | translate }}</div>
|
|
4149
|
-
<div class="flex items-center gap-2">
|
|
4150
|
-
<label for="oip-app-config-admin-mode">{{ 'config.all' | translate }}</label>
|
|
4151
|
-
<p-toggle-switch
|
|
4152
|
-
id="oip-app-config-admin-mode"
|
|
4153
|
-
[(ngModel)]="menuService.adminMode"
|
|
4154
|
-
(onChange)="onSwitchChange()"></p-toggle-switch>
|
|
4155
|
-
</div>
|
|
4156
|
-
<div class="flex items-center gap-2">
|
|
4157
|
-
<label for="oip-app-config-admin-mode">{{ 'config.moduleManagement' | translate }}</label>
|
|
4158
|
-
<p-button icon="pi pi-cog" label="{{ 'config.goTo' | translate }}" routerLink="/modules" />
|
|
4159
|
-
</div>
|
|
4160
|
-
</div>
|
|
4161
|
-
</div>
|
|
4162
|
-
}
|
|
4163
|
-
</div>
|
|
5033
|
+
template: `
|
|
5034
|
+
<div class="flex flex-col md:flex-row gap-4">
|
|
5035
|
+
<div class="md:w-1/2">
|
|
5036
|
+
<div class="card flex flex-col gap-4">
|
|
5037
|
+
<div class="font-semibold text-xl">{{ 'config.profile' | translate }}</div>
|
|
5038
|
+
<div class="flex justify-content-end flex-wrap">
|
|
5039
|
+
{{ userService.userName }}
|
|
5040
|
+
</div>
|
|
5041
|
+
<label>
|
|
5042
|
+
{{ 'config.photo' | translate }}
|
|
5043
|
+
<span
|
|
5044
|
+
class="pi pi-question-circle"
|
|
5045
|
+
pTooltip="{{ 'config.usePhoto256x256Pixel' | translate }}"
|
|
5046
|
+
tooltipPosition="right"></span>
|
|
5047
|
+
</label>
|
|
5048
|
+
<div class="flex justify-content-end flex-wrap">
|
|
5049
|
+
<user-profile></user-profile>
|
|
5050
|
+
</div>
|
|
5051
|
+
</div>
|
|
5052
|
+
</div>
|
|
5053
|
+
<div class="md:w-1/2">
|
|
5054
|
+
<div class="card flex flex-col gap-4">
|
|
5055
|
+
<div class="font-semibold text-xl">{{ 'config.localization' | translate }}</div>
|
|
5056
|
+
<label> {{ 'config.selectLanguage' | translate }} </label>
|
|
5057
|
+
<div class="flex justify-content-end flex-wrap">
|
|
5058
|
+
<p-select
|
|
5059
|
+
class="w-full md:w-56"
|
|
5060
|
+
optionLabel="name"
|
|
5061
|
+
optionValue="code"
|
|
5062
|
+
qa-id="oip-app-config-language-select"
|
|
5063
|
+
[options]="l10nService.availableLanguages"
|
|
5064
|
+
[(ngModel)]="selectedLanguage"
|
|
5065
|
+
(onChange)="changeLanguage()">
|
|
5066
|
+
<ng-template #selectedItem let-selectedOption>
|
|
5067
|
+
<div class="flex items-center gap-2">
|
|
5068
|
+
<span [class]="selectedOption.icon"></span>
|
|
5069
|
+
<div>{{ selectedOption.name }}</div>
|
|
5070
|
+
</div>
|
|
5071
|
+
</ng-template>
|
|
5072
|
+
<ng-template #item let-languages>
|
|
5073
|
+
<div class="flex items-center gap-2">
|
|
5074
|
+
<span [class]="languages.icon"></span>
|
|
5075
|
+
<div>{{ languages.name }}</div>
|
|
5076
|
+
</div>
|
|
5077
|
+
</ng-template>
|
|
5078
|
+
</p-select>
|
|
5079
|
+
</div>
|
|
5080
|
+
<div class="flex flex-col gap-5">
|
|
5081
|
+
<div class="mt-5">{{ 'config.dateTimeFormat' | translate }}</div>
|
|
5082
|
+
<p-select
|
|
5083
|
+
class="w-full md:w-56"
|
|
5084
|
+
qa-id="oip-app-config-date-format-select"
|
|
5085
|
+
[options]="dateFormats"
|
|
5086
|
+
[placeholder]="'config.dateFormat' | translate"
|
|
5087
|
+
[(ngModel)]="selectedDateFormat"
|
|
5088
|
+
(onChange)="changeDateFormat()" />
|
|
5089
|
+
<p-select
|
|
5090
|
+
class="w-full md:w-56"
|
|
5091
|
+
qa-id="oip-app-config-time-format-select"
|
|
5092
|
+
[options]="timeFormats"
|
|
5093
|
+
[placeholder]="'config.timeFormat' | translate"
|
|
5094
|
+
[(ngModel)]="selectedTimeFormat"
|
|
5095
|
+
(onChange)="changeTimeFormat()" />
|
|
5096
|
+
<div class="mt-5">{{ 'config.timeZone' | translate }}</div>
|
|
5097
|
+
<p-select
|
|
5098
|
+
class="w-full md:w-56"
|
|
5099
|
+
qa-id="oip-app-config-timezone-select"
|
|
5100
|
+
[filter]="true"
|
|
5101
|
+
[options]="allTimeZones"
|
|
5102
|
+
[placeholder]="'config.timeZone' | translate"
|
|
5103
|
+
[virtualScroll]="true"
|
|
5104
|
+
[virtualScrollItemSize]="34"
|
|
5105
|
+
[(ngModel)]="selectedTimeZone"
|
|
5106
|
+
(onChange)="changeTimeZone()" />
|
|
5107
|
+
</div>
|
|
5108
|
+
</div>
|
|
5109
|
+
</div>
|
|
5110
|
+
@if (securityService.isAdmin()) {
|
|
5111
|
+
<div class="md:w-1/2">
|
|
5112
|
+
<div class="card flex flex-col gap-4">
|
|
5113
|
+
<div class="font-semibold text-xl">{{ 'config.menu' | translate }}</div>
|
|
5114
|
+
<div class="flex items-center gap-2">
|
|
5115
|
+
<label for="oip-app-config-admin-mode">{{ 'config.all' | translate }}</label>
|
|
5116
|
+
<p-toggle-switch
|
|
5117
|
+
id="oip-app-config-admin-mode"
|
|
5118
|
+
[(ngModel)]="menuService.adminMode"
|
|
5119
|
+
(onChange)="onSwitchChange()"></p-toggle-switch>
|
|
5120
|
+
</div>
|
|
5121
|
+
<div class="flex items-center gap-2">
|
|
5122
|
+
<label for="oip-app-config-admin-mode">{{ 'config.moduleManagement' | translate }}</label>
|
|
5123
|
+
<p-button icon="pi pi-cog" label="{{ 'config.goTo' | translate }}" routerLink="/modules" />
|
|
5124
|
+
</div>
|
|
5125
|
+
</div>
|
|
5126
|
+
</div>
|
|
5127
|
+
}
|
|
5128
|
+
</div>
|
|
4164
5129
|
`,
|
|
4165
5130
|
imports: [
|
|
4166
5131
|
ProfileComponent,
|
|
@@ -4196,11 +5161,11 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
4196
5161
|
});
|
|
4197
5162
|
}
|
|
4198
5163
|
async getData() {
|
|
4199
|
-
return this.
|
|
5164
|
+
return this.getMigrations();
|
|
4200
5165
|
}
|
|
4201
5166
|
async applyMigration(rowData) {
|
|
4202
5167
|
const request = { name: rowData.name };
|
|
4203
|
-
return this.
|
|
5168
|
+
return this.applyModuleMigration(request);
|
|
4204
5169
|
}
|
|
4205
5170
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DbMigrationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4206
5171
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DbMigrationComponent, isStandalone: true, selector: "db-migration", providers: [ConfirmationService], usesInheritance: true, ngImport: i0, template: `
|
|
@@ -4281,7 +5246,7 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
4281
5246
|
} @else if (isSecurity) {
|
|
4282
5247
|
<security [controller]="controller" [id]="id"/>
|
|
4283
5248
|
}
|
|
4284
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$
|
|
5249
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$7.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$7.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1$7.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i1$7.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i1$7.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: TagModule }, { kind: "ngmodule", type: InputTextModule }, { kind: "ngmodule", type: TextareaModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "component", type: SecurityComponent, selector: "security", inputs: ["id", "controller"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
4285
5250
|
}
|
|
4286
5251
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DbMigrationComponent, decorators: [{
|
|
4287
5252
|
type: Component,
|
|
@@ -4429,57 +5394,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4429
5394
|
|
|
4430
5395
|
class AppModulesComponent {
|
|
4431
5396
|
constructor() {
|
|
4432
|
-
this.dataService = inject(BaseDataService);
|
|
4433
5397
|
this.modules = [];
|
|
4434
5398
|
this.msgService = inject(MsgService);
|
|
4435
5399
|
this.confirmationService = inject(ConfirmationService);
|
|
4436
5400
|
this.l10nService = inject(L10nService);
|
|
4437
|
-
this.l10n = {};
|
|
4438
5401
|
this.titleService = inject(AppTitleService);
|
|
4439
5402
|
this.moduleService = inject(ModuleApi);
|
|
5403
|
+
this.translationsReady = firstValueFrom(this.l10nService.loadComponentTranslations('app-modules'));
|
|
4440
5404
|
}
|
|
4441
5405
|
async ngOnInit() {
|
|
4442
|
-
this.
|
|
4443
|
-
|
|
4444
|
-
});
|
|
4445
|
-
this.titleService.setTitle(this.l10n.title);
|
|
5406
|
+
await this.translationsReady;
|
|
5407
|
+
this.titleService.setTitle(this.t('app-modules.title'));
|
|
4446
5408
|
await this.refreshAction();
|
|
4447
5409
|
}
|
|
4448
5410
|
async refreshAction() {
|
|
4449
5411
|
this.modules = await this.moduleService.getModulesWithLoadStatus();
|
|
4450
5412
|
}
|
|
4451
|
-
deleteModule(module) {
|
|
5413
|
+
async deleteModule(module) {
|
|
5414
|
+
await this.translationsReady;
|
|
4452
5415
|
this.confirmationService.confirm({
|
|
4453
|
-
header: this.
|
|
4454
|
-
message: this.
|
|
5416
|
+
header: this.t('app-modules.confirm.header'),
|
|
5417
|
+
message: this.t('app-modules.confirm.message'),
|
|
4455
5418
|
icon: 'pi pi-trash',
|
|
4456
5419
|
rejectButtonProps: {
|
|
4457
|
-
label: this.
|
|
5420
|
+
label: this.t('app-modules.confirm.cancel'),
|
|
4458
5421
|
severity: 'secondary',
|
|
4459
5422
|
outlined: true
|
|
4460
5423
|
},
|
|
4461
5424
|
acceptButtonProps: {
|
|
4462
|
-
label: this.
|
|
5425
|
+
label: this.t('app-modules.confirm.delete'),
|
|
4463
5426
|
severity: 'danger'
|
|
4464
5427
|
},
|
|
4465
5428
|
accept: async () => {
|
|
4466
|
-
|
|
4467
|
-
.
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
.
|
|
4472
|
-
|
|
5429
|
+
try {
|
|
5430
|
+
await this.moduleService.delete({
|
|
5431
|
+
moduleId: module.moduleId
|
|
5432
|
+
});
|
|
5433
|
+
await this.refreshAction();
|
|
5434
|
+
this.msgService.success(this.t('app-modules.messages.deleteSuccess'));
|
|
5435
|
+
}
|
|
5436
|
+
catch (error) {
|
|
5437
|
+
this.msgService.error(error);
|
|
5438
|
+
}
|
|
4473
5439
|
}
|
|
4474
5440
|
});
|
|
4475
5441
|
}
|
|
5442
|
+
t(key) {
|
|
5443
|
+
return this.l10nService.instant(key);
|
|
5444
|
+
}
|
|
4476
5445
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppModulesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4477
5446
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: AppModulesComponent, isStandalone: true, selector: "app-modules", providers: [ConfirmationService, ModuleApi], ngImport: i0, template: `
|
|
4478
5447
|
<p-confirmDialog></p-confirmDialog>
|
|
4479
5448
|
<div class="flex flex-col md:flex-row gap-4">
|
|
4480
5449
|
<div class="card w-full">
|
|
4481
5450
|
<div class="font-semibold text-xl mb-4">
|
|
4482
|
-
{{
|
|
5451
|
+
{{ 'app-modules.title' | translate }}
|
|
4483
5452
|
</div>
|
|
4484
5453
|
<div class="mb-4">
|
|
4485
5454
|
<p-toolbar>
|
|
@@ -4528,7 +5497,7 @@ class AppModulesComponent {
|
|
|
4528
5497
|
</p-table>
|
|
4529
5498
|
</div>
|
|
4530
5499
|
</div>
|
|
4531
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$
|
|
5500
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$7.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: ToolbarModule }, { kind: "component", type: i4$2.Toolbar, selector: "p-toolbar", inputs: ["styleClass", "ariaLabelledBy"] }, { kind: "directive", type: Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
4532
5501
|
}
|
|
4533
5502
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppModulesComponent, decorators: [{
|
|
4534
5503
|
type: Component,
|
|
@@ -4541,7 +5510,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4541
5510
|
<div class="flex flex-col md:flex-row gap-4">
|
|
4542
5511
|
<div class="card w-full">
|
|
4543
5512
|
<div class="font-semibold text-xl mb-4">
|
|
4544
|
-
{{
|
|
5513
|
+
{{ 'app-modules.title' | translate }}
|
|
4545
5514
|
</div>
|
|
4546
5515
|
<div class="mb-4">
|
|
4547
5516
|
<p-toolbar>
|
|
@@ -4592,7 +5561,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4592
5561
|
</div>
|
|
4593
5562
|
`
|
|
4594
5563
|
}]
|
|
4595
|
-
}] });
|
|
5564
|
+
}], ctorParameters: () => [] });
|
|
4596
5565
|
|
|
4597
5566
|
/* eslint-disable */
|
|
4598
5567
|
/* tslint:disable */
|
|
@@ -4600,17 +5569,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4600
5569
|
class DiscussionApi extends HttpClient {
|
|
4601
5570
|
constructor() {
|
|
4602
5571
|
super(...arguments);
|
|
4603
|
-
/**
|
|
4604
|
-
* @description Gets comments by object type and object identifier.
|
|
4605
|
-
*
|
|
4606
|
-
* @tags Discussion
|
|
4607
|
-
* @name getByObject
|
|
4608
|
-
* @summary Gets comments by object type and object identifier.
|
|
4609
|
-
* @request GET:/api/discussion/get-by-object
|
|
4610
|
-
* @secure
|
|
4611
|
-
* @response `200` `(CommentDto)[]` OK
|
|
4612
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4613
|
-
*/
|
|
4614
5572
|
this.getByObject = (query, params = {}) => this.request({
|
|
4615
5573
|
path: `/api/discussion/get-by-object`,
|
|
4616
5574
|
method: "GET",
|
|
@@ -4619,18 +5577,6 @@ class DiscussionApi extends HttpClient {
|
|
|
4619
5577
|
format: "json",
|
|
4620
5578
|
...params,
|
|
4621
5579
|
});
|
|
4622
|
-
/**
|
|
4623
|
-
* @description Gets a comment by identifier.
|
|
4624
|
-
*
|
|
4625
|
-
* @tags Discussion
|
|
4626
|
-
* @name getById
|
|
4627
|
-
* @summary Gets a comment by identifier.
|
|
4628
|
-
* @request GET:/api/discussion/get-by-id
|
|
4629
|
-
* @secure
|
|
4630
|
-
* @response `200` `CommentDto` OK
|
|
4631
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4632
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4633
|
-
*/
|
|
4634
5580
|
this.getById = (query, params = {}) => this.request({
|
|
4635
5581
|
path: `/api/discussion/get-by-id`,
|
|
4636
5582
|
method: "GET",
|
|
@@ -4639,18 +5585,6 @@ class DiscussionApi extends HttpClient {
|
|
|
4639
5585
|
format: "json",
|
|
4640
5586
|
...params,
|
|
4641
5587
|
});
|
|
4642
|
-
/**
|
|
4643
|
-
* @description Creates a new comment
|
|
4644
|
-
*
|
|
4645
|
-
* @tags Discussion
|
|
4646
|
-
* @name create
|
|
4647
|
-
* @summary Creates a new comment
|
|
4648
|
-
* @request POST:/api/discussion/create
|
|
4649
|
-
* @secure
|
|
4650
|
-
* @response `200` `CommentDto` OK
|
|
4651
|
-
* @response `400` `ApiExceptionResponse` Bad Request
|
|
4652
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4653
|
-
*/
|
|
4654
5588
|
this.create = (data, params = {}) => this.request({
|
|
4655
5589
|
path: `/api/discussion/create`,
|
|
4656
5590
|
method: "POST",
|
|
@@ -4660,20 +5594,6 @@ class DiscussionApi extends HttpClient {
|
|
|
4660
5594
|
format: "json",
|
|
4661
5595
|
...params,
|
|
4662
5596
|
});
|
|
4663
|
-
/**
|
|
4664
|
-
* @description Updates an existing comment.
|
|
4665
|
-
*
|
|
4666
|
-
* @tags Discussion
|
|
4667
|
-
* @name update
|
|
4668
|
-
* @summary Updates an existing comment.
|
|
4669
|
-
* @request PUT:/api/discussion/update/{id}
|
|
4670
|
-
* @secure
|
|
4671
|
-
* @response `200` `CommentDto` OK
|
|
4672
|
-
* @response `400` `ApiExceptionResponse` Bad Request
|
|
4673
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4674
|
-
* @response `403` `ApiExceptionResponse` Forbidden
|
|
4675
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4676
|
-
*/
|
|
4677
5597
|
this.update = ({ id, ...query }, data, params = {}) => this.request({
|
|
4678
5598
|
path: `/api/discussion/update/${id}`,
|
|
4679
5599
|
method: "PUT",
|
|
@@ -4683,37 +5603,12 @@ class DiscussionApi extends HttpClient {
|
|
|
4683
5603
|
format: "json",
|
|
4684
5604
|
...params,
|
|
4685
5605
|
});
|
|
4686
|
-
/**
|
|
4687
|
-
* @description Soft deletes a comment.
|
|
4688
|
-
*
|
|
4689
|
-
* @tags Discussion
|
|
4690
|
-
* @name delete
|
|
4691
|
-
* @summary Soft deletes a comment.
|
|
4692
|
-
* @request DELETE:/api/discussion/delete/{id}
|
|
4693
|
-
* @secure
|
|
4694
|
-
* @response `204` `void` No Content
|
|
4695
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4696
|
-
* @response `403` `ApiExceptionResponse` Forbidden
|
|
4697
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4698
|
-
*/
|
|
4699
5606
|
this.delete = ({ id, ...query }, params = {}) => this.request({
|
|
4700
5607
|
path: `/api/discussion/delete/${id}`,
|
|
4701
5608
|
method: "DELETE",
|
|
4702
5609
|
secure: true,
|
|
4703
5610
|
...params,
|
|
4704
5611
|
});
|
|
4705
|
-
/**
|
|
4706
|
-
* @description Gets edit history for a comment.
|
|
4707
|
-
*
|
|
4708
|
-
* @tags Discussion
|
|
4709
|
-
* @name getHistory
|
|
4710
|
-
* @summary Gets edit history for a comment.
|
|
4711
|
-
* @request GET:/api/discussion/get-history/{id}
|
|
4712
|
-
* @secure
|
|
4713
|
-
* @response `200` `(CommentHistoryDto)[]` OK
|
|
4714
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4715
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4716
|
-
*/
|
|
4717
5612
|
this.getHistory = ({ id, ...query }, params = {}) => this.request({
|
|
4718
5613
|
path: `/api/discussion/get-history/${id}`,
|
|
4719
5614
|
method: "GET",
|
|
@@ -4721,20 +5616,6 @@ class DiscussionApi extends HttpClient {
|
|
|
4721
5616
|
format: "json",
|
|
4722
5617
|
...params,
|
|
4723
5618
|
});
|
|
4724
|
-
/**
|
|
4725
|
-
* @description Uploads an attachment for a comment.
|
|
4726
|
-
*
|
|
4727
|
-
* @tags Discussion
|
|
4728
|
-
* @name uploadAttachment
|
|
4729
|
-
* @summary Uploads an attachment for a comment.
|
|
4730
|
-
* @request POST:/api/discussion/upload-attachment
|
|
4731
|
-
* @secure
|
|
4732
|
-
* @response `200` `AttachmentDto` OK
|
|
4733
|
-
* @response `400` `ApiExceptionResponse` Bad Request
|
|
4734
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4735
|
-
* @response `403` `ApiExceptionResponse` Forbidden
|
|
4736
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4737
|
-
*/
|
|
4738
5619
|
this.uploadAttachment = (data, params = {}) => this.request({
|
|
4739
5620
|
path: `/api/discussion/upload-attachment`,
|
|
4740
5621
|
method: "POST",
|
|
@@ -4744,56 +5625,18 @@ class DiscussionApi extends HttpClient {
|
|
|
4744
5625
|
format: "json",
|
|
4745
5626
|
...params,
|
|
4746
5627
|
});
|
|
4747
|
-
/**
|
|
4748
|
-
* @description Deletes an attachment.
|
|
4749
|
-
*
|
|
4750
|
-
* @tags Discussion
|
|
4751
|
-
* @name deleteAttachment
|
|
4752
|
-
* @summary Deletes an attachment.
|
|
4753
|
-
* @request DELETE:/api/discussion/delete-attachment/{id}
|
|
4754
|
-
* @secure
|
|
4755
|
-
* @response `204` `void` No Content
|
|
4756
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4757
|
-
* @response `403` `ApiExceptionResponse` Forbidden
|
|
4758
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4759
|
-
*/
|
|
4760
5628
|
this.deleteAttachment = ({ id, ...query }, params = {}) => this.request({
|
|
4761
5629
|
path: `/api/discussion/delete-attachment/${id}`,
|
|
4762
5630
|
method: "DELETE",
|
|
4763
5631
|
secure: true,
|
|
4764
5632
|
...params,
|
|
4765
5633
|
});
|
|
4766
|
-
/**
|
|
4767
|
-
* @description Downloads attachment content.
|
|
4768
|
-
*
|
|
4769
|
-
* @tags Discussion
|
|
4770
|
-
* @name getAttachmentContent
|
|
4771
|
-
* @summary Downloads attachment content.
|
|
4772
|
-
* @request GET:/api/discussion/get-attachment-content/{id}
|
|
4773
|
-
* @secure
|
|
4774
|
-
* @response `200` `void` OK
|
|
4775
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4776
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4777
|
-
*/
|
|
4778
5634
|
this.getAttachmentContent = ({ id, ...query }, params = {}) => this.request({
|
|
4779
5635
|
path: `/api/discussion/get-attachment-content/${id}`,
|
|
4780
5636
|
method: "GET",
|
|
4781
5637
|
secure: true,
|
|
4782
5638
|
...params,
|
|
4783
5639
|
});
|
|
4784
|
-
/**
|
|
4785
|
-
* @description Adds or toggles a reaction for a comment.
|
|
4786
|
-
*
|
|
4787
|
-
* @tags Discussion
|
|
4788
|
-
* @name addReaction
|
|
4789
|
-
* @summary Adds or toggles a reaction for a comment.
|
|
4790
|
-
* @request POST:/api/discussion/add-reaction
|
|
4791
|
-
* @secure
|
|
4792
|
-
* @response `200` `(CommentReactionDto)[]` OK
|
|
4793
|
-
* @response `400` `ApiExceptionResponse` Bad Request
|
|
4794
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4795
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4796
|
-
*/
|
|
4797
5640
|
this.addReaction = (data, params = {}) => this.request({
|
|
4798
5641
|
path: `/api/discussion/add-reaction`,
|
|
4799
5642
|
method: "POST",
|
|
@@ -4803,18 +5646,6 @@ class DiscussionApi extends HttpClient {
|
|
|
4803
5646
|
format: "json",
|
|
4804
5647
|
...params,
|
|
4805
5648
|
});
|
|
4806
|
-
/**
|
|
4807
|
-
* @description Removes a reaction from a comment.
|
|
4808
|
-
*
|
|
4809
|
-
* @tags Discussion
|
|
4810
|
-
* @name removeReaction
|
|
4811
|
-
* @summary Removes a reaction from a comment.
|
|
4812
|
-
* @request DELETE:/api/discussion/remove-reaction
|
|
4813
|
-
* @secure
|
|
4814
|
-
* @response `200` `(CommentReactionDto)[]` OK
|
|
4815
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4816
|
-
* @response `404` `ApiExceptionResponse` Not Found
|
|
4817
|
-
*/
|
|
4818
5649
|
this.removeReaction = (query, params = {}) => this.request({
|
|
4819
5650
|
path: `/api/discussion/remove-reaction`,
|
|
4820
5651
|
method: "DELETE",
|
|
@@ -4823,18 +5654,6 @@ class DiscussionApi extends HttpClient {
|
|
|
4823
5654
|
format: "json",
|
|
4824
5655
|
...params,
|
|
4825
5656
|
});
|
|
4826
|
-
/**
|
|
4827
|
-
* @description Searches users that can be mentioned in a comment.
|
|
4828
|
-
*
|
|
4829
|
-
* @tags Discussion
|
|
4830
|
-
* @name searchMentionUsers
|
|
4831
|
-
* @summary Searches users that can be mentioned in a comment.
|
|
4832
|
-
* @request GET:/api/discussion/search-mention-users
|
|
4833
|
-
* @secure
|
|
4834
|
-
* @response `200` `(MentionUserDto)[]` OK
|
|
4835
|
-
* @response `400` `ApiExceptionResponse` Bad Request
|
|
4836
|
-
* @response `401` `ApiExceptionResponse` Unauthorized
|
|
4837
|
-
*/
|
|
4838
5657
|
this.searchMentionUsers = (query, params = {}) => this.request({
|
|
4839
5658
|
path: `/api/discussion/search-mention-users`,
|
|
4840
5659
|
method: "GET",
|
|
@@ -5597,7 +6416,7 @@ class DiscussionComponent {
|
|
|
5597
6416
|
</div>
|
|
5598
6417
|
}
|
|
5599
6418
|
</section>
|
|
5600
|
-
`, isInline: true, styles: [":host{display:block}.file-trigger{position:relative;display:inline-flex}.file-trigger input{position:absolute;inset:0;opacity:0;cursor:pointer}.markdown-preview,.history-markdown{word-break:break-word}.markdown-preview :is(h1,h2,h3),.history-markdown :is(h1,h2,h3){margin:0 0 .75rem;font-weight:600}.markdown-preview a,.history-markdown a{color:#2563eb;text-decoration:underline;text-underline-offset:.18em}.emoji-popover{display:flex;flex-wrap:wrap;gap:.5rem;max-width:16rem}.emoji-option{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;font-size:1.25rem;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i2$
|
|
6419
|
+
`, isInline: true, styles: [":host{display:block}.file-trigger{position:relative;display:inline-flex}.file-trigger input{position:absolute;inset:0;opacity:0;cursor:pointer}.markdown-preview,.history-markdown{word-break:break-word}.markdown-preview :is(h1,h2,h3),.history-markdown :is(h1,h2,h3){margin:0 0 .75rem;font-weight:600}.markdown-preview a,.history-markdown a{color:#2563eb;text-decoration:underline;text-underline-offset:.18em}.emoji-popover{display:flex;flex-wrap:wrap;gap:.5rem;max-width:16rem}.emoji-option{display:inline-flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;font-size:1.25rem;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i2$3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i5$1.Card, selector: "p-card", inputs: ["header", "subheader", "style", "styleClass"] }, { kind: "component", type: ConfirmDialog, selector: "p-confirmDialog, p-confirmdialog, p-confirm-dialog", inputs: ["header", "icon", "message", "style", "styleClass", "maskStyleClass", "acceptIcon", "acceptLabel", "closeAriaLabel", "acceptAriaLabel", "acceptVisible", "rejectIcon", "rejectLabel", "rejectAriaLabel", "rejectVisible", "acceptButtonStyleClass", "rejectButtonStyleClass", "closeOnEscape", "dismissableMask", "blockScroll", "rtl", "closable", "appendTo", "key", "autoZIndex", "baseZIndex", "transitionOptions", "focusTrap", "defaultFocus", "breakpoints", "modal", "visible", "position", "draggable"], outputs: ["onHide"] }, { kind: "ngmodule", type: DividerModule }, { kind: "ngmodule", type: PanelModule }, { kind: "component", type: i6.Panel, selector: "p-panel", inputs: ["id", "toggleable", "header", "collapsed", "styleClass", "iconPos", "showHeader", "toggler", "transitionOptions", "toggleButtonProps"], outputs: ["collapsedChange", "onBeforeToggle", "onAfterToggle"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i7.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ProgressSpinnerModule }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "directive", type: Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "pipe", type: i2$1.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5601
6420
|
}
|
|
5602
6421
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DiscussionComponent, decorators: [{
|
|
5603
6422
|
type: Component,
|
|
@@ -6123,31 +6942,14 @@ class AuthGuardService {
|
|
|
6123
6942
|
*
|
|
6124
6943
|
* @returns {Observable<boolean | UrlTree>} A stream resolving to true (allow), or UrlTree (redirect).
|
|
6125
6944
|
*/
|
|
6126
|
-
canActivate() {
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
}
|
|
6131
|
-
if (!tokenExpired) {
|
|
6132
|
-
return of(true);
|
|
6133
|
-
}
|
|
6134
|
-
// Token is expired; attempt to refresh
|
|
6135
|
-
return this.tryRefreshToken();
|
|
6136
|
-
}));
|
|
6945
|
+
canActivate(returnUrl = '/') {
|
|
6946
|
+
this.oidcSecurityService.auth();
|
|
6947
|
+
return this.oidcSecurityService.isAuthenticated().pipe(map((authenticated) => authenticated
|
|
6948
|
+
? true
|
|
6949
|
+
: this.router.createUrlTree(['/unauthorized'], { queryParams: { returnUrl: this.getReturnUrl(returnUrl) } })));
|
|
6137
6950
|
}
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
* If successful, allows route activation; otherwise, redirects to `/unauthorized`.
|
|
6141
|
-
*
|
|
6142
|
-
* @returns {boolean | UrlTree} A stream resolving to true or redirect UrlTree.
|
|
6143
|
-
*/
|
|
6144
|
-
tryRefreshToken() {
|
|
6145
|
-
return this.oidcSecurityService.forceRefreshSession().pipe(map((refreshSuccess) => {
|
|
6146
|
-
return refreshSuccess ? true : this.router.parseUrl('/unauthorized');
|
|
6147
|
-
}), catchError((err) => {
|
|
6148
|
-
console.warn(err);
|
|
6149
|
-
return of(this.router.parseUrl('/unauthorized'));
|
|
6150
|
-
}));
|
|
6951
|
+
getReturnUrl(returnUrl) {
|
|
6952
|
+
return returnUrl.startsWith('/unauthorized') ? '/' : returnUrl;
|
|
6151
6953
|
}
|
|
6152
6954
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthGuardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6153
6955
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AuthGuardService }); }
|
|
@@ -6156,80 +6958,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
6156
6958
|
type: Injectable
|
|
6157
6959
|
}] });
|
|
6158
6960
|
|
|
6159
|
-
class SecurityStorageService {
|
|
6160
|
-
read(key) {
|
|
6161
|
-
return localStorage.getItem(key);
|
|
6162
|
-
}
|
|
6163
|
-
write(key, value) {
|
|
6164
|
-
localStorage.setItem(key, value);
|
|
6165
|
-
}
|
|
6166
|
-
remove(key) {
|
|
6167
|
-
localStorage.removeItem(key);
|
|
6168
|
-
}
|
|
6169
|
-
clear() {
|
|
6170
|
-
localStorage.clear();
|
|
6171
|
-
}
|
|
6172
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6173
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityStorageService }); }
|
|
6174
|
-
}
|
|
6175
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityStorageService, decorators: [{
|
|
6176
|
-
type: Injectable
|
|
6177
|
-
}] });
|
|
6178
|
-
|
|
6179
|
-
class NotificationService {
|
|
6180
|
-
constructor() {
|
|
6181
|
-
this.securityService = inject(SecurityService);
|
|
6182
|
-
this.msgService = inject(MsgService);
|
|
6183
|
-
this.frontendConfig = inject(OIP_FRONTEND_CONFIG);
|
|
6184
|
-
this.securityData = null;
|
|
6185
|
-
this.connection = new signalR.HubConnectionBuilder()
|
|
6186
|
-
.withUrl(this.resolveHubUrl(), {
|
|
6187
|
-
accessTokenFactory: () => this.securityData ?? '',
|
|
6188
|
-
skipNegotiation: true,
|
|
6189
|
-
transport: signalR.HttpTransportType.WebSockets
|
|
6190
|
-
})
|
|
6191
|
-
.configureLogging(signalR.LogLevel.Error)
|
|
6192
|
-
.build();
|
|
6193
|
-
this.connection.on('ReceiveNotification', (notification) => {
|
|
6194
|
-
const opt = {
|
|
6195
|
-
severity: notification.severity,
|
|
6196
|
-
summary: notification.subject,
|
|
6197
|
-
detail: notification.message,
|
|
6198
|
-
life: 0
|
|
6199
|
-
};
|
|
6200
|
-
this.msgService.add(opt);
|
|
6201
|
-
});
|
|
6202
|
-
this.securityService.getAccessToken().subscribe((token) => {
|
|
6203
|
-
this.securityData = token;
|
|
6204
|
-
if (!token) {
|
|
6205
|
-
return;
|
|
6206
|
-
}
|
|
6207
|
-
if (this.connection.state === signalR.HubConnectionState.Disconnected) {
|
|
6208
|
-
this.connection.start().catch((error) => console.error('Failed to start notification connection', error));
|
|
6209
|
-
return;
|
|
6210
|
-
}
|
|
6211
|
-
this.connection.stop().then(() => {
|
|
6212
|
-
this.connection.start().catch((error) => console.error('Failed to restart notification connection', error));
|
|
6213
|
-
});
|
|
6214
|
-
});
|
|
6215
|
-
}
|
|
6216
|
-
resolveHubUrl() {
|
|
6217
|
-
if (this.frontendConfig.notificationHubUrl) {
|
|
6218
|
-
return this.frontendConfig.notificationHubUrl;
|
|
6219
|
-
}
|
|
6220
|
-
if (this.frontendConfig.apiBaseUrl) {
|
|
6221
|
-
return `${this.frontendConfig.apiBaseUrl.replace(/\/$/, '')}/hubs/notification`;
|
|
6222
|
-
}
|
|
6223
|
-
return '/hubs/notification';
|
|
6224
|
-
}
|
|
6225
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6226
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationService, providedIn: 'root' }); }
|
|
6227
|
-
}
|
|
6228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: NotificationService, decorators: [{
|
|
6229
|
-
type: Injectable,
|
|
6230
|
-
args: [{ providedIn: 'root' }]
|
|
6231
|
-
}], ctorParameters: () => [] });
|
|
6232
|
-
|
|
6233
6961
|
/**
|
|
6234
6962
|
* Prime-ng table filter service
|
|
6235
6963
|
*/
|
|
@@ -6304,73 +7032,96 @@ function replaceDefaults(themes) {
|
|
|
6304
7032
|
|
|
6305
7033
|
const langIntercept = (req, next) => {
|
|
6306
7034
|
const layoutService = inject(LayoutService);
|
|
7035
|
+
const securityService = inject(SecurityService);
|
|
6307
7036
|
const lang = layoutService.language() ? layoutService.language() : 'en';
|
|
6308
|
-
const
|
|
6309
|
-
|
|
6310
|
-
|
|
7037
|
+
const headers = req.headers
|
|
7038
|
+
.set('Accept-language', lang)
|
|
7039
|
+
.set('X-Timezone', layoutService.timeZone());
|
|
7040
|
+
const reqWithCredentials = req.clone({
|
|
7041
|
+
headers,
|
|
7042
|
+
withCredentials: true
|
|
6311
7043
|
});
|
|
6312
|
-
|
|
7044
|
+
if (!['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method.toUpperCase())) {
|
|
7045
|
+
return next(reqWithCredentials);
|
|
7046
|
+
}
|
|
7047
|
+
if (req.url.includes('/api/security/create-auth-session') || req.url.includes('/api/security/get-auth-csrf-token')) {
|
|
7048
|
+
return next(reqWithCredentials);
|
|
7049
|
+
}
|
|
7050
|
+
return securityService.getCsrfToken().pipe(take(1), switchMap((csrfToken) => next(csrfToken?.token
|
|
7051
|
+
? reqWithCredentials.clone({
|
|
7052
|
+
headers: reqWithCredentials.headers.set(csrfToken.headerName, csrfToken.token)
|
|
7053
|
+
})
|
|
7054
|
+
: reqWithCredentials)));
|
|
6313
7055
|
};
|
|
6314
7056
|
|
|
6315
|
-
|
|
7057
|
+
const httpLoaderFactory = (http) => new TranslateHttpLoader(http);
|
|
7058
|
+
function provideOip() {
|
|
7059
|
+
return makeEnvironmentProviders([
|
|
7060
|
+
provideHttpClient(withInterceptors([langIntercept]), withFetch()),
|
|
7061
|
+
{ provide: LocationStrategy, useClass: PathLocationStrategy },
|
|
7062
|
+
{ provide: SecurityService, useClass: BffSecurityService },
|
|
7063
|
+
AuthGuardService,
|
|
7064
|
+
MessageService,
|
|
7065
|
+
UserService,
|
|
7066
|
+
NotificationService,
|
|
7067
|
+
UserProfileApi,
|
|
7068
|
+
SecurityApi,
|
|
7069
|
+
NotificationApi,
|
|
7070
|
+
importProvidersFrom([
|
|
7071
|
+
TranslateModule.forRoot({
|
|
7072
|
+
loader: {
|
|
7073
|
+
provide: TranslateLoader,
|
|
7074
|
+
useFactory: httpLoaderFactory,
|
|
7075
|
+
deps: [HttpClient$1]
|
|
7076
|
+
}
|
|
7077
|
+
})
|
|
7078
|
+
])
|
|
7079
|
+
]);
|
|
7080
|
+
}
|
|
7081
|
+
|
|
7082
|
+
/* eslint-disable */
|
|
7083
|
+
/* tslint:disable */
|
|
7084
|
+
// @ts-nocheck
|
|
7085
|
+
class FolderModuleApi extends HttpClient {
|
|
6316
7086
|
constructor() {
|
|
6317
|
-
|
|
6318
|
-
this.
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
7087
|
+
super(...arguments);
|
|
7088
|
+
this.getModuleInstanceSettings = (query, params = {}) => this.request({
|
|
7089
|
+
path: `/api/folder-module/get-module-instance-settings`,
|
|
7090
|
+
method: "GET",
|
|
7091
|
+
query: query,
|
|
7092
|
+
secure: true,
|
|
7093
|
+
format: "json",
|
|
7094
|
+
...params,
|
|
7095
|
+
});
|
|
6324
7096
|
}
|
|
6325
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
6326
|
-
static { this.ɵ
|
|
7097
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FolderModuleApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
7098
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FolderModuleApi }); }
|
|
6327
7099
|
}
|
|
6328
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
6329
|
-
type:
|
|
6330
|
-
args: [{
|
|
6331
|
-
standalone: true,
|
|
6332
|
-
name: 'secure'
|
|
6333
|
-
}]
|
|
7100
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FolderModuleApi, decorators: [{
|
|
7101
|
+
type: Injectable
|
|
6334
7102
|
}] });
|
|
6335
7103
|
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
const config$ = new Observable((subscribe) => {
|
|
6350
|
-
subscribe.next(JSON.parse(settingsStings));
|
|
7104
|
+
/* eslint-disable */
|
|
7105
|
+
/* tslint:disable */
|
|
7106
|
+
// @ts-nocheck
|
|
7107
|
+
class IframeModuleApi extends HttpClient {
|
|
7108
|
+
constructor() {
|
|
7109
|
+
super(...arguments);
|
|
7110
|
+
this.getModuleInstanceSettings = (query, params = {}) => this.request({
|
|
7111
|
+
path: `/api/iframe-module/get-module-instance-settings`,
|
|
7112
|
+
method: "GET",
|
|
7113
|
+
query: query,
|
|
7114
|
+
secure: true,
|
|
7115
|
+
format: "json",
|
|
7116
|
+
...params,
|
|
6351
7117
|
});
|
|
6352
|
-
return new StsConfigHttpLoader(config$);
|
|
6353
|
-
}
|
|
6354
|
-
else {
|
|
6355
|
-
const config$ = httpClient.get(`api/security/get-keycloak-client-settings`).pipe(map$1((config) => {
|
|
6356
|
-
const authConfig = {
|
|
6357
|
-
authority: config.authority,
|
|
6358
|
-
redirectUrl: window.location.origin,
|
|
6359
|
-
postLogoutRedirectUri: window.location.origin,
|
|
6360
|
-
clientId: config.clientId,
|
|
6361
|
-
scope: config.scope,
|
|
6362
|
-
responseType: config.responseType,
|
|
6363
|
-
useRefreshToken: config.useRefreshToken,
|
|
6364
|
-
silentRenew: config.silentRenew,
|
|
6365
|
-
logLevel: config.logLevel,
|
|
6366
|
-
secureRoutes: appendCurrentOriginSecureRoute(config.secureRoutes)
|
|
6367
|
-
};
|
|
6368
|
-
sessionStorage.setItem(KEYCLOAK_SETTINGS_KEY, JSON.stringify(authConfig));
|
|
6369
|
-
return authConfig;
|
|
6370
|
-
}));
|
|
6371
|
-
return new StsConfigHttpLoader(config$);
|
|
6372
7118
|
}
|
|
6373
|
-
};
|
|
7119
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IframeModuleApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
7120
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IframeModuleApi }); }
|
|
7121
|
+
}
|
|
7122
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: IframeModuleApi, decorators: [{
|
|
7123
|
+
type: Injectable
|
|
7124
|
+
}] });
|
|
6374
7125
|
|
|
6375
7126
|
// Components
|
|
6376
7127
|
|
|
@@ -6378,5 +7129,5 @@ const httpLoaderAuthFactory = (httpClient) => {
|
|
|
6378
7129
|
* Generated bundle index. Do not edit.
|
|
6379
7130
|
*/
|
|
6380
7131
|
|
|
6381
|
-
export { APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService,
|
|
7132
|
+
export { APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService, BaseModuleComponent, BffSecurityService, ConfigComponent, ContentType, DbMigrationComponent, DiscussionComponent, ErrorComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, KeycloakSecurityService, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, MsgService, NotfoundComponent, NotificationApi, NotificationService, ProfileComponent, SecurityApi, SecurityComponent, SecurityService, SidebarComponent, TableFilterService, TopBarService, UnauthorizedComponent, UserNotificationsComponent, UserProfileApi, UserService, convertToPrimeNgDateFormat, langIntercept, mergeWithDefaults, provideAppThemes, provideLogoComponent, provideOip, replaceDefaults };
|
|
6382
7133
|
//# sourceMappingURL=oip-common.mjs.map
|