oip-common 0.1.6 → 0.1.8
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/en.json +2 -1
- package/assets/i18n/ru.json +2 -1
- package/fesm2022/oip-common.mjs +826 -608
- package/fesm2022/oip-common.mjs.map +1 -1
- package/index.d.ts +126 -85
- package/package.json +1 -1
package/fesm2022/oip-common.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, inject, InjectionToken, signal, computed, effect, ChangeDetectorRef, Component, Input, PLATFORM_ID, HostBinding, EventEmitter, Output, ViewChild, Renderer2, SecurityContext, ChangeDetectionStrategy, Pipe } from '@angular/core';
|
|
2
|
+
import { Injectable, inject, InjectionToken, signal, computed, effect, DestroyRef, ChangeDetectorRef, Component, Input, PLATFORM_ID, HostBinding, EventEmitter, Output, ViewChild, Renderer2, SecurityContext, ChangeDetectionStrategy, makeEnvironmentProviders, Pipe } from '@angular/core';
|
|
3
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
3
4
|
import * as i2$6 from 'primeng/api';
|
|
4
5
|
import { MessageService, ConfirmationService, PrimeIcons, SharedModule } from 'primeng/api';
|
|
5
6
|
import { HttpErrorResponse, HttpClient as HttpClient$1, HttpHeaders } from '@angular/common/http';
|
|
@@ -7,8 +8,11 @@ import * as i2$4 from '@ngx-translate/core';
|
|
|
7
8
|
import { TranslateService, TranslatePipe, TranslateModule } from '@ngx-translate/core';
|
|
8
9
|
import * as i1$3 from '@angular/router';
|
|
9
10
|
import { ActivatedRoute, Router, RouterModule, NavigationEnd, RouterLinkActive, RouterLink } from '@angular/router';
|
|
10
|
-
import { lastValueFrom, BehaviorSubject, Subject, ReplaySubject, merge, filter as filter$1, combineLatest, of, map as map$1, Observable } from 'rxjs';
|
|
11
|
+
import { lastValueFrom, BehaviorSubject, Subject, ReplaySubject, merge, from, filter as filter$1, combineLatest, of, map as map$1, Observable } from 'rxjs';
|
|
12
|
+
import { filter, distinctUntilChanged, map, switchMap, catchError } from 'rxjs/operators';
|
|
11
13
|
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
14
|
+
import { PrimeNG } from 'primeng/config';
|
|
15
|
+
import { OidcSecurityService, PublicEventsService, EventTypes, StsConfigHttpLoader } from 'angular-auth-oidc-client';
|
|
12
16
|
import * as i1 from 'primeng/multiselect';
|
|
13
17
|
import { MultiSelectModule } from 'primeng/multiselect';
|
|
14
18
|
import * as i2 from 'primeng/tooltip';
|
|
@@ -25,11 +29,8 @@ import { updatePreset, updateSurfacePalette, $t } from '@primeng/themes';
|
|
|
25
29
|
import Aura from '@primeng/themes/aura';
|
|
26
30
|
import Lara from '@primeng/themes/lara';
|
|
27
31
|
import Nora from '@primeng/themes/nora';
|
|
28
|
-
import { PrimeNG } from 'primeng/config';
|
|
29
32
|
import * as i3 from 'primeng/selectbutton';
|
|
30
33
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
31
|
-
import { OidcSecurityService, PublicEventsService, EventTypes, StsConfigHttpLoader } from 'angular-auth-oidc-client';
|
|
32
|
-
import { filter, distinctUntilChanged, map, switchMap, catchError } from 'rxjs/operators';
|
|
33
34
|
import { Tabs, TabList, Tab } from 'primeng/tabs';
|
|
34
35
|
import * as i2$2 from 'primeng/avatar';
|
|
35
36
|
import { AvatarModule } from 'primeng/avatar';
|
|
@@ -144,7 +145,11 @@ class MsgService {
|
|
|
144
145
|
});
|
|
145
146
|
}
|
|
146
147
|
error(detail, summary = this.translate.instant('msgService.error'), life = this.lifetime) {
|
|
147
|
-
|
|
148
|
+
const validationMessage = this.extractValidationMessage(detail);
|
|
149
|
+
if (validationMessage) {
|
|
150
|
+
detail = validationMessage;
|
|
151
|
+
}
|
|
152
|
+
else if (detail instanceof HttpErrorResponse) {
|
|
148
153
|
summary = `Error: ${detail.status} ${detail.statusText}`;
|
|
149
154
|
detail = `${detail.name} \r\n ${detail.message}`;
|
|
150
155
|
}
|
|
@@ -156,6 +161,10 @@ class MsgService {
|
|
|
156
161
|
});
|
|
157
162
|
}
|
|
158
163
|
extractErrorMessage(error, fallback) {
|
|
164
|
+
const validationMessage = this.extractValidationMessage(error);
|
|
165
|
+
if (validationMessage) {
|
|
166
|
+
return validationMessage;
|
|
167
|
+
}
|
|
159
168
|
if (typeof error === 'object' &&
|
|
160
169
|
error &&
|
|
161
170
|
'error' in error &&
|
|
@@ -170,6 +179,35 @@ class MsgService {
|
|
|
170
179
|
}
|
|
171
180
|
return fallback;
|
|
172
181
|
}
|
|
182
|
+
extractValidationMessage(error) {
|
|
183
|
+
const responseError = this.getObjectProperty(error, 'error');
|
|
184
|
+
const validationErrors = this.getObjectProperty(responseError, 'errors') ?? this.getObjectProperty(error, 'errors');
|
|
185
|
+
if (!validationErrors) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
const messages = Object.entries(validationErrors)
|
|
189
|
+
.reduce((result, [field, value]) => [...result, ...this.toValidationMessages(field, value)], [])
|
|
190
|
+
.filter((message) => message.length > 0);
|
|
191
|
+
return messages.length > 0 ? messages.join('\n') : null;
|
|
192
|
+
}
|
|
193
|
+
toValidationMessages(field, value) {
|
|
194
|
+
if (Array.isArray(value)) {
|
|
195
|
+
return value
|
|
196
|
+
.filter((message) => typeof message === 'string')
|
|
197
|
+
.map((message) => `${field}: ${message}`);
|
|
198
|
+
}
|
|
199
|
+
if (typeof value === 'string') {
|
|
200
|
+
return [`${field}: ${value}`];
|
|
201
|
+
}
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
getObjectProperty(source, property) {
|
|
205
|
+
if (typeof source !== 'object' || source === null || !(property in source)) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
const value = source[property];
|
|
209
|
+
return typeof value === 'object' && value !== null ? value : null;
|
|
210
|
+
}
|
|
173
211
|
errorFromException(error, fallback, summary = fallback, life = this.lifetime) {
|
|
174
212
|
this.error(this.extractErrorMessage(error, fallback), summary, life);
|
|
175
213
|
}
|
|
@@ -567,7 +605,219 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
567
605
|
args: [{ providedIn: 'root' }]
|
|
568
606
|
}], ctorParameters: () => [] });
|
|
569
607
|
|
|
608
|
+
/**
|
|
609
|
+
* Service for managing translation loading in the application
|
|
610
|
+
*/
|
|
611
|
+
class L10nService {
|
|
612
|
+
constructor() {
|
|
613
|
+
this.loadedTranslations = new Set();
|
|
614
|
+
this.httpClient = inject(HttpClient$1);
|
|
615
|
+
this.translateService = inject(TranslateService);
|
|
616
|
+
this.primeNg = inject(PrimeNG);
|
|
617
|
+
this.layoutService = inject(LayoutService);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Loads translations for a specific component
|
|
621
|
+
* @param component - Name of the component to load translations for
|
|
622
|
+
*/
|
|
623
|
+
loadComponentTranslations(component) {
|
|
624
|
+
const lang = this.translateService.currentLang;
|
|
625
|
+
this.loadTranslations(component, lang);
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Gets the translated value of a key (or an array of keys)
|
|
629
|
+
* @returns the translated key, or an object of translated keys
|
|
630
|
+
*/
|
|
631
|
+
get(key) {
|
|
632
|
+
this.loadComponentTranslations(key.split('.')[0]);
|
|
633
|
+
return this.translateService.get(key);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Internal method to load translations from JSON files
|
|
637
|
+
* @param component - Component or translation namespace
|
|
638
|
+
* @param lang - Language code to load translations for
|
|
639
|
+
*/
|
|
640
|
+
loadTranslations(component, lang) {
|
|
641
|
+
const key = `${component}.${lang}`;
|
|
642
|
+
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
|
+
});
|
|
651
|
+
}
|
|
652
|
+
catch (e) {
|
|
653
|
+
console.error(`No translations found for ${component}.${lang}.json`);
|
|
654
|
+
console.error(e);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Changes the lang currently used
|
|
659
|
+
*/
|
|
660
|
+
use(selectedLanguage, key = null) {
|
|
661
|
+
if (key) {
|
|
662
|
+
this.get(key);
|
|
663
|
+
}
|
|
664
|
+
this.translateService.use(selectedLanguage);
|
|
665
|
+
}
|
|
666
|
+
init(languages) {
|
|
667
|
+
this.availableLanguages = languages;
|
|
668
|
+
this.translateService.addLangs(languages.map((x) => x.code));
|
|
669
|
+
const lang = this.layoutService.language() ? this.layoutService.language() : 'en';
|
|
670
|
+
this.translateService.setDefaultLang(lang);
|
|
671
|
+
this.translateService.use(lang).subscribe(() => {
|
|
672
|
+
this.loadComponentTranslations('app-info');
|
|
673
|
+
this.translateService.get('primeng').subscribe((res) => this.primeNg.setTranslation(res));
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
instant(key, interpolateParams) {
|
|
677
|
+
return this.translateService.instant(key, interpolateParams);
|
|
678
|
+
}
|
|
679
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: L10nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
680
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: L10nService, providedIn: 'root' }); }
|
|
681
|
+
}
|
|
682
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: L10nService, decorators: [{
|
|
683
|
+
type: Injectable,
|
|
684
|
+
args: [{ providedIn: 'root' }]
|
|
685
|
+
}] });
|
|
686
|
+
|
|
687
|
+
class SecurityDataService extends BaseDataService {
|
|
688
|
+
getSecurity(controller, id) {
|
|
689
|
+
return this.sendRequest(this.baseUrl + `api/${controller}/get-security?id=${id}`);
|
|
690
|
+
}
|
|
691
|
+
saveSecurity(controller, request) {
|
|
692
|
+
return this.sendRequest(this.baseUrl + `api/${controller}/put-security`, 'PUT', request);
|
|
693
|
+
}
|
|
694
|
+
getRealmRoles() {
|
|
695
|
+
return this.sendRequest(this.baseUrl + `api/security/get-realm-roles`);
|
|
696
|
+
}
|
|
697
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityDataService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
698
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityDataService }); }
|
|
699
|
+
}
|
|
700
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityDataService, decorators: [{
|
|
701
|
+
type: Injectable
|
|
702
|
+
}] });
|
|
703
|
+
|
|
704
|
+
class SecurityService {
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* SecurityService extends OidcSecurityService to manage authentication,
|
|
708
|
+
* token handling, and user role access in an Angular application.
|
|
709
|
+
*
|
|
710
|
+
* It provides helper methods for checking authentication, managing tokens,
|
|
711
|
+
* determining user roles, and performing logout and refresh operations.
|
|
712
|
+
*/
|
|
713
|
+
class KeycloakSecurityService extends OidcSecurityService {
|
|
714
|
+
/**
|
|
715
|
+
* Initializes service and subscribes to authentication events.
|
|
716
|
+
* When a 'NewAuthenticationResult' event is received, the `auth` method is called.
|
|
717
|
+
*/
|
|
718
|
+
constructor() {
|
|
719
|
+
super();
|
|
720
|
+
/**
|
|
721
|
+
* Handles angular OIDC events.
|
|
722
|
+
*/
|
|
723
|
+
this.publicEventsService = inject(PublicEventsService);
|
|
724
|
+
/**
|
|
725
|
+
* Stores the latest login response from checkAuth().
|
|
726
|
+
*/
|
|
727
|
+
this.loginResponse = new BehaviorSubject(null);
|
|
728
|
+
/**
|
|
729
|
+
* Stores the decoded access token payload.
|
|
730
|
+
*/
|
|
731
|
+
this.payload = new BehaviorSubject(null);
|
|
732
|
+
/**
|
|
733
|
+
* Stores user-specific data from the login response.
|
|
734
|
+
*/
|
|
735
|
+
this.currentUser = new BehaviorSubject(null);
|
|
736
|
+
/**
|
|
737
|
+
* Emits access token updates from initial auth check, manual refresh,
|
|
738
|
+
* and library authentication events.
|
|
739
|
+
*/
|
|
740
|
+
this.accessToken = new ReplaySubject(1);
|
|
741
|
+
this.publicEventsService
|
|
742
|
+
.registerForEvents()
|
|
743
|
+
.pipe(filter((event) => event.type === EventTypes.NewAuthenticationResult))
|
|
744
|
+
.subscribe(() => {
|
|
745
|
+
super.getAccessToken().subscribe(token => { this.accessToken.next(token); });
|
|
746
|
+
this.auth();
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
getCurrentUser() {
|
|
750
|
+
return this.currentUser.getValue();
|
|
751
|
+
}
|
|
752
|
+
getCurrentUser$() {
|
|
753
|
+
return this.currentUser.asObservable();
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* Returns the ID token for the sign-in.
|
|
757
|
+
* @returns A string with the id token.
|
|
758
|
+
*/
|
|
759
|
+
getAccessToken(configId) {
|
|
760
|
+
return merge(super.getAccessToken(configId), this.accessToken.asObservable()).pipe(distinctUntilChanged());
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Indicates whether the current user has the 'admin' role.
|
|
764
|
+
*
|
|
765
|
+
* @returns {boolean} True if the user is an admin, false otherwise.
|
|
766
|
+
*/
|
|
767
|
+
isAdmin() {
|
|
768
|
+
return this.payload.getValue()?.realm_access?.roles?.includes('admin');
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Initiates authentication check and updates login response, user data,
|
|
772
|
+
* and decoded token payload if authenticated.
|
|
773
|
+
*/
|
|
774
|
+
auth() {
|
|
775
|
+
super.checkAuth().subscribe((_response) => {
|
|
776
|
+
this.loginResponse.next(_response);
|
|
777
|
+
this.currentUser.next(_response.userData);
|
|
778
|
+
this.getPayloadFromAccessToken().subscribe((_token) => {
|
|
779
|
+
this.payload.next(_token);
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
/**
|
|
784
|
+
* Performs logout and clears the local token payload.
|
|
785
|
+
*
|
|
786
|
+
* @param {string} [configId] Optional configuration ID for logout.
|
|
787
|
+
* @param {LogoutAuthOptions} [logoutAuthOptions] Optional logout options.
|
|
788
|
+
*/
|
|
789
|
+
logout(configId, logoutAuthOptions) {
|
|
790
|
+
this.logoff(configId, logoutAuthOptions).subscribe((x) => this.payload.next(x));
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Completes the BehaviorSubjects when the service is destroyed to avoid memory leaks.
|
|
794
|
+
*/
|
|
795
|
+
ngOnDestroy() {
|
|
796
|
+
this.loginResponse.complete();
|
|
797
|
+
this.payload.complete();
|
|
798
|
+
this.currentUser.complete();
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Checks whether the current access token is expired based on the 'exp' claim.
|
|
802
|
+
*
|
|
803
|
+
* @returns {Observable<boolean>} Observable that emits true if the token is expired.
|
|
804
|
+
*/
|
|
805
|
+
isTokenExpired() {
|
|
806
|
+
return this.getPayloadFromAccessToken().pipe(map((payload) => {
|
|
807
|
+
return payload.exp < Math.floor(Date.now() / 1000);
|
|
808
|
+
}));
|
|
809
|
+
}
|
|
810
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KeycloakSecurityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
811
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KeycloakSecurityService }); }
|
|
812
|
+
}
|
|
813
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: KeycloakSecurityService, decorators: [{
|
|
814
|
+
type: Injectable
|
|
815
|
+
}], ctorParameters: () => [] });
|
|
816
|
+
|
|
570
817
|
class BaseModuleComponent {
|
|
818
|
+
static { this.readRight = 'read'; }
|
|
819
|
+
static { this.editRight = 'edit'; }
|
|
820
|
+
static { this.deleteRight = 'delete'; }
|
|
571
821
|
/**
|
|
572
822
|
* Updates local settings and persists them to local storage.
|
|
573
823
|
* @return {void}
|
|
@@ -615,12 +865,21 @@ class BaseModuleComponent {
|
|
|
615
865
|
get isSecurity() {
|
|
616
866
|
return this.topBarService.checkId('security');
|
|
617
867
|
}
|
|
868
|
+
/**
|
|
869
|
+
* Gets an instant translation for a key or an array of keys.
|
|
870
|
+
*/
|
|
871
|
+
t(key, interpolateParams) {
|
|
872
|
+
return this.translateService.instant(key, interpolateParams);
|
|
873
|
+
}
|
|
618
874
|
/**
|
|
619
875
|
* Initializes the component and subscribes to local settings updates.
|
|
620
876
|
*/
|
|
621
877
|
constructor() {
|
|
622
878
|
this.isInitialized = false;
|
|
623
879
|
this.moduleInstanceReloadPromise = Promise.resolve();
|
|
880
|
+
this.destroyRef = inject(DestroyRef);
|
|
881
|
+
this.securityDataService = inject(SecurityDataService);
|
|
882
|
+
this.securityService = inject(SecurityService);
|
|
624
883
|
/**
|
|
625
884
|
* Provide access to app settings
|
|
626
885
|
*/
|
|
@@ -683,6 +942,11 @@ class BaseModuleComponent {
|
|
|
683
942
|
* @type {Subject<TLocalStoreSettings>}
|
|
684
943
|
*/
|
|
685
944
|
this.localSettingsUpdate = new Subject();
|
|
945
|
+
this.l10nService = inject(L10nService);
|
|
946
|
+
this.canRead = false;
|
|
947
|
+
this.canEdit = false;
|
|
948
|
+
this.canDelete = false;
|
|
949
|
+
this.securityRightsLoaded = false;
|
|
686
950
|
/**
|
|
687
951
|
* A unique numerical identifier for the module.
|
|
688
952
|
* @type {number}
|
|
@@ -704,6 +968,7 @@ class BaseModuleComponent {
|
|
|
704
968
|
});
|
|
705
969
|
this.subscriptions.push(this.route.url.subscribe((url) => {
|
|
706
970
|
this.controller = url[0].path;
|
|
971
|
+
this.l10n$ = this.l10nService.get(this.controller);
|
|
707
972
|
}));
|
|
708
973
|
this.subscriptions.push(this.route.paramMap.subscribe((params) => {
|
|
709
974
|
const routeId = params.get('id');
|
|
@@ -725,6 +990,7 @@ class BaseModuleComponent {
|
|
|
725
990
|
ngOnDestroy() {
|
|
726
991
|
this.topBarService.setTopBarItems([]);
|
|
727
992
|
this.topBarService.activeId = this.topBarItems[0].id;
|
|
993
|
+
this.rightsSubscription?.unsubscribe();
|
|
728
994
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
729
995
|
}
|
|
730
996
|
/**
|
|
@@ -782,10 +1048,58 @@ class BaseModuleComponent {
|
|
|
782
1048
|
* Called whenever the module instance changes, including the first load.
|
|
783
1049
|
* Derived components can override this to refresh module-specific data.
|
|
784
1050
|
*/
|
|
785
|
-
async onModuleInstanceChange() {
|
|
1051
|
+
async onModuleInstanceChange() {
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Called whenever current user rights for the active module instance are recalculated.
|
|
1055
|
+
*/
|
|
1056
|
+
onSecurityRightsChange() {
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Starts watching current token roles and maps them to module instance security settings.
|
|
1060
|
+
*/
|
|
1061
|
+
watchSecurityRights(controller = this.controller, id = this.id) {
|
|
1062
|
+
this.rightsSubscription?.unsubscribe();
|
|
1063
|
+
this.resetRightsState();
|
|
1064
|
+
if (!controller || id == null) {
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
this.rightsSubscription = this.securityService.payload
|
|
1068
|
+
.pipe(switchMap((payload) => from(this.securityDataService.getSecurity(controller, id)).pipe(map((securitySettings) => ({ payload, securitySettings })))), takeUntilDestroyed(this.destroyRef))
|
|
1069
|
+
.subscribe({
|
|
1070
|
+
next: ({ payload, securitySettings }) => {
|
|
1071
|
+
const roles = payload?.realm_access?.roles ?? [];
|
|
1072
|
+
this.updateRightsState(roles, securitySettings);
|
|
1073
|
+
},
|
|
1074
|
+
error: (error) => {
|
|
1075
|
+
this.securityRightsLoaded = true;
|
|
1076
|
+
console.error('Не удалось загрузить права', error);
|
|
1077
|
+
this.onSecurityRightsChange();
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
resetRightsState() {
|
|
1082
|
+
this.canRead = false;
|
|
1083
|
+
this.canEdit = false;
|
|
1084
|
+
this.canDelete = false;
|
|
1085
|
+
this.securityRightsLoaded = false;
|
|
1086
|
+
}
|
|
1087
|
+
updateRightsState(roles, securitySettings) {
|
|
1088
|
+
this.canRead = this.hasSecurityRight(roles, securitySettings, BaseModuleComponent.readRight);
|
|
1089
|
+
this.canEdit = this.hasSecurityRight(roles, securitySettings, BaseModuleComponent.editRight);
|
|
1090
|
+
this.canDelete = this.hasSecurityRight(roles, securitySettings, BaseModuleComponent.deleteRight);
|
|
1091
|
+
this.securityRightsLoaded = true;
|
|
1092
|
+
this.onSecurityRightsChange();
|
|
1093
|
+
}
|
|
1094
|
+
hasSecurityRight(roles, securitySettings, code) {
|
|
1095
|
+
return securitySettings
|
|
1096
|
+
.find((security) => security.code === code)
|
|
1097
|
+
?.roles?.some((role) => roles.includes(role)) ?? false;
|
|
1098
|
+
}
|
|
786
1099
|
async reloadModuleInstance() {
|
|
787
1100
|
this.moduleInstanceReloadPromise = this.moduleInstanceReloadPromise.then(async () => {
|
|
788
1101
|
await this.getSettings();
|
|
1102
|
+
this.watchSecurityRights();
|
|
789
1103
|
await this.onModuleInstanceChange();
|
|
790
1104
|
});
|
|
791
1105
|
await this.moduleInstanceReloadPromise;
|
|
@@ -798,48 +1112,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
798
1112
|
args: [{ standalone: true, template: '' }]
|
|
799
1113
|
}], ctorParameters: () => [] });
|
|
800
1114
|
|
|
801
|
-
class SecurityDataService extends BaseDataService {
|
|
802
|
-
getSecurity(controller, id) {
|
|
803
|
-
return this.sendRequest(this.baseUrl + `api/${controller}/get-security?id=${id}`);
|
|
804
|
-
}
|
|
805
|
-
saveSecurity(controller, request) {
|
|
806
|
-
return this.sendRequest(this.baseUrl + `api/${controller}/put-security`, 'PUT', request);
|
|
807
|
-
}
|
|
808
|
-
getRealmRoles() {
|
|
809
|
-
return this.sendRequest(this.baseUrl + `api/security/get-realm-roles`);
|
|
810
|
-
}
|
|
811
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityDataService, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
812
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityDataService }); }
|
|
813
|
-
}
|
|
814
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityDataService, decorators: [{
|
|
815
|
-
type: Injectable
|
|
816
|
-
}] });
|
|
817
|
-
|
|
818
1115
|
class SecurityComponent {
|
|
819
1116
|
constructor() {
|
|
820
1117
|
this.msgService = inject(MsgService);
|
|
821
1118
|
this.dataService = inject(SecurityDataService);
|
|
822
1119
|
this.translateService = inject(TranslateService);
|
|
1120
|
+
this.securityLoadToken = 0;
|
|
1121
|
+
this.securityData = [];
|
|
823
1122
|
this.roles = [];
|
|
824
1123
|
}
|
|
825
1124
|
ngOnDestroy() {
|
|
826
1125
|
// on destroy
|
|
827
1126
|
}
|
|
828
|
-
|
|
829
|
-
if (
|
|
830
|
-
this.
|
|
831
|
-
}
|
|
832
|
-
if (!this.controller) {
|
|
833
|
-
this.msgService.error('Controller not passed!');
|
|
1127
|
+
ngOnChanges(changes) {
|
|
1128
|
+
if (changes['id'] || changes['controller']) {
|
|
1129
|
+
void this.loadSecurity();
|
|
834
1130
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
}, (error) => this.msgService.error(error));
|
|
1131
|
+
}
|
|
1132
|
+
ngOnInit() {
|
|
838
1133
|
this.dataService.getRealmRoles().then((result) => {
|
|
839
1134
|
this.roles = result;
|
|
840
1135
|
}, (error) => this.msgService.error(error));
|
|
841
1136
|
}
|
|
842
1137
|
saveClick() {
|
|
1138
|
+
if (this.id == null) {
|
|
1139
|
+
this.msgService.error('Module id not passed!');
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
if (!this.controller) {
|
|
1143
|
+
this.msgService.error('Controller not passed!');
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
843
1146
|
const request = {
|
|
844
1147
|
id: this.id,
|
|
845
1148
|
securities: this.securityData
|
|
@@ -850,11 +1153,31 @@ class SecurityComponent {
|
|
|
850
1153
|
}
|
|
851
1154
|
saveKeyDown($event) {
|
|
852
1155
|
if ($event.key === 'Enter' || $event.key === 'Space') {
|
|
853
|
-
this.
|
|
1156
|
+
this.saveClick();
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
async loadSecurity() {
|
|
1160
|
+
const loadToken = ++this.securityLoadToken;
|
|
1161
|
+
const controller = this.controller;
|
|
1162
|
+
const id = this.id;
|
|
1163
|
+
this.securityData = [];
|
|
1164
|
+
if (!controller || id == null) {
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
try {
|
|
1168
|
+
const result = await this.dataService.getSecurity(controller, id);
|
|
1169
|
+
if (loadToken === this.securityLoadToken) {
|
|
1170
|
+
this.securityData = result;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
catch (error) {
|
|
1174
|
+
if (loadToken === this.securityLoadToken) {
|
|
1175
|
+
this.msgService.error(error);
|
|
1176
|
+
}
|
|
854
1177
|
}
|
|
855
1178
|
}
|
|
856
1179
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: SecurityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
857
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: SecurityComponent, isStandalone: true, selector: "security", inputs: { id: "id", controller: "controller" }, ngImport: i0, template: `
|
|
1180
|
+
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: `
|
|
858
1181
|
<div class="flex flex-col md:flex-row gap-8">
|
|
859
1182
|
<div class="md:w-1/2">
|
|
860
1183
|
<div class="card flex flex-col gap-4">
|
|
@@ -869,7 +1192,7 @@ class SecurityComponent {
|
|
|
869
1192
|
</label>
|
|
870
1193
|
<p-multiSelect
|
|
871
1194
|
id="oip-security-multiselect-{{ item.name }}"
|
|
872
|
-
placeholder="
|
|
1195
|
+
placeholder="{{ 'securityComponent.selectRoles' | translate }}"
|
|
873
1196
|
[maxSelectedLabels]="10"
|
|
874
1197
|
[options]="roles"
|
|
875
1198
|
[(ngModel)]="item.roles" />
|
|
@@ -907,7 +1230,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
907
1230
|
</label>
|
|
908
1231
|
<p-multiSelect
|
|
909
1232
|
id="oip-security-multiselect-{{ item.name }}"
|
|
910
|
-
placeholder="
|
|
1233
|
+
placeholder="{{ 'securityComponent.selectRoles' | translate }}"
|
|
911
1234
|
[maxSelectedLabels]="10"
|
|
912
1235
|
[options]="roles"
|
|
913
1236
|
[(ngModel)]="item.roles" />
|
|
@@ -934,11 +1257,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
934
1257
|
type: Input
|
|
935
1258
|
}] } });
|
|
936
1259
|
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1260
|
+
const APP_THEME_PRESETS = new InjectionToken('APP_THEME_PRESETS', {
|
|
1261
|
+
factory: () => []
|
|
1262
|
+
});
|
|
1263
|
+
const APP_THEME_PRESETS_MERGE_MODE = new InjectionToken('APP_THEME_PRESETS_MERGE_MODE', {
|
|
1264
|
+
factory: () => 'mergeWithDefaults'
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1267
|
+
const DEFAULT_THEME_PRESETS = [
|
|
1268
|
+
{ id: 'Aura', label: 'Aura', preset: Aura },
|
|
1269
|
+
{ id: 'Lara', label: 'Lara', preset: Lara },
|
|
1270
|
+
{ id: 'Nora', label: 'Nora', preset: Nora }
|
|
1271
|
+
];
|
|
1272
|
+
const PRIMARY_COLORS = [
|
|
1273
|
+
'emerald',
|
|
1274
|
+
'green',
|
|
1275
|
+
'lime',
|
|
1276
|
+
'orange',
|
|
1277
|
+
'amber',
|
|
1278
|
+
'yellow',
|
|
1279
|
+
'teal',
|
|
1280
|
+
'cyan',
|
|
1281
|
+
'sky',
|
|
1282
|
+
'blue',
|
|
1283
|
+
'indigo',
|
|
1284
|
+
'violet',
|
|
1285
|
+
'purple',
|
|
1286
|
+
'fuchsia',
|
|
1287
|
+
'pink',
|
|
1288
|
+
'rose'
|
|
1289
|
+
];
|
|
942
1290
|
class AppConfiguratorComponent {
|
|
943
1291
|
constructor() {
|
|
944
1292
|
this.router = inject(Router);
|
|
@@ -946,7 +1294,14 @@ class AppConfiguratorComponent {
|
|
|
946
1294
|
this.layoutService = inject(LayoutService);
|
|
947
1295
|
this.platformId = inject(PLATFORM_ID);
|
|
948
1296
|
this.primeng = inject(PrimeNG);
|
|
949
|
-
this.
|
|
1297
|
+
this.injectedThemePresets = inject(APP_THEME_PRESETS);
|
|
1298
|
+
this.themePresetMergeMode = inject(APP_THEME_PRESETS_MERGE_MODE);
|
|
1299
|
+
this.themePresets = this.getThemePresets();
|
|
1300
|
+
this.themePresetsMap = new Map(this.themePresets.map((theme) => [theme.id, theme]));
|
|
1301
|
+
this.defaultThemePreset = this.themePresets[0] ?? DEFAULT_THEME_PRESETS[0];
|
|
1302
|
+
this.fallbackPrimaryColors = (DEFAULT_THEME_PRESETS[0].preset
|
|
1303
|
+
.primitive ?? {});
|
|
1304
|
+
this.presets = this.themePresets.map((theme) => ({ label: theme.label ?? theme.id, value: theme.id }));
|
|
950
1305
|
this.showMenuModeButton = signal(!this.router.url.includes('auth'), ...(ngDevMode ? [{ debugName: "showMenuModeButton" }] : []));
|
|
951
1306
|
this.menuModeOptions = [
|
|
952
1307
|
{ label: 'Static', value: 'static' },
|
|
@@ -1097,43 +1452,23 @@ class AppConfiguratorComponent {
|
|
|
1097
1452
|
this.selectedPreset = computed(() => this.layoutService.layoutConfig().preset, ...(ngDevMode ? [{ debugName: "selectedPreset" }] : []));
|
|
1098
1453
|
this.menuMode = computed(() => this.layoutService.layoutConfig().menuMode, ...(ngDevMode ? [{ debugName: "menuMode" }] : []));
|
|
1099
1454
|
this.primaryColors = computed(() => {
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1102
|
-
'emerald',
|
|
1103
|
-
'green',
|
|
1104
|
-
'lime',
|
|
1105
|
-
'orange',
|
|
1106
|
-
'amber',
|
|
1107
|
-
'yellow',
|
|
1108
|
-
'teal',
|
|
1109
|
-
'cyan',
|
|
1110
|
-
'sky',
|
|
1111
|
-
'blue',
|
|
1112
|
-
'indigo',
|
|
1113
|
-
'violet',
|
|
1114
|
-
'purple',
|
|
1115
|
-
'fuchsia',
|
|
1116
|
-
'pink',
|
|
1117
|
-
'rose'
|
|
1118
|
-
];
|
|
1119
|
-
const palettes = [{ name: 'noir', palette: {} }];
|
|
1120
|
-
colors.forEach((color) => {
|
|
1121
|
-
palettes.push({
|
|
1122
|
-
name: color,
|
|
1123
|
-
palette: presetPalette?.[color]
|
|
1124
|
-
});
|
|
1125
|
-
});
|
|
1126
|
-
return palettes;
|
|
1455
|
+
const activeThemePreset = this.getThemeById(this.layoutService.layoutConfig().preset);
|
|
1456
|
+
return this.getPrimaryColorOptions(activeThemePreset);
|
|
1127
1457
|
}, ...(ngDevMode ? [{ debugName: "primaryColors" }] : []));
|
|
1458
|
+
this.surfaceColors = computed(() => {
|
|
1459
|
+
const activeThemePreset = this.getThemeById(this.layoutService.layoutConfig().preset);
|
|
1460
|
+
return this.getSurfaceColorOptions(activeThemePreset);
|
|
1461
|
+
}, ...(ngDevMode ? [{ debugName: "surfaceColors" }] : []));
|
|
1128
1462
|
}
|
|
1129
1463
|
ngOnInit() {
|
|
1130
1464
|
if (isPlatformBrowser(this.platformId)) {
|
|
1131
|
-
this.
|
|
1465
|
+
const presetId = this.ensureValidThemeId(this.layoutService.layoutConfig().preset);
|
|
1466
|
+
this.onPresetChange(presetId);
|
|
1132
1467
|
}
|
|
1133
1468
|
}
|
|
1134
1469
|
getPresetExt() {
|
|
1135
1470
|
const color = this.primaryColors().find((c) => c.name === this.selectedPrimaryColor()) || {};
|
|
1136
|
-
const preset = this.layoutService.layoutConfig().preset;
|
|
1471
|
+
const preset = this.getThemeById(this.layoutService.layoutConfig().preset).id;
|
|
1137
1472
|
if (color.name === 'noir') {
|
|
1138
1473
|
return {
|
|
1139
1474
|
semantic: {
|
|
@@ -1258,307 +1593,259 @@ class AppConfiguratorComponent {
|
|
|
1258
1593
|
};
|
|
1259
1594
|
}
|
|
1260
1595
|
}
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
event.stopPropagation();
|
|
1276
|
-
}
|
|
1277
|
-
applyTheme(type, color) {
|
|
1278
|
-
if (type === 'primary') {
|
|
1279
|
-
updatePreset(this.getPresetExt());
|
|
1280
|
-
}
|
|
1281
|
-
else if (type === 'surface') {
|
|
1282
|
-
updateSurfacePalette(color.palette);
|
|
1596
|
+
getThemePresets() {
|
|
1597
|
+
const source = this.themePresetMergeMode === 'replaceDefaults' ? [] : [...DEFAULT_THEME_PRESETS];
|
|
1598
|
+
const result = [...source];
|
|
1599
|
+
for (const theme of this.injectedThemePresets ?? []) {
|
|
1600
|
+
if (!theme?.id || !theme?.preset) {
|
|
1601
|
+
continue;
|
|
1602
|
+
}
|
|
1603
|
+
const index = result.findIndex((item) => item.id === theme.id);
|
|
1604
|
+
if (index >= 0) {
|
|
1605
|
+
result[index] = theme;
|
|
1606
|
+
}
|
|
1607
|
+
else {
|
|
1608
|
+
result.push(theme);
|
|
1609
|
+
}
|
|
1283
1610
|
}
|
|
1611
|
+
return result;
|
|
1284
1612
|
}
|
|
1285
|
-
|
|
1286
|
-
this.
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1301
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppConfiguratorComponent, isStandalone: true, selector: "app-configurator", host: { classAttribute: "hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]" }, ngImport: i0, template: `
|
|
1302
|
-
<div class="flex flex-col gap-4">
|
|
1303
|
-
<div>
|
|
1304
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
|
|
1305
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1306
|
-
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
1307
|
-
<button
|
|
1308
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1309
|
-
id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
|
|
1310
|
-
type="button"
|
|
1311
|
-
[ngClass]="{
|
|
1312
|
-
'outline-primary': primaryColor.name === selectedPrimaryColor()
|
|
1313
|
-
}"
|
|
1314
|
-
[style]="{
|
|
1315
|
-
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
1316
|
-
}"
|
|
1317
|
-
[title]="primaryColor.name"
|
|
1318
|
-
(click)="updateColors($event, 'primary', primaryColor)"></button>
|
|
1319
|
-
}
|
|
1320
|
-
</div>
|
|
1321
|
-
</div>
|
|
1322
|
-
<div>
|
|
1323
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
|
|
1324
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1325
|
-
@for (surface of surfaces; track surface.name) {
|
|
1326
|
-
<button
|
|
1327
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1328
|
-
id="oip-app-configurator-surface-color-{{ surface.name }}"
|
|
1329
|
-
type="button"
|
|
1330
|
-
[ngClass]="{
|
|
1331
|
-
'outline-primary': selectedSurfaceColor()
|
|
1332
|
-
? selectedSurfaceColor() === surface.name
|
|
1333
|
-
: layoutService.layoutConfig().darkTheme
|
|
1334
|
-
? surface.name === 'zinc'
|
|
1335
|
-
: surface.name === 'slate'
|
|
1336
|
-
}"
|
|
1337
|
-
[style]="{
|
|
1338
|
-
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
1339
|
-
}"
|
|
1340
|
-
[title]="surface.name"
|
|
1341
|
-
(click)="updateColors($event, 'surface', surface)"></button>
|
|
1342
|
-
}
|
|
1343
|
-
</div>
|
|
1344
|
-
</div>
|
|
1345
|
-
<div class="flex flex-col gap-2">
|
|
1346
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
|
|
1347
|
-
<p-selectButton
|
|
1348
|
-
id="oip-app-configurator-preset-select-button"
|
|
1349
|
-
size="small"
|
|
1350
|
-
[allowEmpty]="false"
|
|
1351
|
-
[ngModel]="selectedPreset()"
|
|
1352
|
-
[options]="presets"
|
|
1353
|
-
(ngModelChange)="onPresetChange($event)" />
|
|
1354
|
-
</div>
|
|
1355
|
-
@if (showMenuModeButton()) {
|
|
1356
|
-
<div class="flex flex-col gap-2">
|
|
1357
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
|
|
1358
|
-
<p-selectButton
|
|
1359
|
-
id="oip-app-configurator-menu-mode-select-button"
|
|
1360
|
-
size="small"
|
|
1361
|
-
[allowEmpty]="false"
|
|
1362
|
-
[ngModel]="menuMode()"
|
|
1363
|
-
[options]="menuModeOptions"
|
|
1364
|
-
(ngModelChange)="onMenuModeChange($event)" />
|
|
1365
|
-
</div>
|
|
1366
|
-
}
|
|
1367
|
-
</div>
|
|
1368
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
1369
|
-
}
|
|
1370
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, decorators: [{
|
|
1371
|
-
type: Component,
|
|
1372
|
-
args: [{
|
|
1373
|
-
selector: 'app-configurator',
|
|
1374
|
-
standalone: true,
|
|
1375
|
-
imports: [CommonModule, FormsModule, SelectButtonModule, TranslatePipe],
|
|
1376
|
-
template: `
|
|
1377
|
-
<div class="flex flex-col gap-4">
|
|
1378
|
-
<div>
|
|
1379
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
|
|
1380
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1381
|
-
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
1382
|
-
<button
|
|
1383
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1384
|
-
id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
|
|
1385
|
-
type="button"
|
|
1386
|
-
[ngClass]="{
|
|
1387
|
-
'outline-primary': primaryColor.name === selectedPrimaryColor()
|
|
1388
|
-
}"
|
|
1389
|
-
[style]="{
|
|
1390
|
-
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
1391
|
-
}"
|
|
1392
|
-
[title]="primaryColor.name"
|
|
1393
|
-
(click)="updateColors($event, 'primary', primaryColor)"></button>
|
|
1394
|
-
}
|
|
1395
|
-
</div>
|
|
1396
|
-
</div>
|
|
1397
|
-
<div>
|
|
1398
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
|
|
1399
|
-
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1400
|
-
@for (surface of surfaces; track surface.name) {
|
|
1401
|
-
<button
|
|
1402
|
-
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1403
|
-
id="oip-app-configurator-surface-color-{{ surface.name }}"
|
|
1404
|
-
type="button"
|
|
1405
|
-
[ngClass]="{
|
|
1406
|
-
'outline-primary': selectedSurfaceColor()
|
|
1407
|
-
? selectedSurfaceColor() === surface.name
|
|
1408
|
-
: layoutService.layoutConfig().darkTheme
|
|
1409
|
-
? surface.name === 'zinc'
|
|
1410
|
-
: surface.name === 'slate'
|
|
1411
|
-
}"
|
|
1412
|
-
[style]="{
|
|
1413
|
-
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
1414
|
-
}"
|
|
1415
|
-
[title]="surface.name"
|
|
1416
|
-
(click)="updateColors($event, 'surface', surface)"></button>
|
|
1417
|
-
}
|
|
1418
|
-
</div>
|
|
1419
|
-
</div>
|
|
1420
|
-
<div class="flex flex-col gap-2">
|
|
1421
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
|
|
1422
|
-
<p-selectButton
|
|
1423
|
-
id="oip-app-configurator-preset-select-button"
|
|
1424
|
-
size="small"
|
|
1425
|
-
[allowEmpty]="false"
|
|
1426
|
-
[ngModel]="selectedPreset()"
|
|
1427
|
-
[options]="presets"
|
|
1428
|
-
(ngModelChange)="onPresetChange($event)" />
|
|
1429
|
-
</div>
|
|
1430
|
-
@if (showMenuModeButton()) {
|
|
1431
|
-
<div class="flex flex-col gap-2">
|
|
1432
|
-
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
|
|
1433
|
-
<p-selectButton
|
|
1434
|
-
id="oip-app-configurator-menu-mode-select-button"
|
|
1435
|
-
size="small"
|
|
1436
|
-
[allowEmpty]="false"
|
|
1437
|
-
[ngModel]="menuMode()"
|
|
1438
|
-
[options]="menuModeOptions"
|
|
1439
|
-
(ngModelChange)="onMenuModeChange($event)" />
|
|
1440
|
-
</div>
|
|
1441
|
-
}
|
|
1442
|
-
</div>
|
|
1443
|
-
`,
|
|
1444
|
-
host: {
|
|
1445
|
-
class: 'hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]'
|
|
1446
|
-
}
|
|
1447
|
-
}]
|
|
1448
|
-
}] });
|
|
1449
|
-
|
|
1450
|
-
class SecurityService {
|
|
1451
|
-
}
|
|
1452
|
-
/**
|
|
1453
|
-
* SecurityService extends OidcSecurityService to manage authentication,
|
|
1454
|
-
* token handling, and user role access in an Angular application.
|
|
1455
|
-
*
|
|
1456
|
-
* It provides helper methods for checking authentication, managing tokens,
|
|
1457
|
-
* determining user roles, and performing logout and refresh operations.
|
|
1458
|
-
*/
|
|
1459
|
-
class KeycloakSecurityService extends OidcSecurityService {
|
|
1460
|
-
/**
|
|
1461
|
-
* Initializes service and subscribes to authentication events.
|
|
1462
|
-
* When a 'NewAuthenticationResult' event is received, the `auth` method is called.
|
|
1463
|
-
*/
|
|
1464
|
-
constructor() {
|
|
1465
|
-
super();
|
|
1466
|
-
/**
|
|
1467
|
-
* Handles angular OIDC events.
|
|
1468
|
-
*/
|
|
1469
|
-
this.publicEventsService = inject(PublicEventsService);
|
|
1470
|
-
/**
|
|
1471
|
-
* Stores the latest login response from checkAuth().
|
|
1472
|
-
*/
|
|
1473
|
-
this.loginResponse = new BehaviorSubject(null);
|
|
1474
|
-
/**
|
|
1475
|
-
* Stores the decoded access token payload.
|
|
1476
|
-
*/
|
|
1477
|
-
this.payload = new BehaviorSubject(null);
|
|
1478
|
-
/**
|
|
1479
|
-
* Stores user-specific data from the login response.
|
|
1480
|
-
*/
|
|
1481
|
-
this.currentUser = new BehaviorSubject(null);
|
|
1482
|
-
/**
|
|
1483
|
-
* Emits access token updates from initial auth check, manual refresh,
|
|
1484
|
-
* and library authentication events.
|
|
1485
|
-
*/
|
|
1486
|
-
this.accessToken = new ReplaySubject(1);
|
|
1487
|
-
this.publicEventsService
|
|
1488
|
-
.registerForEvents()
|
|
1489
|
-
.pipe(filter((event) => event.type === EventTypes.NewAuthenticationResult))
|
|
1490
|
-
.subscribe(() => {
|
|
1491
|
-
super.getAccessToken().subscribe(token => { this.accessToken.next(token); });
|
|
1492
|
-
this.auth();
|
|
1493
|
-
});
|
|
1494
|
-
}
|
|
1495
|
-
getCurrentUser() {
|
|
1496
|
-
return this.currentUser.getValue();
|
|
1497
|
-
}
|
|
1498
|
-
getCurrentUser$() {
|
|
1499
|
-
return this.currentUser.asObservable();
|
|
1500
|
-
}
|
|
1501
|
-
/**
|
|
1502
|
-
* Returns the ID token for the sign-in.
|
|
1503
|
-
* @returns A string with the id token.
|
|
1504
|
-
*/
|
|
1505
|
-
getAccessToken(configId) {
|
|
1506
|
-
return merge(super.getAccessToken(configId), this.accessToken.asObservable()).pipe(distinctUntilChanged());
|
|
1507
|
-
}
|
|
1508
|
-
/**
|
|
1509
|
-
* Indicates whether the current user has the 'admin' role.
|
|
1510
|
-
*
|
|
1511
|
-
* @returns {boolean} True if the user is an admin, false otherwise.
|
|
1512
|
-
*/
|
|
1513
|
-
isAdmin() {
|
|
1514
|
-
return this.payload.getValue()?.realm_access?.roles?.includes('admin');
|
|
1515
|
-
}
|
|
1516
|
-
/**
|
|
1517
|
-
* Initiates authentication check and updates login response, user data,
|
|
1518
|
-
* and decoded token payload if authenticated.
|
|
1519
|
-
*/
|
|
1520
|
-
auth() {
|
|
1521
|
-
super.checkAuth().subscribe((_response) => {
|
|
1522
|
-
this.loginResponse.next(_response);
|
|
1523
|
-
this.currentUser.next(_response.userData);
|
|
1524
|
-
this.getPayloadFromAccessToken().subscribe((_token) => {
|
|
1525
|
-
this.payload.next(_token);
|
|
1613
|
+
getThemeById(themeId) {
|
|
1614
|
+
return this.themePresetsMap.get(themeId ?? '') ?? this.defaultThemePreset;
|
|
1615
|
+
}
|
|
1616
|
+
getPrimaryColorOptions(activeThemePreset) {
|
|
1617
|
+
if (activeThemePreset.primaryColors) {
|
|
1618
|
+
return Object.entries(activeThemePreset.primaryColors)
|
|
1619
|
+
.filter((entry) => Boolean(entry[1]))
|
|
1620
|
+
.map(([name, palette]) => ({ name, palette }));
|
|
1621
|
+
}
|
|
1622
|
+
const presetPalette = (activeThemePreset.preset.primitive ?? {});
|
|
1623
|
+
const palettes = [{ name: 'noir', palette: {} }];
|
|
1624
|
+
PRIMARY_COLORS.forEach((color) => {
|
|
1625
|
+
palettes.push({
|
|
1626
|
+
name: color,
|
|
1627
|
+
palette: presetPalette[color] ?? this.fallbackPrimaryColors[color]
|
|
1526
1628
|
});
|
|
1527
1629
|
});
|
|
1630
|
+
return palettes;
|
|
1528
1631
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
this.logoff(configId, logoutAuthOptions).subscribe((x) => this.payload.next(x));
|
|
1632
|
+
getSurfaceColorOptions(activeThemePreset) {
|
|
1633
|
+
if (activeThemePreset.surfaceColors) {
|
|
1634
|
+
return Object.entries(activeThemePreset.surfaceColors)
|
|
1635
|
+
.filter((entry) => Boolean(entry[1]))
|
|
1636
|
+
.map(([name, palette]) => ({ name, palette }));
|
|
1637
|
+
}
|
|
1638
|
+
return this.surfaces;
|
|
1537
1639
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
this.
|
|
1543
|
-
|
|
1544
|
-
|
|
1640
|
+
ensureValidThemeId(themeId) {
|
|
1641
|
+
if (themeId && this.themePresetsMap.has(themeId)) {
|
|
1642
|
+
return themeId;
|
|
1643
|
+
}
|
|
1644
|
+
if (themeId && isPlatformBrowser(this.platformId)) {
|
|
1645
|
+
console.warn(`[AppConfigurator] Unknown theme preset "${themeId}", fallback to "${this.defaultThemePreset.id}".`);
|
|
1646
|
+
}
|
|
1647
|
+
return this.defaultThemePreset.id;
|
|
1545
1648
|
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1649
|
+
updateColors(event, type, color) {
|
|
1650
|
+
if (type === 'primary') {
|
|
1651
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1652
|
+
...state,
|
|
1653
|
+
primary: color.name
|
|
1654
|
+
}));
|
|
1655
|
+
}
|
|
1656
|
+
else if (type === 'surface') {
|
|
1657
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1658
|
+
...state,
|
|
1659
|
+
surface: color.name
|
|
1660
|
+
}));
|
|
1661
|
+
}
|
|
1662
|
+
this.applyTheme(type, color);
|
|
1663
|
+
event.stopPropagation();
|
|
1664
|
+
}
|
|
1665
|
+
applyTheme(type, color) {
|
|
1666
|
+
if (type === 'primary') {
|
|
1667
|
+
updatePreset(this.getPresetExt());
|
|
1668
|
+
}
|
|
1669
|
+
else if (type === 'surface') {
|
|
1670
|
+
updateSurfacePalette(color.palette);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
onPresetChange(event) {
|
|
1674
|
+
const nextThemeId = this.ensureValidThemeId(event);
|
|
1675
|
+
const nextTheme = this.getThemeById(nextThemeId);
|
|
1676
|
+
const primaryColors = this.getPrimaryColorOptions(nextTheme);
|
|
1677
|
+
const surfaceColors = this.getSurfaceColorOptions(nextTheme);
|
|
1678
|
+
this.layoutService.layoutConfig.update((state) => ({
|
|
1679
|
+
...state,
|
|
1680
|
+
preset: nextThemeId,
|
|
1681
|
+
primary: primaryColors.some((color) => color.name === state.primary) ? state.primary : (primaryColors[0]?.name ?? state.primary),
|
|
1682
|
+
surface: nextTheme.surfaceColors && !surfaceColors.some((color) => color.name === state.surface)
|
|
1683
|
+
? (surfaceColors[0]?.name ?? state.surface)
|
|
1684
|
+
: state.surface
|
|
1554
1685
|
}));
|
|
1686
|
+
const preset = nextTheme.preset;
|
|
1687
|
+
const surfacePalette = this.surfaceColors().find((s) => s.name === this.selectedSurfaceColor())?.palette;
|
|
1688
|
+
$t().preset(preset).preset(this.getPresetExt()).surfacePalette(surfacePalette).use({ useDefaultOptions: true });
|
|
1555
1689
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1690
|
+
onMenuModeChange(event) {
|
|
1691
|
+
this.layoutService.layoutConfig.update((prev) => ({
|
|
1692
|
+
...prev,
|
|
1693
|
+
menuMode: event
|
|
1694
|
+
}));
|
|
1695
|
+
}
|
|
1696
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1697
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppConfiguratorComponent, isStandalone: true, selector: "app-configurator", host: { classAttribute: "hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]" }, ngImport: i0, template: `
|
|
1698
|
+
<div class="flex flex-col gap-4">
|
|
1699
|
+
<div>
|
|
1700
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
|
|
1701
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1702
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
1703
|
+
<button
|
|
1704
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1705
|
+
id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
|
|
1706
|
+
type="button"
|
|
1707
|
+
[ngClass]="{
|
|
1708
|
+
'outline-primary': primaryColor.name === selectedPrimaryColor()
|
|
1709
|
+
}"
|
|
1710
|
+
[style]="{
|
|
1711
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
1712
|
+
}"
|
|
1713
|
+
[title]="primaryColor.name"
|
|
1714
|
+
(click)="updateColors($event, 'primary', primaryColor)"></button>
|
|
1715
|
+
}
|
|
1716
|
+
</div>
|
|
1717
|
+
</div>
|
|
1718
|
+
<div>
|
|
1719
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
|
|
1720
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1721
|
+
@for (surface of surfaceColors(); track surface.name) {
|
|
1722
|
+
<button
|
|
1723
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1724
|
+
id="oip-app-configurator-surface-color-{{ surface.name }}"
|
|
1725
|
+
type="button"
|
|
1726
|
+
[ngClass]="{
|
|
1727
|
+
'outline-primary': selectedSurfaceColor()
|
|
1728
|
+
? selectedSurfaceColor() === surface.name
|
|
1729
|
+
: layoutService.layoutConfig().darkTheme
|
|
1730
|
+
? surface.name === 'zinc'
|
|
1731
|
+
: surface.name === 'slate'
|
|
1732
|
+
}"
|
|
1733
|
+
[style]="{
|
|
1734
|
+
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
1735
|
+
}"
|
|
1736
|
+
[title]="surface.name"
|
|
1737
|
+
(click)="updateColors($event, 'surface', surface)"></button>
|
|
1738
|
+
}
|
|
1739
|
+
</div>
|
|
1740
|
+
</div>
|
|
1741
|
+
<div class="flex flex-col gap-2">
|
|
1742
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
|
|
1743
|
+
<p-selectButton
|
|
1744
|
+
id="oip-app-configurator-preset-select-button"
|
|
1745
|
+
size="small"
|
|
1746
|
+
[allowEmpty]="false"
|
|
1747
|
+
[ngModel]="selectedPreset()"
|
|
1748
|
+
[options]="presets"
|
|
1749
|
+
optionLabel="label"
|
|
1750
|
+
optionValue="value"
|
|
1751
|
+
(ngModelChange)="onPresetChange($event)" />
|
|
1752
|
+
</div>
|
|
1753
|
+
@if (showMenuModeButton()) {
|
|
1754
|
+
<div class="flex flex-col gap-2">
|
|
1755
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
|
|
1756
|
+
<p-selectButton
|
|
1757
|
+
id="oip-app-configurator-menu-mode-select-button"
|
|
1758
|
+
size="small"
|
|
1759
|
+
[allowEmpty]="false"
|
|
1760
|
+
[ngModel]="menuMode()"
|
|
1761
|
+
[options]="menuModeOptions"
|
|
1762
|
+
(ngModelChange)="onMenuModeChange($event)" />
|
|
1763
|
+
</div>
|
|
1764
|
+
}
|
|
1765
|
+
</div>
|
|
1766
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: "ngmodule", type: SelectButtonModule }, { kind: "component", type: i3.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
1558
1767
|
}
|
|
1559
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
1560
|
-
type:
|
|
1561
|
-
|
|
1768
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppConfiguratorComponent, decorators: [{
|
|
1769
|
+
type: Component,
|
|
1770
|
+
args: [{
|
|
1771
|
+
selector: 'app-configurator',
|
|
1772
|
+
standalone: true,
|
|
1773
|
+
imports: [CommonModule, FormsModule, SelectButtonModule, TranslatePipe],
|
|
1774
|
+
template: `
|
|
1775
|
+
<div class="flex flex-col gap-4">
|
|
1776
|
+
<div>
|
|
1777
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.primary' | translate }}</span>
|
|
1778
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1779
|
+
@for (primaryColor of primaryColors(); track primaryColor.name) {
|
|
1780
|
+
<button
|
|
1781
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1782
|
+
id="oip-app-configurator-primary-color-{{ primaryColor.name }}"
|
|
1783
|
+
type="button"
|
|
1784
|
+
[ngClass]="{
|
|
1785
|
+
'outline-primary': primaryColor.name === selectedPrimaryColor()
|
|
1786
|
+
}"
|
|
1787
|
+
[style]="{
|
|
1788
|
+
'background-color': primaryColor?.name === 'noir' ? 'var(--text-color)' : primaryColor?.palette?.['500']
|
|
1789
|
+
}"
|
|
1790
|
+
[title]="primaryColor.name"
|
|
1791
|
+
(click)="updateColors($event, 'primary', primaryColor)"></button>
|
|
1792
|
+
}
|
|
1793
|
+
</div>
|
|
1794
|
+
</div>
|
|
1795
|
+
<div>
|
|
1796
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.surface' | translate }}</span>
|
|
1797
|
+
<div class="pt-2 flex gap-2 flex-wrap justify-start">
|
|
1798
|
+
@for (surface of surfaceColors(); track surface.name) {
|
|
1799
|
+
<button
|
|
1800
|
+
class="border-none w-5 h-5 rounded-full p-0 cursor-pointer outline-none outline-offset-1"
|
|
1801
|
+
id="oip-app-configurator-surface-color-{{ surface.name }}"
|
|
1802
|
+
type="button"
|
|
1803
|
+
[ngClass]="{
|
|
1804
|
+
'outline-primary': selectedSurfaceColor()
|
|
1805
|
+
? selectedSurfaceColor() === surface.name
|
|
1806
|
+
: layoutService.layoutConfig().darkTheme
|
|
1807
|
+
? surface.name === 'zinc'
|
|
1808
|
+
: surface.name === 'slate'
|
|
1809
|
+
}"
|
|
1810
|
+
[style]="{
|
|
1811
|
+
'background-color': surface?.name === 'noir' ? 'var(--text-color)' : surface?.palette?.['500']
|
|
1812
|
+
}"
|
|
1813
|
+
[title]="surface.name"
|
|
1814
|
+
(click)="updateColors($event, 'surface', surface)"></button>
|
|
1815
|
+
}
|
|
1816
|
+
</div>
|
|
1817
|
+
</div>
|
|
1818
|
+
<div class="flex flex-col gap-2">
|
|
1819
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
|
|
1820
|
+
<p-selectButton
|
|
1821
|
+
id="oip-app-configurator-preset-select-button"
|
|
1822
|
+
size="small"
|
|
1823
|
+
[allowEmpty]="false"
|
|
1824
|
+
[ngModel]="selectedPreset()"
|
|
1825
|
+
[options]="presets"
|
|
1826
|
+
optionLabel="label"
|
|
1827
|
+
optionValue="value"
|
|
1828
|
+
(ngModelChange)="onPresetChange($event)" />
|
|
1829
|
+
</div>
|
|
1830
|
+
@if (showMenuModeButton()) {
|
|
1831
|
+
<div class="flex flex-col gap-2">
|
|
1832
|
+
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.menuMode' | translate }}</span>
|
|
1833
|
+
<p-selectButton
|
|
1834
|
+
id="oip-app-configurator-menu-mode-select-button"
|
|
1835
|
+
size="small"
|
|
1836
|
+
[allowEmpty]="false"
|
|
1837
|
+
[ngModel]="menuMode()"
|
|
1838
|
+
[options]="menuModeOptions"
|
|
1839
|
+
(ngModelChange)="onMenuModeChange($event)" />
|
|
1840
|
+
</div>
|
|
1841
|
+
}
|
|
1842
|
+
</div>
|
|
1843
|
+
`,
|
|
1844
|
+
host: {
|
|
1845
|
+
class: 'hidden absolute top-[3.25rem] right-0 w-72 p-4 bg-surface-0 dark:bg-surface-900 border border-surface rounded-border origin-top shadow-[0px_3px_5px_rgba(0,0,0,0.02),0px_0px_2px_rgba(0,0,0,0.05),0px_1px_4px_rgba(0,0,0,0.08)]'
|
|
1846
|
+
}
|
|
1847
|
+
}]
|
|
1848
|
+
}] });
|
|
1562
1849
|
|
|
1563
1850
|
/**
|
|
1564
1851
|
* UserService is responsible for retrieving and handling user-related data,
|
|
@@ -2011,18 +2298,15 @@ class HttpClient {
|
|
|
2011
2298
|
this.layoutService = inject(LayoutService);
|
|
2012
2299
|
this.baseUrl = "";
|
|
2013
2300
|
this.securityData = null;
|
|
2014
|
-
this.securityWorker = (securityData) => {
|
|
2015
|
-
|
|
2301
|
+
this.securityWorker = (securityData) => ({
|
|
2302
|
+
headers: {
|
|
2016
2303
|
"Accept-language": this.layoutService.language()
|
|
2017
2304
|
? this.layoutService.language()
|
|
2018
2305
|
: "en",
|
|
2019
2306
|
"X-Timezone": this.layoutService.timeZone(),
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
}
|
|
2024
|
-
return { headers };
|
|
2025
|
-
};
|
|
2307
|
+
Authorization: `Bearer ${securityData}`,
|
|
2308
|
+
},
|
|
2309
|
+
});
|
|
2026
2310
|
this.abortControllers = new Map();
|
|
2027
2311
|
this.customFetch = (...fetchParams) => fetch(...fetchParams);
|
|
2028
2312
|
this.baseApiParams = {
|
|
@@ -3442,85 +3726,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3442
3726
|
}]
|
|
3443
3727
|
}] });
|
|
3444
3728
|
|
|
3445
|
-
/**
|
|
3446
|
-
* Service for managing translation loading in the application
|
|
3447
|
-
*/
|
|
3448
|
-
class L10nService {
|
|
3449
|
-
constructor() {
|
|
3450
|
-
this.loadedTranslations = new Set();
|
|
3451
|
-
this.httpClient = inject(HttpClient$1);
|
|
3452
|
-
this.translateService = inject(TranslateService);
|
|
3453
|
-
this.primeNg = inject(PrimeNG);
|
|
3454
|
-
this.layoutService = inject(LayoutService);
|
|
3455
|
-
}
|
|
3456
|
-
/**
|
|
3457
|
-
* Loads translations for a specific component
|
|
3458
|
-
* @param component - Name of the component to load translations for
|
|
3459
|
-
*/
|
|
3460
|
-
loadComponentTranslations(component) {
|
|
3461
|
-
const lang = this.translateService.currentLang;
|
|
3462
|
-
this.loadTranslations(component, lang);
|
|
3463
|
-
}
|
|
3464
|
-
/**
|
|
3465
|
-
* Gets the translated value of a key (or an array of keys)
|
|
3466
|
-
* @returns the translated key, or an object of translated keys
|
|
3467
|
-
*/
|
|
3468
|
-
get(key) {
|
|
3469
|
-
this.loadComponentTranslations(key.split('.')[0]);
|
|
3470
|
-
return this.translateService.get(key);
|
|
3471
|
-
}
|
|
3472
|
-
/**
|
|
3473
|
-
* Internal method to load translations from JSON files
|
|
3474
|
-
* @param component - Component or translation namespace
|
|
3475
|
-
* @param lang - Language code to load translations for
|
|
3476
|
-
*/
|
|
3477
|
-
loadTranslations(component, lang) {
|
|
3478
|
-
const key = `${component}.${lang}`;
|
|
3479
|
-
if (this.loadedTranslations.has(key)) {
|
|
3480
|
-
return;
|
|
3481
|
-
}
|
|
3482
|
-
try {
|
|
3483
|
-
this.httpClient.get(`./assets/i18n/${component}.${lang}.json`).subscribe((translations) => {
|
|
3484
|
-
const current = this.translateService.translations[lang] || {};
|
|
3485
|
-
this.translateService.setTranslation(lang, { ...current, ...translations }, true);
|
|
3486
|
-
this.loadedTranslations.add(key);
|
|
3487
|
-
});
|
|
3488
|
-
}
|
|
3489
|
-
catch (e) {
|
|
3490
|
-
console.error(`No translations found for ${component}.${lang}.json`);
|
|
3491
|
-
console.error(e);
|
|
3492
|
-
}
|
|
3493
|
-
}
|
|
3494
|
-
/**
|
|
3495
|
-
* Changes the lang currently used
|
|
3496
|
-
*/
|
|
3497
|
-
use(selectedLanguage, key = null) {
|
|
3498
|
-
if (key) {
|
|
3499
|
-
this.get(key);
|
|
3500
|
-
}
|
|
3501
|
-
this.translateService.use(selectedLanguage);
|
|
3502
|
-
}
|
|
3503
|
-
init(languages) {
|
|
3504
|
-
this.availableLanguages = languages;
|
|
3505
|
-
this.translateService.addLangs(languages.map((x) => x.code));
|
|
3506
|
-
const lang = this.layoutService.language() ? this.layoutService.language() : 'en';
|
|
3507
|
-
this.translateService.setDefaultLang(lang);
|
|
3508
|
-
this.translateService.use(lang).subscribe(() => {
|
|
3509
|
-
this.loadComponentTranslations('app-info');
|
|
3510
|
-
this.translateService.get('primeng').subscribe((res) => this.primeNg.setTranslation(res));
|
|
3511
|
-
});
|
|
3512
|
-
}
|
|
3513
|
-
instant(key, interpolateParams) {
|
|
3514
|
-
return this.translateService.instant(key, interpolateParams);
|
|
3515
|
-
}
|
|
3516
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: L10nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3517
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: L10nService, providedIn: 'root' }); }
|
|
3518
|
-
}
|
|
3519
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: L10nService, decorators: [{
|
|
3520
|
-
type: Injectable,
|
|
3521
|
-
args: [{ providedIn: 'root' }]
|
|
3522
|
-
}] });
|
|
3523
|
-
|
|
3524
3729
|
class NotfoundComponent {
|
|
3525
3730
|
constructor(l10nService) {
|
|
3526
3731
|
l10nService.get('notfound');
|
|
@@ -4048,7 +4253,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4048
4253
|
class DbMigrationComponent extends BaseModuleComponent {
|
|
4049
4254
|
constructor() {
|
|
4050
4255
|
super();
|
|
4051
|
-
this.l10nService = inject(L10nService);
|
|
4052
4256
|
this.l10nService.loadComponentTranslations('db-migration');
|
|
4053
4257
|
}
|
|
4054
4258
|
async ngOnInit() {
|
|
@@ -4073,84 +4277,84 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
4073
4277
|
return this.baseDataService.sendRequest(`api/${this.controller}/apply-migration`, 'POST', request);
|
|
4074
4278
|
}
|
|
4075
4279
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DbMigrationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4076
|
-
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: `
|
|
4077
|
-
@if (isContent) {
|
|
4078
|
-
<div class="card" style="height: 100%">
|
|
4079
|
-
<p-confirmDialog
|
|
4080
|
-
<div>
|
|
4081
|
-
<h5>{{ 'db-migration.migrationManager' | translate }}</h5>
|
|
4082
|
-
<div class="flex flex-row gap-2">
|
|
4083
|
-
<p-button
|
|
4084
|
-
icon="pi pi-refresh"
|
|
4085
|
-
severity="secondary"
|
|
4086
|
-
tooltipPosition="bottom"
|
|
4087
|
-
[outlined]="true"
|
|
4088
|
-
[pTooltip]="'db-migration.actions.refresh' | translate"
|
|
4089
|
-
(click)="refreshAction()"
|
|
4090
|
-
<p-button
|
|
4091
|
-
icon="pi pi-filter-slash"
|
|
4092
|
-
severity="secondary"
|
|
4093
|
-
tooltipPosition="bottom"
|
|
4094
|
-
[outlined]="true"
|
|
4095
|
-
[pTooltip]="'db-migration.actions.cleanFilter' | translate"
|
|
4096
|
-
(click)="dt.clear()"
|
|
4097
|
-
</div>
|
|
4098
|
-
<div>
|
|
4099
|
-
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
4100
|
-
<ng-template let-columns pTemplate="header">
|
|
4101
|
-
<tr>
|
|
4102
|
-
<th pSortableColumn="name" scope="col">
|
|
4103
|
-
{{ 'db-migration.columns.name' | translate }}
|
|
4104
|
-
<p-columnFilter display="menu" field="name" type="text"
|
|
4105
|
-
</th>
|
|
4106
|
-
<th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
|
|
4107
|
-
<th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
|
|
4108
|
-
<th scope="col">{{ 'db-migration.columns.pending' | translate }}</th>
|
|
4109
|
-
<th scope="col"></th>
|
|
4110
|
-
</tr>
|
|
4111
|
-
</ng-template>
|
|
4112
|
-
|
|
4113
|
-
<ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
|
|
4114
|
-
<tr [pEditableRow]="rowData">
|
|
4115
|
-
<td>
|
|
4116
|
-
{{ rowData.name }}
|
|
4117
|
-
</td>
|
|
4118
|
-
<td>
|
|
4119
|
-
@if (rowData.applied) {
|
|
4120
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"
|
|
4121
|
-
}
|
|
4122
|
-
</td>
|
|
4123
|
-
<td>
|
|
4124
|
-
@if (rowData.exist) {
|
|
4125
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"
|
|
4126
|
-
}
|
|
4127
|
-
</td>
|
|
4128
|
-
<td>
|
|
4129
|
-
@if (rowData.pending) {
|
|
4130
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
4131
|
-
}
|
|
4132
|
-
</td>
|
|
4133
|
-
<td>
|
|
4134
|
-
<p-button
|
|
4135
|
-
icon="pi pi-bolt"
|
|
4136
|
-
pCancelEditableRow
|
|
4137
|
-
pTooltip="{{ 'db-migration.actions.applyMigration' | translate }}"
|
|
4138
|
-
severity="secondary"
|
|
4139
|
-
tooltipPosition="left"
|
|
4140
|
-
[rounded]="true"
|
|
4141
|
-
[text]="true"
|
|
4142
|
-
(click)="applyMigration(rowData)">
|
|
4143
|
-
</p-button>
|
|
4144
|
-
</td>
|
|
4145
|
-
</tr>
|
|
4146
|
-
</ng-template>
|
|
4147
|
-
</p-table>
|
|
4148
|
-
</div>
|
|
4149
|
-
</div>
|
|
4150
|
-
</div>
|
|
4151
|
-
} @else if (isSecurity) {
|
|
4152
|
-
<security [controller]="controller" [id]="id"
|
|
4153
|
-
}
|
|
4280
|
+
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
|
+
@if (isContent) {
|
|
4282
|
+
<div class="card" style="height: 100%">
|
|
4283
|
+
<p-confirmDialog/>
|
|
4284
|
+
<div>
|
|
4285
|
+
<h5>{{ 'db-migration.migrationManager' | translate }}</h5>
|
|
4286
|
+
<div class="flex flex-row gap-2">
|
|
4287
|
+
<p-button
|
|
4288
|
+
icon="pi pi-refresh"
|
|
4289
|
+
severity="secondary"
|
|
4290
|
+
tooltipPosition="bottom"
|
|
4291
|
+
[outlined]="true"
|
|
4292
|
+
[pTooltip]="'db-migration.actions.refresh' | translate"
|
|
4293
|
+
(click)="refreshAction()"/>
|
|
4294
|
+
<p-button
|
|
4295
|
+
icon="pi pi-filter-slash"
|
|
4296
|
+
severity="secondary"
|
|
4297
|
+
tooltipPosition="bottom"
|
|
4298
|
+
[outlined]="true"
|
|
4299
|
+
[pTooltip]="'db-migration.actions.cleanFilter' | translate"
|
|
4300
|
+
(click)="dt.clear()"/>
|
|
4301
|
+
</div>
|
|
4302
|
+
<div>
|
|
4303
|
+
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
4304
|
+
<ng-template let-columns pTemplate="header">
|
|
4305
|
+
<tr>
|
|
4306
|
+
<th pSortableColumn="name" scope="col">
|
|
4307
|
+
{{ 'db-migration.columns.name' | translate }}
|
|
4308
|
+
<p-columnFilter display="menu" field="name" type="text"/>
|
|
4309
|
+
</th>
|
|
4310
|
+
<th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
|
|
4311
|
+
<th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
|
|
4312
|
+
<th scope="col">{{ 'db-migration.columns.pending' | translate }}</th>
|
|
4313
|
+
<th scope="col"></th>
|
|
4314
|
+
</tr>
|
|
4315
|
+
</ng-template>
|
|
4316
|
+
|
|
4317
|
+
<ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
|
|
4318
|
+
<tr [pEditableRow]="rowData">
|
|
4319
|
+
<td>
|
|
4320
|
+
{{ rowData.name }}
|
|
4321
|
+
</td>
|
|
4322
|
+
<td>
|
|
4323
|
+
@if (rowData.applied) {
|
|
4324
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
4325
|
+
}
|
|
4326
|
+
</td>
|
|
4327
|
+
<td>
|
|
4328
|
+
@if (rowData.exist) {
|
|
4329
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"/>
|
|
4330
|
+
}
|
|
4331
|
+
</td>
|
|
4332
|
+
<td>
|
|
4333
|
+
@if (rowData.pending) {
|
|
4334
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
4335
|
+
}
|
|
4336
|
+
</td>
|
|
4337
|
+
<td>
|
|
4338
|
+
<p-button
|
|
4339
|
+
icon="pi pi-bolt"
|
|
4340
|
+
pCancelEditableRow
|
|
4341
|
+
pTooltip="{{ 'db-migration.actions.applyMigration' | translate }}"
|
|
4342
|
+
severity="secondary"
|
|
4343
|
+
tooltipPosition="left"
|
|
4344
|
+
[rounded]="true"
|
|
4345
|
+
[text]="true"
|
|
4346
|
+
(click)="applyMigration(rowData)">
|
|
4347
|
+
</p-button>
|
|
4348
|
+
</td>
|
|
4349
|
+
</tr>
|
|
4350
|
+
</ng-template>
|
|
4351
|
+
</p-table>
|
|
4352
|
+
</div>
|
|
4353
|
+
</div>
|
|
4354
|
+
</div>
|
|
4355
|
+
} @else if (isSecurity) {
|
|
4356
|
+
<security [controller]="controller" [id]="id"/>
|
|
4357
|
+
}
|
|
4154
4358
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$6.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$6.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$6.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1$6.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i1$6.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i1$6.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" }] }); }
|
|
4155
4359
|
}
|
|
4156
4360
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DbMigrationComponent, decorators: [{
|
|
@@ -4170,84 +4374,84 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4170
4374
|
TranslatePipe
|
|
4171
4375
|
],
|
|
4172
4376
|
selector: 'db-migration',
|
|
4173
|
-
template: `
|
|
4174
|
-
@if (isContent) {
|
|
4175
|
-
<div class="card" style="height: 100%">
|
|
4176
|
-
<p-confirmDialog
|
|
4177
|
-
<div>
|
|
4178
|
-
<h5>{{ 'db-migration.migrationManager' | translate }}</h5>
|
|
4179
|
-
<div class="flex flex-row gap-2">
|
|
4180
|
-
<p-button
|
|
4181
|
-
icon="pi pi-refresh"
|
|
4182
|
-
severity="secondary"
|
|
4183
|
-
tooltipPosition="bottom"
|
|
4184
|
-
[outlined]="true"
|
|
4185
|
-
[pTooltip]="'db-migration.actions.refresh' | translate"
|
|
4186
|
-
(click)="refreshAction()"
|
|
4187
|
-
<p-button
|
|
4188
|
-
icon="pi pi-filter-slash"
|
|
4189
|
-
severity="secondary"
|
|
4190
|
-
tooltipPosition="bottom"
|
|
4191
|
-
[outlined]="true"
|
|
4192
|
-
[pTooltip]="'db-migration.actions.cleanFilter' | translate"
|
|
4193
|
-
(click)="dt.clear()"
|
|
4194
|
-
</div>
|
|
4195
|
-
<div>
|
|
4196
|
-
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
4197
|
-
<ng-template let-columns pTemplate="header">
|
|
4198
|
-
<tr>
|
|
4199
|
-
<th pSortableColumn="name" scope="col">
|
|
4200
|
-
{{ 'db-migration.columns.name' | translate }}
|
|
4201
|
-
<p-columnFilter display="menu" field="name" type="text"
|
|
4202
|
-
</th>
|
|
4203
|
-
<th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
|
|
4204
|
-
<th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
|
|
4205
|
-
<th scope="col">{{ 'db-migration.columns.pending' | translate }}</th>
|
|
4206
|
-
<th scope="col"></th>
|
|
4207
|
-
</tr>
|
|
4208
|
-
</ng-template>
|
|
4209
|
-
|
|
4210
|
-
<ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
|
|
4211
|
-
<tr [pEditableRow]="rowData">
|
|
4212
|
-
<td>
|
|
4213
|
-
{{ rowData.name }}
|
|
4214
|
-
</td>
|
|
4215
|
-
<td>
|
|
4216
|
-
@if (rowData.applied) {
|
|
4217
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"
|
|
4218
|
-
}
|
|
4219
|
-
</td>
|
|
4220
|
-
<td>
|
|
4221
|
-
@if (rowData.exist) {
|
|
4222
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"
|
|
4223
|
-
}
|
|
4224
|
-
</td>
|
|
4225
|
-
<td>
|
|
4226
|
-
@if (rowData.pending) {
|
|
4227
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
4228
|
-
}
|
|
4229
|
-
</td>
|
|
4230
|
-
<td>
|
|
4231
|
-
<p-button
|
|
4232
|
-
icon="pi pi-bolt"
|
|
4233
|
-
pCancelEditableRow
|
|
4234
|
-
pTooltip="{{ 'db-migration.actions.applyMigration' | translate }}"
|
|
4235
|
-
severity="secondary"
|
|
4236
|
-
tooltipPosition="left"
|
|
4237
|
-
[rounded]="true"
|
|
4238
|
-
[text]="true"
|
|
4239
|
-
(click)="applyMigration(rowData)">
|
|
4240
|
-
</p-button>
|
|
4241
|
-
</td>
|
|
4242
|
-
</tr>
|
|
4243
|
-
</ng-template>
|
|
4244
|
-
</p-table>
|
|
4245
|
-
</div>
|
|
4246
|
-
</div>
|
|
4247
|
-
</div>
|
|
4248
|
-
} @else if (isSecurity) {
|
|
4249
|
-
<security [controller]="controller" [id]="id"
|
|
4250
|
-
}
|
|
4377
|
+
template: `
|
|
4378
|
+
@if (isContent) {
|
|
4379
|
+
<div class="card" style="height: 100%">
|
|
4380
|
+
<p-confirmDialog/>
|
|
4381
|
+
<div>
|
|
4382
|
+
<h5>{{ 'db-migration.migrationManager' | translate }}</h5>
|
|
4383
|
+
<div class="flex flex-row gap-2">
|
|
4384
|
+
<p-button
|
|
4385
|
+
icon="pi pi-refresh"
|
|
4386
|
+
severity="secondary"
|
|
4387
|
+
tooltipPosition="bottom"
|
|
4388
|
+
[outlined]="true"
|
|
4389
|
+
[pTooltip]="'db-migration.actions.refresh' | translate"
|
|
4390
|
+
(click)="refreshAction()"/>
|
|
4391
|
+
<p-button
|
|
4392
|
+
icon="pi pi-filter-slash"
|
|
4393
|
+
severity="secondary"
|
|
4394
|
+
tooltipPosition="bottom"
|
|
4395
|
+
[outlined]="true"
|
|
4396
|
+
[pTooltip]="'db-migration.actions.cleanFilter' | translate"
|
|
4397
|
+
(click)="dt.clear()"/>
|
|
4398
|
+
</div>
|
|
4399
|
+
<div>
|
|
4400
|
+
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
4401
|
+
<ng-template let-columns pTemplate="header">
|
|
4402
|
+
<tr>
|
|
4403
|
+
<th pSortableColumn="name" scope="col">
|
|
4404
|
+
{{ 'db-migration.columns.name' | translate }}
|
|
4405
|
+
<p-columnFilter display="menu" field="name" type="text"/>
|
|
4406
|
+
</th>
|
|
4407
|
+
<th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
|
|
4408
|
+
<th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
|
|
4409
|
+
<th scope="col">{{ 'db-migration.columns.pending' | translate }}</th>
|
|
4410
|
+
<th scope="col"></th>
|
|
4411
|
+
</tr>
|
|
4412
|
+
</ng-template>
|
|
4413
|
+
|
|
4414
|
+
<ng-template #body let-columns="columns" let-editing="editing" let-ri="rowIndex" let-rowData>
|
|
4415
|
+
<tr [pEditableRow]="rowData">
|
|
4416
|
+
<td>
|
|
4417
|
+
{{ rowData.name }}
|
|
4418
|
+
</td>
|
|
4419
|
+
<td>
|
|
4420
|
+
@if (rowData.applied) {
|
|
4421
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
4422
|
+
}
|
|
4423
|
+
</td>
|
|
4424
|
+
<td>
|
|
4425
|
+
@if (rowData.exist) {
|
|
4426
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"/>
|
|
4427
|
+
}
|
|
4428
|
+
</td>
|
|
4429
|
+
<td>
|
|
4430
|
+
@if (rowData.pending) {
|
|
4431
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"></p-button>
|
|
4432
|
+
}
|
|
4433
|
+
</td>
|
|
4434
|
+
<td>
|
|
4435
|
+
<p-button
|
|
4436
|
+
icon="pi pi-bolt"
|
|
4437
|
+
pCancelEditableRow
|
|
4438
|
+
pTooltip="{{ 'db-migration.actions.applyMigration' | translate }}"
|
|
4439
|
+
severity="secondary"
|
|
4440
|
+
tooltipPosition="left"
|
|
4441
|
+
[rounded]="true"
|
|
4442
|
+
[text]="true"
|
|
4443
|
+
(click)="applyMigration(rowData)">
|
|
4444
|
+
</p-button>
|
|
4445
|
+
</td>
|
|
4446
|
+
</tr>
|
|
4447
|
+
</ng-template>
|
|
4448
|
+
</p-table>
|
|
4449
|
+
</div>
|
|
4450
|
+
</div>
|
|
4451
|
+
</div>
|
|
4452
|
+
} @else if (isSecurity) {
|
|
4453
|
+
<security [controller]="controller" [id]="id"/>
|
|
4454
|
+
}
|
|
4251
4455
|
`,
|
|
4252
4456
|
providers: [ConfirmationService]
|
|
4253
4457
|
}]
|
|
@@ -6060,6 +6264,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
6060
6264
|
type: Injectable
|
|
6061
6265
|
}] });
|
|
6062
6266
|
|
|
6267
|
+
function provideAppThemes(themes, options) {
|
|
6268
|
+
const mode = options?.mode ?? 'mergeWithDefaults';
|
|
6269
|
+
return makeEnvironmentProviders([
|
|
6270
|
+
{ provide: APP_THEME_PRESETS, useValue: themes },
|
|
6271
|
+
{ provide: APP_THEME_PRESETS_MERGE_MODE, useValue: mode }
|
|
6272
|
+
]);
|
|
6273
|
+
}
|
|
6274
|
+
function mergeWithDefaults(themes) {
|
|
6275
|
+
return provideAppThemes(themes, { mode: 'mergeWithDefaults' });
|
|
6276
|
+
}
|
|
6277
|
+
function replaceDefaults(themes) {
|
|
6278
|
+
return provideAppThemes(themes, { mode: 'replaceDefaults' });
|
|
6279
|
+
}
|
|
6280
|
+
|
|
6063
6281
|
const langIntercept = (req, next) => {
|
|
6064
6282
|
const layoutService = inject(LayoutService);
|
|
6065
6283
|
const lang = layoutService.language() ? layoutService.language() : 'en';
|
|
@@ -6132,5 +6350,5 @@ const httpLoaderAuthFactory = (httpClient) => {
|
|
|
6132
6350
|
* Generated bundle index. Do not edit.
|
|
6133
6351
|
*/
|
|
6134
6352
|
|
|
6135
|
-
export { AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService, BaseDataService, BaseModuleComponent, ConfigComponent, ContentType, DEFAULT_OIP_FRONTEND_CONFIG, DbMigrationComponent, DiscussionComponent, ErrorComponent, FooterComponent, HttpClient, KeycloakSecurityService, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, MsgService, NotfoundComponent, NotificationService, OIP_FRONTEND_CONFIG, ProfileComponent, SecurePipe, SecurityComponent, SecurityDataService, SecurityService, SecurityStorageService, SidebarComponent, TableFilterService, TopBarService, UnauthorizedComponent, UserService, httpLoaderAuthFactory, langIntercept, provideLogoComponent };
|
|
6353
|
+
export { APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AuthGuardService, BaseDataService, BaseModuleComponent, ConfigComponent, ContentType, DEFAULT_OIP_FRONTEND_CONFIG, DbMigrationComponent, DiscussionComponent, ErrorComponent, FooterComponent, HttpClient, KeycloakSecurityService, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, MsgService, NotfoundComponent, NotificationService, OIP_FRONTEND_CONFIG, ProfileComponent, SecurePipe, SecurityComponent, SecurityDataService, SecurityService, SecurityStorageService, SidebarComponent, TableFilterService, TopBarService, UnauthorizedComponent, UserService, httpLoaderAuthFactory, langIntercept, mergeWithDefaults, provideAppThemes, provideLogoComponent, replaceDefaults };
|
|
6136
6354
|
//# sourceMappingURL=oip-common.mjs.map
|