oip-common 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/i18n/app-modules.en.json +8 -1
- package/assets/i18n/app-modules.ru.json +8 -1
- package/assets/i18n/en.json +2 -1
- package/assets/i18n/extensions.en.json +1 -0
- package/assets/i18n/extensions.ru.json +1 -0
- package/assets/i18n/ru.json +2 -1
- package/fesm2022/oip-common.mjs +1337 -515
- package/fesm2022/oip-common.mjs.map +1 -1
- package/index.d.ts +241 -61
- package/package.json +2 -2
- package/scripts/generate-api.mjs +4 -4
- package/templates/http-client.ejs +14 -1
package/fesm2022/oip-common.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
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';
|
|
2
|
+
import { Injectable, inject, signal, computed, effect, DestroyRef, ChangeDetectorRef, Component, Input, InjectionToken, PLATFORM_ID, ViewChild, HostBinding, EventEmitter, Output, Renderer2, SecurityContext, ChangeDetectionStrategy, Injector, EnvironmentInjector, ViewContainerRef, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
+
import { Subject, BehaviorSubject, of, tap, shareReplay, ReplaySubject, firstValueFrom, from, filter as filter$1 } from 'rxjs';
|
|
4
5
|
import * as i2$2 from 'primeng/api';
|
|
5
6
|
import { MessageService, ConfirmationService, PrimeIcons, SharedModule } from 'primeng/api';
|
|
6
7
|
import { HttpErrorResponse, HttpClient as HttpClient$1, provideHttpClient, withInterceptors, withFetch } from '@angular/common/http';
|
|
@@ -8,7 +9,6 @@ import * as i2$3 from '@ngx-translate/core';
|
|
|
8
9
|
import { TranslateService, TranslatePipe, TranslateModule, TranslateLoader } from '@ngx-translate/core';
|
|
9
10
|
import * as i1$5 from '@angular/router';
|
|
10
11
|
import { ActivatedRoute, Router, RouterModule, NavigationEnd, RouterLinkActive, RouterLink } from '@angular/router';
|
|
11
|
-
import { BehaviorSubject, Subject, of, tap, shareReplay, ReplaySubject, firstValueFrom, from, filter as filter$1 } from 'rxjs';
|
|
12
12
|
import { tap as tap$1, catchError, filter, distinctUntilChanged, switchMap, map, take } from 'rxjs/operators';
|
|
13
13
|
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
14
14
|
import { PrimeNG } from 'primeng/config';
|
|
@@ -24,7 +24,7 @@ import * as i1$3 from '@angular/common';
|
|
|
24
24
|
import { isPlatformBrowser, CommonModule, NgComponentOutlet, NgClass, DatePipe, PathLocationStrategy, LocationStrategy } from '@angular/common';
|
|
25
25
|
import * as i3$3 from 'primeng/styleclass';
|
|
26
26
|
import { StyleClassModule } from 'primeng/styleclass';
|
|
27
|
-
import { updatePreset, updateSurfacePalette, $t } from '@primeng/themes';
|
|
27
|
+
import { updatePreset, updateSurfacePalette, $t, definePreset } from '@primeng/themes';
|
|
28
28
|
import Aura from '@primeng/themes/aura';
|
|
29
29
|
import Lara from '@primeng/themes/lara';
|
|
30
30
|
import Nora from '@primeng/themes/nora';
|
|
@@ -65,13 +65,15 @@ import { TableModule } from 'primeng/table';
|
|
|
65
65
|
import * as i2$4 from 'primeng/toggleswitch';
|
|
66
66
|
import { ToggleSwitchModule } from 'primeng/toggleswitch';
|
|
67
67
|
import { TextareaModule, Textarea } from 'primeng/textarea';
|
|
68
|
-
import * as
|
|
68
|
+
import * as i5$1 from 'primeng/toolbar';
|
|
69
69
|
import { ToolbarModule } from 'primeng/toolbar';
|
|
70
|
-
import * as i5$
|
|
70
|
+
import * as i5$2 from 'primeng/card';
|
|
71
71
|
import { CardModule } from 'primeng/card';
|
|
72
72
|
import { DividerModule } from 'primeng/divider';
|
|
73
73
|
import * as i6 from 'primeng/panel';
|
|
74
74
|
import { PanelModule } from 'primeng/panel';
|
|
75
|
+
import { loadRemoteModule } from '@angular-architects/module-federation';
|
|
76
|
+
import { primitive } from '@primeng/themes/aura/base';
|
|
75
77
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
|
76
78
|
|
|
77
79
|
class TopBarService {
|
|
@@ -89,22 +91,24 @@ class TopBarService {
|
|
|
89
91
|
}
|
|
90
92
|
set activeId(value) {
|
|
91
93
|
this._activeId = value;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
const activeTopBarItem = this.activeTopBarItem;
|
|
95
|
+
if (activeTopBarItem?.click)
|
|
96
|
+
activeTopBarItem.click();
|
|
97
|
+
this.activeIdSubject.next(value);
|
|
94
98
|
}
|
|
95
99
|
constructor() {
|
|
96
100
|
this.topBarItems = [];
|
|
101
|
+
this.activeIdSubject = new Subject();
|
|
102
|
+
this.activeId$ = this.activeIdSubject.asObservable();
|
|
97
103
|
}
|
|
98
104
|
// Set tob bar items
|
|
99
105
|
setTopBarItems(items) {
|
|
100
106
|
this.topBarItems = items;
|
|
101
107
|
}
|
|
102
108
|
checkId(id) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return false;
|
|
107
|
-
return this.activeTopBarItem.id == id;
|
|
109
|
+
const activeTopBarItem = this.activeTopBarItem;
|
|
110
|
+
const result = activeTopBarItem === undefined ? id === 'content' : activeTopBarItem.id == id;
|
|
111
|
+
return result;
|
|
108
112
|
}
|
|
109
113
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: TopBarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
110
114
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: TopBarService, providedIn: 'root' }); }
|
|
@@ -150,18 +154,17 @@ class MsgService {
|
|
|
150
154
|
});
|
|
151
155
|
}
|
|
152
156
|
error(detail, summary = this.translate.instant('msgService.error'), life = this.lifetime) {
|
|
153
|
-
|
|
154
|
-
if (validationMessage) {
|
|
155
|
-
detail = validationMessage;
|
|
156
|
-
}
|
|
157
|
-
else if (detail instanceof HttpErrorResponse) {
|
|
157
|
+
if (detail instanceof HttpErrorResponse) {
|
|
158
158
|
summary = `Error: ${detail.status} ${detail.statusText}`;
|
|
159
|
-
detail = `${detail.name} \r\n ${detail.message}
|
|
159
|
+
detail = this.extractErrorMessage(detail, `${detail.name} \r\n ${detail.message}`);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
detail = this.extractErrorMessage(detail, detail?.toString?.() ?? this.translate.instant('msgService.error'));
|
|
160
163
|
}
|
|
161
164
|
this.messageService.add({
|
|
162
165
|
severity: 'error',
|
|
163
166
|
summary: summary,
|
|
164
|
-
detail: detail
|
|
167
|
+
detail: detail,
|
|
165
168
|
life: life
|
|
166
169
|
});
|
|
167
170
|
}
|
|
@@ -170,14 +173,9 @@ class MsgService {
|
|
|
170
173
|
if (validationMessage) {
|
|
171
174
|
return validationMessage;
|
|
172
175
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
typeof error.error === 'object' &&
|
|
177
|
-
error.error &&
|
|
178
|
-
'message' in error.error &&
|
|
179
|
-
typeof error.error.message === 'string') {
|
|
180
|
-
return error.error.message;
|
|
176
|
+
const apiExceptionMessage = this.extractApiExceptionMessage(error);
|
|
177
|
+
if (apiExceptionMessage) {
|
|
178
|
+
return apiExceptionMessage;
|
|
181
179
|
}
|
|
182
180
|
if (typeof error === 'object' && error && 'message' in error && typeof error.message === 'string') {
|
|
183
181
|
return error.message;
|
|
@@ -195,6 +193,15 @@ class MsgService {
|
|
|
195
193
|
.filter((message) => message.length > 0);
|
|
196
194
|
return messages.length > 0 ? messages.join('\n') : null;
|
|
197
195
|
}
|
|
196
|
+
extractApiExceptionMessage(error) {
|
|
197
|
+
const responseError = this.getObjectProperty(error, 'error');
|
|
198
|
+
const message = this.getStringProperty(responseError, 'message') ?? this.getStringProperty(error, 'message');
|
|
199
|
+
const title = this.getStringProperty(responseError, 'title') ?? this.getStringProperty(error, 'title');
|
|
200
|
+
if (message && title) {
|
|
201
|
+
return `${title}: ${message}`;
|
|
202
|
+
}
|
|
203
|
+
return message ?? title;
|
|
204
|
+
}
|
|
198
205
|
toValidationMessages(field, value) {
|
|
199
206
|
if (Array.isArray(value)) {
|
|
200
207
|
return value
|
|
@@ -213,6 +220,13 @@ class MsgService {
|
|
|
213
220
|
const value = source[property];
|
|
214
221
|
return typeof value === 'object' && value !== null ? value : null;
|
|
215
222
|
}
|
|
223
|
+
getStringProperty(source, property) {
|
|
224
|
+
if (typeof source !== 'object' || source === null || !(property in source)) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const value = source[property];
|
|
228
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
229
|
+
}
|
|
216
230
|
errorFromException(error, fallback, summary = fallback, life = this.lifetime) {
|
|
217
231
|
this.error(this.extractErrorMessage(error, fallback), summary, life);
|
|
218
232
|
}
|
|
@@ -399,6 +413,7 @@ class LayoutService {
|
|
|
399
413
|
return ngDateFormat;
|
|
400
414
|
}, ...(ngDevMode ? [{ debugName: "monthFormat" }] : []));
|
|
401
415
|
this.timeZone = computed(() => this.layoutConfig().timeZone, ...(ngDevMode ? [{ debugName: "timeZone" }] : []));
|
|
416
|
+
this.adminMode = computed(() => this.layoutConfig().adminMode ?? false, ...(ngDevMode ? [{ debugName: "adminMode" }] : []));
|
|
402
417
|
this.transitionComplete = signal(false, ...(ngDevMode ? [{ debugName: "transitionComplete" }] : []));
|
|
403
418
|
this.initialized = false;
|
|
404
419
|
effect(() => {
|
|
@@ -437,7 +452,8 @@ class LayoutService {
|
|
|
437
452
|
dateFormat: 'yyyy-MM-dd',
|
|
438
453
|
timeFormat: 'HH:mm:ss',
|
|
439
454
|
dateTimeFormat: 'yyyy-MM-dd HH:mm:ss',
|
|
440
|
-
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
455
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
456
|
+
adminMode: false
|
|
441
457
|
};
|
|
442
458
|
}
|
|
443
459
|
handleDarkModeTransition(config) {
|
|
@@ -542,6 +558,36 @@ class L10nService {
|
|
|
542
558
|
const lang = this.translateService.currentLang || this.layoutService.language() || 'en';
|
|
543
559
|
return this.loadTranslations(component, lang);
|
|
544
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* Loads translations from an explicit asset URL and merges them into the active language dictionary.
|
|
563
|
+
* Use this for extension modules whose assets are hosted outside the shell application.
|
|
564
|
+
*/
|
|
565
|
+
loadTranslationsFromUrl(namespace, url, lang) {
|
|
566
|
+
const selectedLang = lang || this.translateService.currentLang || this.layoutService.language() || 'en';
|
|
567
|
+
const key = `${namespace}.${selectedLang}.${url}`;
|
|
568
|
+
if (this.loadedTranslations.has(key)) {
|
|
569
|
+
return of(null);
|
|
570
|
+
}
|
|
571
|
+
const loading = this.loadingTranslations.get(key);
|
|
572
|
+
if (loading) {
|
|
573
|
+
return loading;
|
|
574
|
+
}
|
|
575
|
+
const request = this.httpClient.get(url).pipe(tap((translations) => {
|
|
576
|
+
const current = this.translateService.translations[selectedLang] || {};
|
|
577
|
+
this.translateService.setTranslation(selectedLang, { ...current, ...translations }, true);
|
|
578
|
+
this.loadedTranslations.add(key);
|
|
579
|
+
this.loadingTranslations.delete(key);
|
|
580
|
+
}), shareReplay(1));
|
|
581
|
+
this.loadingTranslations.set(key, request);
|
|
582
|
+
request.subscribe({
|
|
583
|
+
error: (e) => {
|
|
584
|
+
this.loadingTranslations.delete(key);
|
|
585
|
+
console.error(`No translations found for ${namespace}.${selectedLang}.json at ${url}`);
|
|
586
|
+
console.error(e);
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
return request;
|
|
590
|
+
}
|
|
545
591
|
/**
|
|
546
592
|
* Gets the translated value of a key (or an array of keys)
|
|
547
593
|
* @returns the translated key, or an object of translated keys
|
|
@@ -620,16 +666,21 @@ class BffSecurityService {
|
|
|
620
666
|
this.csrfToken = new ReplaySubject(1);
|
|
621
667
|
this.payload = new BehaviorSubject(null);
|
|
622
668
|
}
|
|
669
|
+
static { this.authorizeAfterLogoutReturnUrlKey = 'oip.authorizeAfterLogoutReturnUrl'; }
|
|
623
670
|
auth() {
|
|
624
|
-
this.http
|
|
671
|
+
this.http
|
|
672
|
+
.get(this.buildUrl('api/security/get-current-auth-session'), {
|
|
625
673
|
withCredentials: true
|
|
626
|
-
})
|
|
674
|
+
})
|
|
675
|
+
.pipe(tap$1((session) => this.applySession(session)), catchError(() => {
|
|
627
676
|
this.applyAnonymousSession();
|
|
628
677
|
return of(null);
|
|
629
|
-
}))
|
|
678
|
+
}))
|
|
679
|
+
.subscribe();
|
|
630
680
|
}
|
|
631
681
|
logout() {
|
|
632
682
|
firstValueFrom(this.getCsrfToken()).then((csrfToken) => {
|
|
683
|
+
this.storeAuthorizeAfterLogoutReturnUrl();
|
|
633
684
|
const form = this.createPostForm(this.buildUrl('api/security/delete-auth-session'));
|
|
634
685
|
if (csrfToken?.token) {
|
|
635
686
|
const tokenInput = document.createElement('input');
|
|
@@ -665,15 +716,20 @@ class BffSecurityService {
|
|
|
665
716
|
});
|
|
666
717
|
}
|
|
667
718
|
getCsrfToken() {
|
|
668
|
-
this.http
|
|
719
|
+
this.http
|
|
720
|
+
.get(this.buildUrl('api/security/get-auth-csrf-token'), {
|
|
669
721
|
withCredentials: true
|
|
670
|
-
})
|
|
722
|
+
})
|
|
723
|
+
.pipe(catchError(() => of(null)))
|
|
724
|
+
.subscribe((token) => this.csrfToken.next(token));
|
|
671
725
|
return this.csrfToken.asObservable();
|
|
672
726
|
}
|
|
673
727
|
isAdmin() {
|
|
674
728
|
return this.payload.getValue()?.realm_access?.roles?.includes('admin') ?? false;
|
|
675
729
|
}
|
|
676
|
-
authorize() {
|
|
730
|
+
authorize(returnUrl) {
|
|
731
|
+
const normalizedReturnUrl = this.normalizeReturnUrl(returnUrl);
|
|
732
|
+
this.replaceWithUnauthorizedUrl(normalizedReturnUrl);
|
|
677
733
|
const form = this.createPostForm(this.buildUrl('api/security/create-auth-session'));
|
|
678
734
|
document.body.appendChild(form);
|
|
679
735
|
form.submit();
|
|
@@ -724,10 +780,40 @@ class BffSecurityService {
|
|
|
724
780
|
form.style.display = 'none';
|
|
725
781
|
return form;
|
|
726
782
|
}
|
|
783
|
+
normalizeReturnUrl(returnUrl) {
|
|
784
|
+
const candidate = returnUrl?.trim();
|
|
785
|
+
if (!candidate || /[\u0000-\u001f\u007f\\]/.test(candidate)) {
|
|
786
|
+
return '/';
|
|
787
|
+
}
|
|
788
|
+
if (!candidate.startsWith('/') || candidate.startsWith('//')) {
|
|
789
|
+
return '/';
|
|
790
|
+
}
|
|
791
|
+
try {
|
|
792
|
+
const url = new URL(candidate, window.location.origin);
|
|
793
|
+
if (url.origin !== window.location.origin) {
|
|
794
|
+
return '/';
|
|
795
|
+
}
|
|
796
|
+
const normalizedUrl = `${url.pathname}${url.search}${url.hash}`;
|
|
797
|
+
return normalizedUrl.startsWith('/unauthorized') ? '/' : normalizedUrl;
|
|
798
|
+
}
|
|
799
|
+
catch {
|
|
800
|
+
return '/';
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
replaceWithUnauthorizedUrl(returnUrl) {
|
|
804
|
+
const unauthorizedUrl = new URL('unauthorized', this.getBaseUrl());
|
|
805
|
+
unauthorizedUrl.searchParams.set('returnUrl', returnUrl);
|
|
806
|
+
history.replaceState(history.state, '', `${unauthorizedUrl.pathname}${unauthorizedUrl.search}`);
|
|
807
|
+
}
|
|
808
|
+
storeAuthorizeAfterLogoutReturnUrl() {
|
|
809
|
+
sessionStorage.setItem(BffSecurityService.authorizeAfterLogoutReturnUrlKey, this.normalizeReturnUrl(`${window.location.pathname}${window.location.search}${window.location.hash}`));
|
|
810
|
+
}
|
|
727
811
|
buildUrl(path) {
|
|
812
|
+
return `${this.getBaseUrl()}${path}`;
|
|
813
|
+
}
|
|
814
|
+
getBaseUrl() {
|
|
728
815
|
const baseUrl = document.getElementsByTagName('base')[0].href;
|
|
729
|
-
|
|
730
|
-
return `${normalizedBase}${path}`;
|
|
816
|
+
return baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;
|
|
731
817
|
}
|
|
732
818
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: BffSecurityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
733
819
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: BffSecurityService }); }
|
|
@@ -1171,13 +1257,11 @@ class BaseModuleComponent {
|
|
|
1171
1257
|
* Called whenever the module instance changes, including the first load.
|
|
1172
1258
|
* Derived components can override this to refresh module-specific data.
|
|
1173
1259
|
*/
|
|
1174
|
-
async onModuleInstanceChange() {
|
|
1175
|
-
}
|
|
1260
|
+
async onModuleInstanceChange() { }
|
|
1176
1261
|
/**
|
|
1177
1262
|
* Called whenever current user rights for the active module instance are recalculated.
|
|
1178
1263
|
*/
|
|
1179
|
-
onSecurityRightsChange() {
|
|
1180
|
-
}
|
|
1264
|
+
onSecurityRightsChange() { }
|
|
1181
1265
|
/**
|
|
1182
1266
|
* Starts watching current token roles and maps them to module instance security settings.
|
|
1183
1267
|
*/
|
|
@@ -1219,9 +1303,7 @@ class BaseModuleComponent {
|
|
|
1219
1303
|
this.onSecurityRightsChange();
|
|
1220
1304
|
}
|
|
1221
1305
|
hasSecurityRight(roles, securitySettings, code) {
|
|
1222
|
-
return securitySettings
|
|
1223
|
-
.find((security) => security.code === code)
|
|
1224
|
-
?.roles?.some((role) => roles.includes(role)) ?? false;
|
|
1306
|
+
return (securitySettings.find((security) => security.code === code)?.roles?.some((role) => roles.includes(role)) ?? false);
|
|
1225
1307
|
}
|
|
1226
1308
|
getSecurity(controller = this.controller, id = this.id) {
|
|
1227
1309
|
if (!controller || id == null) {
|
|
@@ -1548,8 +1630,7 @@ class AppConfiguratorComponent {
|
|
|
1548
1630
|
this.themePresets = this.getThemePresets();
|
|
1549
1631
|
this.themePresetsMap = new Map(this.themePresets.map((theme) => [theme.id, theme]));
|
|
1550
1632
|
this.defaultThemePreset = this.themePresets[0] ?? DEFAULT_THEME_PRESETS[0];
|
|
1551
|
-
this.fallbackPrimaryColors = (DEFAULT_THEME_PRESETS[0].preset
|
|
1552
|
-
.primitive ?? {});
|
|
1633
|
+
this.fallbackPrimaryColors = (DEFAULT_THEME_PRESETS[0].preset.primitive ?? {});
|
|
1553
1634
|
this.presets = this.themePresets.map((theme) => ({ label: theme.label ?? theme.id, value: theme.id }));
|
|
1554
1635
|
this.showMenuModeButton = signal(!this.router.url.includes('auth'), ...(ngDevMode ? [{ debugName: "showMenuModeButton" }] : []));
|
|
1555
1636
|
this.menuModeOptions = [
|
|
@@ -1868,7 +1949,7 @@ class AppConfiguratorComponent {
|
|
|
1868
1949
|
.filter((entry) => Boolean(entry[1]))
|
|
1869
1950
|
.map(([name, palette]) => ({ name, palette }));
|
|
1870
1951
|
}
|
|
1871
|
-
const presetPalette =
|
|
1952
|
+
const presetPalette = activeThemePreset.preset.primitive ?? {};
|
|
1872
1953
|
const palettes = [{ name: 'noir', palette: {} }];
|
|
1873
1954
|
PRIMARY_COLORS.forEach((color) => {
|
|
1874
1955
|
palettes.push({
|
|
@@ -1927,7 +2008,9 @@ class AppConfiguratorComponent {
|
|
|
1927
2008
|
this.layoutService.layoutConfig.update((state) => ({
|
|
1928
2009
|
...state,
|
|
1929
2010
|
preset: nextThemeId,
|
|
1930
|
-
primary: primaryColors.some((color) => color.name === state.primary)
|
|
2011
|
+
primary: primaryColors.some((color) => color.name === state.primary)
|
|
2012
|
+
? state.primary
|
|
2013
|
+
: (primaryColors[0]?.name ?? state.primary),
|
|
1931
2014
|
surface: nextTheme.surfaceColors && !surfaceColors.some((color) => color.name === state.surface)
|
|
1932
2015
|
? (surfaceColors[0]?.name ?? state.surface)
|
|
1933
2016
|
: state.surface
|
|
@@ -1991,12 +2074,12 @@ class AppConfiguratorComponent {
|
|
|
1991
2074
|
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
|
|
1992
2075
|
<p-selectButton
|
|
1993
2076
|
id="oip-app-configurator-preset-select-button"
|
|
2077
|
+
optionLabel="label"
|
|
2078
|
+
optionValue="value"
|
|
1994
2079
|
size="small"
|
|
1995
2080
|
[allowEmpty]="false"
|
|
1996
2081
|
[ngModel]="selectedPreset()"
|
|
1997
2082
|
[options]="presets"
|
|
1998
|
-
optionLabel="label"
|
|
1999
|
-
optionValue="value"
|
|
2000
2083
|
(ngModelChange)="onPresetChange($event)" />
|
|
2001
2084
|
</div>
|
|
2002
2085
|
@if (showMenuModeButton()) {
|
|
@@ -2068,12 +2151,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
2068
2151
|
<span class="text-sm text-muted-color font-semibold">{{ 'app-configurator.presets' | translate }}</span>
|
|
2069
2152
|
<p-selectButton
|
|
2070
2153
|
id="oip-app-configurator-preset-select-button"
|
|
2154
|
+
optionLabel="label"
|
|
2155
|
+
optionValue="value"
|
|
2071
2156
|
size="small"
|
|
2072
2157
|
[allowEmpty]="false"
|
|
2073
2158
|
[ngModel]="selectedPreset()"
|
|
2074
2159
|
[options]="presets"
|
|
2075
|
-
optionLabel="label"
|
|
2076
|
-
optionValue="value"
|
|
2077
2160
|
(ngModelChange)="onPresetChange($event)" />
|
|
2078
2161
|
</div>
|
|
2079
2162
|
@if (showMenuModeButton()) {
|
|
@@ -2102,10 +2185,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
2102
2185
|
class UserProfileApi extends HttpClient {
|
|
2103
2186
|
constructor() {
|
|
2104
2187
|
super(...arguments);
|
|
2105
|
-
this.getUserPhoto = (
|
|
2188
|
+
this.getUserPhoto = (params = {}) => this.request({
|
|
2106
2189
|
path: `/api/user-profile/get-user-photo`,
|
|
2107
2190
|
method: "GET",
|
|
2108
|
-
|
|
2191
|
+
secure: true,
|
|
2192
|
+
format: "blob",
|
|
2193
|
+
...params,
|
|
2194
|
+
});
|
|
2195
|
+
this.getUserPhotoById = ({ userId, ...query }, params = {}) => this.request({
|
|
2196
|
+
path: `/api/user-profile/get-user-photo-by-id/${userId}`,
|
|
2197
|
+
method: "GET",
|
|
2109
2198
|
secure: true,
|
|
2110
2199
|
format: "blob",
|
|
2111
2200
|
...params,
|
|
@@ -2149,7 +2238,9 @@ class UserService {
|
|
|
2149
2238
|
constructor() {
|
|
2150
2239
|
this.securityService = inject(SecurityService);
|
|
2151
2240
|
this.userProfileApi = inject(UserProfileApi);
|
|
2152
|
-
this.
|
|
2241
|
+
this.msgService = inject(MsgService);
|
|
2242
|
+
this.translateService = inject(TranslateService);
|
|
2243
|
+
this.requestedPhotoKey = null;
|
|
2153
2244
|
/**
|
|
2154
2245
|
* Stores the user's photo as a data URL or binary blob, depending on how it's processed.
|
|
2155
2246
|
*/
|
|
@@ -2160,7 +2251,7 @@ class UserService {
|
|
|
2160
2251
|
this.photoLoaded = false;
|
|
2161
2252
|
this.securityService
|
|
2162
2253
|
.getCurrentUser$()
|
|
2163
|
-
.pipe(map((user) => user
|
|
2254
|
+
.pipe(map((user) => this.getCurrentUserPhotoKey(user)), filter((photoKey) => !!photoKey), distinctUntilChanged())
|
|
2164
2255
|
.subscribe(() => {
|
|
2165
2256
|
this.getUserPhoto();
|
|
2166
2257
|
});
|
|
@@ -2178,35 +2269,41 @@ class UserService {
|
|
|
2178
2269
|
}
|
|
2179
2270
|
get userName() {
|
|
2180
2271
|
const data = this.securityService.getCurrentUser();
|
|
2181
|
-
return [data?.given_name, data?.family_name].filter(Boolean).join(' ')
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2272
|
+
return ([data?.given_name, data?.family_name].filter(Boolean).join(' ') ||
|
|
2273
|
+
data?.displayName ||
|
|
2274
|
+
data?.name ||
|
|
2275
|
+
data?.userName ||
|
|
2276
|
+
data?.preferred_username ||
|
|
2277
|
+
data?.email ||
|
|
2278
|
+
'');
|
|
2188
2279
|
}
|
|
2189
2280
|
/**
|
|
2190
|
-
* Initiates an HTTP request to fetch the user's photo
|
|
2281
|
+
* Initiates an HTTP request to fetch the current user's photo,
|
|
2191
2282
|
* and updates the `photo` and `photoLoaded` properties accordingly.
|
|
2192
2283
|
*/
|
|
2193
2284
|
getUserPhoto() {
|
|
2194
|
-
const
|
|
2195
|
-
if (!
|
|
2285
|
+
const photoKey = this.getCurrentUserPhotoKey(this.securityService.getCurrentUser());
|
|
2286
|
+
if (!photoKey) {
|
|
2196
2287
|
return;
|
|
2197
2288
|
}
|
|
2198
|
-
if (this.
|
|
2289
|
+
if (this.requestedPhotoKey === photoKey && (this.photoLoaded || this.photo)) {
|
|
2199
2290
|
return;
|
|
2200
2291
|
}
|
|
2201
|
-
this.
|
|
2202
|
-
this.userProfileApi.getUserPhoto({
|
|
2292
|
+
this.requestedPhotoKey = photoKey;
|
|
2293
|
+
this.userProfileApi.getUserPhoto({ format: 'blob' }).then((data) => {
|
|
2203
2294
|
this.createImageFromBlob(data);
|
|
2204
2295
|
this.photoLoaded = true;
|
|
2205
2296
|
}, (error) => {
|
|
2206
|
-
|
|
2297
|
+
this.msgService.errorFromException(error, this.translateService.instant('profileComponent.failedToLoadPhoto'));
|
|
2207
2298
|
this.photoLoaded = false;
|
|
2208
2299
|
});
|
|
2209
2300
|
}
|
|
2301
|
+
refreshUserPhoto() {
|
|
2302
|
+
this.requestedPhotoKey = null;
|
|
2303
|
+
this.photo = null;
|
|
2304
|
+
this.photoLoaded = false;
|
|
2305
|
+
this.getUserPhoto();
|
|
2306
|
+
}
|
|
2210
2307
|
/**
|
|
2211
2308
|
* Converts a Blob image into a Base64 data URL and stores it in the `photo` property.
|
|
2212
2309
|
*
|
|
@@ -2222,14 +2319,17 @@ class UserService {
|
|
|
2222
2319
|
}
|
|
2223
2320
|
}
|
|
2224
2321
|
getInitials(value) {
|
|
2225
|
-
return value
|
|
2322
|
+
return (value
|
|
2226
2323
|
?.trim()
|
|
2227
2324
|
.split(/\s+/)
|
|
2228
2325
|
.filter(Boolean)
|
|
2229
2326
|
.slice(0, 2)
|
|
2230
2327
|
.map((part) => part[0])
|
|
2231
2328
|
.join('')
|
|
2232
|
-
.toUpperCase() ?? '';
|
|
2329
|
+
.toUpperCase() ?? '');
|
|
2330
|
+
}
|
|
2331
|
+
getCurrentUserPhotoKey(user) {
|
|
2332
|
+
return user?.sub || user?.userName || user?.preferred_username || user?.displayName || user?.name || null;
|
|
2233
2333
|
}
|
|
2234
2334
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2235
2335
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: UserService }); }
|
|
@@ -2502,8 +2602,8 @@ class UserNotificationsComponent {
|
|
|
2502
2602
|
class="layout-topbar-action relative"
|
|
2503
2603
|
id="oip-app-topbar-notification-button"
|
|
2504
2604
|
type="button"
|
|
2505
|
-
|
|
2506
|
-
|
|
2605
|
+
[attr.aria-label]="'Notifications: ' + unreadNotificationCount()"
|
|
2606
|
+
(click)="toggle($event)">
|
|
2507
2607
|
<i class="pi pi-bell"></i>
|
|
2508
2608
|
@if (unreadNotificationCount() > 0) {
|
|
2509
2609
|
<p-badge
|
|
@@ -2579,8 +2679,8 @@ class UserNotificationsComponent {
|
|
|
2579
2679
|
styleClass="mt-3"
|
|
2580
2680
|
[first]="skip"
|
|
2581
2681
|
[rows]="take"
|
|
2582
|
-
[totalRecords]="totalCount"
|
|
2583
2682
|
[rowsPerPageOptions]="[5, 10, 20]"
|
|
2683
|
+
[totalRecords]="totalCount"
|
|
2584
2684
|
(onPageChange)="onPageChange($event)"></p-paginator>
|
|
2585
2685
|
}
|
|
2586
2686
|
</p-popover>
|
|
@@ -2591,14 +2691,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
2591
2691
|
args: [{
|
|
2592
2692
|
selector: 'app-user-notifications',
|
|
2593
2693
|
standalone: true,
|
|
2594
|
-
imports: [
|
|
2694
|
+
imports: [
|
|
2695
|
+
CommonModule,
|
|
2696
|
+
BadgeModule,
|
|
2697
|
+
ButtonModule,
|
|
2698
|
+
PaginatorModule,
|
|
2699
|
+
Popover,
|
|
2700
|
+
ProgressSpinnerModule,
|
|
2701
|
+
Tag,
|
|
2702
|
+
Tooltip,
|
|
2703
|
+
TranslatePipe
|
|
2704
|
+
],
|
|
2595
2705
|
template: `
|
|
2596
2706
|
<button
|
|
2597
2707
|
class="layout-topbar-action relative"
|
|
2598
2708
|
id="oip-app-topbar-notification-button"
|
|
2599
2709
|
type="button"
|
|
2600
|
-
|
|
2601
|
-
|
|
2710
|
+
[attr.aria-label]="'Notifications: ' + unreadNotificationCount()"
|
|
2711
|
+
(click)="toggle($event)">
|
|
2602
2712
|
<i class="pi pi-bell"></i>
|
|
2603
2713
|
@if (unreadNotificationCount() > 0) {
|
|
2604
2714
|
<p-badge
|
|
@@ -2674,8 +2784,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
2674
2784
|
styleClass="mt-3"
|
|
2675
2785
|
[first]="skip"
|
|
2676
2786
|
[rows]="take"
|
|
2677
|
-
[totalRecords]="totalCount"
|
|
2678
2787
|
[rowsPerPageOptions]="[5, 10, 20]"
|
|
2788
|
+
[totalRecords]="totalCount"
|
|
2679
2789
|
(onPageChange)="onPageChange($event)"></p-paginator>
|
|
2680
2790
|
}
|
|
2681
2791
|
</p-popover>
|
|
@@ -2839,6 +2949,10 @@ class AppTopbar {
|
|
|
2839
2949
|
this.confirmationService = inject(ConfirmationService);
|
|
2840
2950
|
this.translateService = inject(TranslateService);
|
|
2841
2951
|
}
|
|
2952
|
+
onActiveTabChange(value) {
|
|
2953
|
+
const nextActiveId = value == null ? undefined : String(value);
|
|
2954
|
+
this.topBarService.activeId = nextActiveId;
|
|
2955
|
+
}
|
|
2842
2956
|
toggleDarkMode() {
|
|
2843
2957
|
this.layoutService.layoutConfig.update((state) => ({
|
|
2844
2958
|
...state,
|
|
@@ -2871,106 +2985,108 @@ class AppTopbar {
|
|
|
2871
2985
|
});
|
|
2872
2986
|
}
|
|
2873
2987
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AppTopbar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2874
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: AppTopbar, isStandalone: true, selector: "app-topbar", providers: [ConfirmationService], ngImport: i0, template: `
|
|
2875
|
-
<
|
|
2876
|
-
|
|
2877
|
-
<
|
|
2878
|
-
<
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
<
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
</div>
|
|
2988
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: AppTopbar, isStandalone: true, selector: "app-topbar", providers: [ConfirmationService], ngImport: i0, template: ` <div class="layout-topbar">
|
|
2989
|
+
<p-confirmDialog appendTo="body" />
|
|
2990
|
+
<div class="layout-topbar-logo-container">
|
|
2991
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
2992
|
+
<i class="pi pi-bars"></i>
|
|
2993
|
+
</button>
|
|
2994
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
2995
|
+
<ng-container
|
|
2996
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
2997
|
+
<span>{{ 'app-info.title' | translate }}</span>
|
|
2998
|
+
</a>
|
|
2999
|
+
</div>
|
|
2887
3000
|
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
3001
|
+
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
3002
|
+
<p-tabs
|
|
3003
|
+
class="layout-topbar-tabs ml-2"
|
|
3004
|
+
[value]="topBarService.activeId"
|
|
3005
|
+
(valueChange)="onActiveTabChange($event)">
|
|
3006
|
+
<p-tablist>
|
|
3007
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
3008
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
3009
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
3010
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
3011
|
+
</p-tab>
|
|
3012
|
+
}
|
|
3013
|
+
</p-tablist>
|
|
3014
|
+
</p-tabs>
|
|
3015
|
+
}
|
|
3016
|
+
<div class="layout-topbar-actions">
|
|
3017
|
+
<div class="layout-config-menu">
|
|
3018
|
+
<app-topbar-application-switcher />
|
|
3019
|
+
<app-user-notifications />
|
|
3020
|
+
<p-button
|
|
3021
|
+
class="layout-topbar-action"
|
|
3022
|
+
id="oip-app-topbar-theme-button"
|
|
3023
|
+
severity="secondary"
|
|
3024
|
+
type="button"
|
|
3025
|
+
[rounded]="true"
|
|
3026
|
+
[text]="true"
|
|
3027
|
+
(click)="toggleDarkMode()">
|
|
3028
|
+
<i
|
|
3029
|
+
class="pi"
|
|
3030
|
+
[ngClass]="{
|
|
2915
3031
|
'pi-moon': layoutService.isDarkTheme(),
|
|
2916
3032
|
'pi-sun': !layoutService.isDarkTheme()
|
|
2917
3033
|
}"></i>
|
|
3034
|
+
</p-button>
|
|
3035
|
+
<div class="relative">
|
|
3036
|
+
<p-button
|
|
3037
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
3038
|
+
enterActiveClass="animate-scalein"
|
|
3039
|
+
enterFromClass="hidden"
|
|
3040
|
+
id="oip-app-topbar-palette-button"
|
|
3041
|
+
leaveActiveClass="animate-fadeout"
|
|
3042
|
+
leaveToClass="hidden"
|
|
3043
|
+
pStyleClass="@next"
|
|
3044
|
+
[hideOnOutsideClick]="true"
|
|
3045
|
+
[rounded]="true">
|
|
3046
|
+
<i class="pi pi-palette"></i>
|
|
2918
3047
|
</p-button>
|
|
2919
|
-
<
|
|
2920
|
-
<p-button
|
|
2921
|
-
class="layout-topbar-action layout-topbar-action-highlight"
|
|
2922
|
-
enterActiveClass="animate-scalein"
|
|
2923
|
-
enterFromClass="hidden"
|
|
2924
|
-
id="oip-app-topbar-palette-button"
|
|
2925
|
-
leaveActiveClass="animate-fadeout"
|
|
2926
|
-
leaveToClass="hidden"
|
|
2927
|
-
pStyleClass="@next"
|
|
2928
|
-
[hideOnOutsideClick]="true"
|
|
2929
|
-
[rounded]="true">
|
|
2930
|
-
<i class="pi pi-palette"></i>
|
|
2931
|
-
</p-button>
|
|
2932
|
-
<app-configurator/>
|
|
2933
|
-
</div>
|
|
3048
|
+
<app-configurator />
|
|
2934
3049
|
</div>
|
|
3050
|
+
</div>
|
|
2935
3051
|
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
3052
|
+
<button
|
|
3053
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
3054
|
+
enterActiveClass="animate-scalein"
|
|
3055
|
+
enterFromClass="hidden"
|
|
3056
|
+
id="oip-app-topbar-menu-expand-button"
|
|
3057
|
+
leaveActiveClass="animate-fadeout"
|
|
3058
|
+
leaveToClass="hidden"
|
|
3059
|
+
pStyleClass="@next"
|
|
3060
|
+
[hideOnOutsideClick]="true">
|
|
3061
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
3062
|
+
</button>
|
|
2947
3063
|
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
3064
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
3065
|
+
<div class="layout-topbar-menu-content">
|
|
3066
|
+
<button
|
|
3067
|
+
class="layout-topbar-action"
|
|
3068
|
+
id="oip-app-topbar-logout-button"
|
|
3069
|
+
type="button"
|
|
3070
|
+
(click)="confirmLogout()"
|
|
3071
|
+
(keydown)="logoutKeyDown($event)">
|
|
3072
|
+
<i class="pi pi-sign-out"></i>
|
|
3073
|
+
<span>{{ 'topbar.logout' | translate }}</span>
|
|
3074
|
+
</button>
|
|
3075
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
3076
|
+
<p-avatar
|
|
3077
|
+
class="p-link flex align-items-center"
|
|
3078
|
+
id="oip-app-topbar-user-avatar"
|
|
3079
|
+
shape="circle"
|
|
3080
|
+
size="normal"
|
|
3081
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
2966
3082
|
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
</div>
|
|
3083
|
+
</p-avatar>
|
|
3084
|
+
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
3085
|
+
</button>
|
|
2971
3086
|
</div>
|
|
2972
3087
|
</div>
|
|
2973
|
-
</div
|
|
3088
|
+
</div>
|
|
3089
|
+
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$5.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$3.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$3.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$1.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: "component", type: AppTopbarApplicationSwitcherComponent, selector: "app-topbar-application-switcher" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
2974
3090
|
}
|
|
2975
3091
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AppTopbar, decorators: [{
|
|
2976
3092
|
type: Component,
|
|
@@ -2992,106 +3108,108 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
2992
3108
|
TranslatePipe,
|
|
2993
3109
|
AppTopbarApplicationSwitcherComponent
|
|
2994
3110
|
],
|
|
2995
|
-
template: `
|
|
2996
|
-
<
|
|
2997
|
-
|
|
2998
|
-
<
|
|
2999
|
-
<
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
<
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
</div>
|
|
3111
|
+
template: ` <div class="layout-topbar">
|
|
3112
|
+
<p-confirmDialog appendTo="body" />
|
|
3113
|
+
<div class="layout-topbar-logo-container">
|
|
3114
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
3115
|
+
<i class="pi pi-bars"></i>
|
|
3116
|
+
</button>
|
|
3117
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
3118
|
+
<ng-container
|
|
3119
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
3120
|
+
<span>{{ 'app-info.title' | translate }}</span>
|
|
3121
|
+
</a>
|
|
3122
|
+
</div>
|
|
3008
3123
|
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3124
|
+
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
3125
|
+
<p-tabs
|
|
3126
|
+
class="layout-topbar-tabs ml-2"
|
|
3127
|
+
[value]="topBarService.activeId"
|
|
3128
|
+
(valueChange)="onActiveTabChange($event)">
|
|
3129
|
+
<p-tablist>
|
|
3130
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
3131
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
3132
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
3133
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
3134
|
+
</p-tab>
|
|
3135
|
+
}
|
|
3136
|
+
</p-tablist>
|
|
3137
|
+
</p-tabs>
|
|
3138
|
+
}
|
|
3139
|
+
<div class="layout-topbar-actions">
|
|
3140
|
+
<div class="layout-config-menu">
|
|
3141
|
+
<app-topbar-application-switcher />
|
|
3142
|
+
<app-user-notifications />
|
|
3143
|
+
<p-button
|
|
3144
|
+
class="layout-topbar-action"
|
|
3145
|
+
id="oip-app-topbar-theme-button"
|
|
3146
|
+
severity="secondary"
|
|
3147
|
+
type="button"
|
|
3148
|
+
[rounded]="true"
|
|
3149
|
+
[text]="true"
|
|
3150
|
+
(click)="toggleDarkMode()">
|
|
3151
|
+
<i
|
|
3152
|
+
class="pi"
|
|
3153
|
+
[ngClass]="{
|
|
3036
3154
|
'pi-moon': layoutService.isDarkTheme(),
|
|
3037
3155
|
'pi-sun': !layoutService.isDarkTheme()
|
|
3038
3156
|
}"></i>
|
|
3157
|
+
</p-button>
|
|
3158
|
+
<div class="relative">
|
|
3159
|
+
<p-button
|
|
3160
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
3161
|
+
enterActiveClass="animate-scalein"
|
|
3162
|
+
enterFromClass="hidden"
|
|
3163
|
+
id="oip-app-topbar-palette-button"
|
|
3164
|
+
leaveActiveClass="animate-fadeout"
|
|
3165
|
+
leaveToClass="hidden"
|
|
3166
|
+
pStyleClass="@next"
|
|
3167
|
+
[hideOnOutsideClick]="true"
|
|
3168
|
+
[rounded]="true">
|
|
3169
|
+
<i class="pi pi-palette"></i>
|
|
3039
3170
|
</p-button>
|
|
3040
|
-
<
|
|
3041
|
-
<p-button
|
|
3042
|
-
class="layout-topbar-action layout-topbar-action-highlight"
|
|
3043
|
-
enterActiveClass="animate-scalein"
|
|
3044
|
-
enterFromClass="hidden"
|
|
3045
|
-
id="oip-app-topbar-palette-button"
|
|
3046
|
-
leaveActiveClass="animate-fadeout"
|
|
3047
|
-
leaveToClass="hidden"
|
|
3048
|
-
pStyleClass="@next"
|
|
3049
|
-
[hideOnOutsideClick]="true"
|
|
3050
|
-
[rounded]="true">
|
|
3051
|
-
<i class="pi pi-palette"></i>
|
|
3052
|
-
</p-button>
|
|
3053
|
-
<app-configurator/>
|
|
3054
|
-
</div>
|
|
3171
|
+
<app-configurator />
|
|
3055
3172
|
</div>
|
|
3173
|
+
</div>
|
|
3056
3174
|
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3175
|
+
<button
|
|
3176
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
3177
|
+
enterActiveClass="animate-scalein"
|
|
3178
|
+
enterFromClass="hidden"
|
|
3179
|
+
id="oip-app-topbar-menu-expand-button"
|
|
3180
|
+
leaveActiveClass="animate-fadeout"
|
|
3181
|
+
leaveToClass="hidden"
|
|
3182
|
+
pStyleClass="@next"
|
|
3183
|
+
[hideOnOutsideClick]="true">
|
|
3184
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
3185
|
+
</button>
|
|
3068
3186
|
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3187
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
3188
|
+
<div class="layout-topbar-menu-content">
|
|
3189
|
+
<button
|
|
3190
|
+
class="layout-topbar-action"
|
|
3191
|
+
id="oip-app-topbar-logout-button"
|
|
3192
|
+
type="button"
|
|
3193
|
+
(click)="confirmLogout()"
|
|
3194
|
+
(keydown)="logoutKeyDown($event)">
|
|
3195
|
+
<i class="pi pi-sign-out"></i>
|
|
3196
|
+
<span>{{ 'topbar.logout' | translate }}</span>
|
|
3197
|
+
</button>
|
|
3198
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
3199
|
+
<p-avatar
|
|
3200
|
+
class="p-link flex align-items-center"
|
|
3201
|
+
id="oip-app-topbar-user-avatar"
|
|
3202
|
+
shape="circle"
|
|
3203
|
+
size="normal"
|
|
3204
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
3087
3205
|
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
</div>
|
|
3206
|
+
</p-avatar>
|
|
3207
|
+
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
3208
|
+
</button>
|
|
3092
3209
|
</div>
|
|
3093
3210
|
</div>
|
|
3094
|
-
</div
|
|
3211
|
+
</div>
|
|
3212
|
+
</div>`,
|
|
3095
3213
|
providers: [ConfirmationService]
|
|
3096
3214
|
}]
|
|
3097
3215
|
}] });
|
|
@@ -3206,10 +3324,16 @@ class MenuService {
|
|
|
3206
3324
|
this.resetSource = new Subject();
|
|
3207
3325
|
this.titleService = inject(AppTitleService);
|
|
3208
3326
|
this.menuDataService = inject(MenuApi);
|
|
3327
|
+
this.layoutService = inject(LayoutService);
|
|
3209
3328
|
this.menuSource$ = this.menuSource.asObservable();
|
|
3210
3329
|
this.resetSource$ = this.resetSource.asObservable();
|
|
3211
3330
|
this.menu = [];
|
|
3212
|
-
|
|
3331
|
+
}
|
|
3332
|
+
get adminMode() {
|
|
3333
|
+
return this.layoutService.adminMode();
|
|
3334
|
+
}
|
|
3335
|
+
set adminMode(value) {
|
|
3336
|
+
this.layoutService.layoutConfig.update((config) => ({ ...config, adminMode: value }));
|
|
3213
3337
|
}
|
|
3214
3338
|
async loadMenu() {
|
|
3215
3339
|
this.menu = this.adminMode ? await this.getAdminMenu() : await this.getMenu();
|
|
@@ -4179,8 +4303,7 @@ class MenuComponent {
|
|
|
4179
4303
|
];
|
|
4180
4304
|
}
|
|
4181
4305
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4182
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: MenuComponent, isStandalone: true, selector: "app-menu", providers: [MenuApi], viewQueries: [{ propertyName: "menuItemCreateDialogComponent", first: true, predicate: MenuItemCreateDialogComponent, descendants: true }, { propertyName: "menuItemEditDialogComponent", first: true, predicate: MenuItemEditDialogComponent, descendants: true }, { propertyName: "contextMenu", first: true, predicate: ContextMenu, descendants: true }], ngImport: i0, template: `
|
|
4183
|
-
<div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
4306
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: MenuComponent, isStandalone: true, selector: "app-menu", providers: [MenuApi], viewQueries: [{ propertyName: "menuItemCreateDialogComponent", first: true, predicate: MenuItemCreateDialogComponent, descendants: true }, { propertyName: "menuItemEditDialogComponent", first: true, predicate: MenuItemEditDialogComponent, descendants: true }, { propertyName: "contextMenu", first: true, predicate: ContextMenu, descendants: true }], ngImport: i0, template: ` <div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
4184
4307
|
<ul class="layout-menu">
|
|
4185
4308
|
@for (item of menuService.menu; track item; let i = $index) {
|
|
4186
4309
|
<ng-container>
|
|
@@ -4201,9 +4324,9 @@ class MenuComponent {
|
|
|
4201
4324
|
</ul>
|
|
4202
4325
|
</div>
|
|
4203
4326
|
@if (securityService.isAdmin()) {
|
|
4204
|
-
<p-contextMenu [target]="empty"/>
|
|
4205
|
-
<menu-item-create-dialog/>
|
|
4206
|
-
<menu-item-edit-dialog/>
|
|
4327
|
+
<p-contextMenu [target]="empty" />
|
|
4328
|
+
<menu-item-create-dialog />
|
|
4329
|
+
<menu-item-edit-dialog />
|
|
4207
4330
|
}`, 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$6.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"] }] }); }
|
|
4208
4331
|
}
|
|
4209
4332
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MenuComponent, decorators: [{
|
|
@@ -4222,8 +4345,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
4222
4345
|
providers: [MenuApi],
|
|
4223
4346
|
selector: 'app-menu',
|
|
4224
4347
|
standalone: true,
|
|
4225
|
-
template: `
|
|
4226
|
-
<div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
4348
|
+
template: ` <div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
4227
4349
|
<ul class="layout-menu">
|
|
4228
4350
|
@for (item of menuService.menu; track item; let i = $index) {
|
|
4229
4351
|
<ng-container>
|
|
@@ -4244,9 +4366,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
4244
4366
|
</ul>
|
|
4245
4367
|
</div>
|
|
4246
4368
|
@if (securityService.isAdmin()) {
|
|
4247
|
-
<p-contextMenu [target]="empty"/>
|
|
4248
|
-
<menu-item-create-dialog/>
|
|
4249
|
-
<menu-item-edit-dialog/>
|
|
4369
|
+
<p-contextMenu [target]="empty" />
|
|
4370
|
+
<menu-item-create-dialog />
|
|
4371
|
+
<menu-item-edit-dialog />
|
|
4250
4372
|
}`
|
|
4251
4373
|
}]
|
|
4252
4374
|
}], propDecorators: { menuItemCreateDialogComponent: [{
|
|
@@ -4528,14 +4650,18 @@ class UnauthorizedComponent {
|
|
|
4528
4650
|
constructor() {
|
|
4529
4651
|
this.securityService = inject(SecurityService);
|
|
4530
4652
|
this.route = inject(ActivatedRoute);
|
|
4531
|
-
|
|
4653
|
+
}
|
|
4654
|
+
ngOnInit() {
|
|
4655
|
+
const returnUrl = sessionStorage.getItem(BffSecurityService.authorizeAfterLogoutReturnUrlKey);
|
|
4656
|
+
if (!returnUrl) {
|
|
4657
|
+
return;
|
|
4658
|
+
}
|
|
4659
|
+
sessionStorage.removeItem(BffSecurityService.authorizeAfterLogoutReturnUrlKey);
|
|
4660
|
+
this.securityService.authorize(returnUrl);
|
|
4532
4661
|
}
|
|
4533
4662
|
signIn() {
|
|
4534
4663
|
const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') || '/';
|
|
4535
|
-
this.
|
|
4536
|
-
queryParams: { returnUrl },
|
|
4537
|
-
replaceUrl: true
|
|
4538
|
-
}).then(() => this.securityService.authorize());
|
|
4664
|
+
this.securityService.authorize(returnUrl);
|
|
4539
4665
|
}
|
|
4540
4666
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: UnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4541
4667
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: UnauthorizedComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: `
|
|
@@ -4690,9 +4816,21 @@ class ProfileComponent {
|
|
|
4690
4816
|
this.userService = inject(UserService);
|
|
4691
4817
|
this.msgService = inject(MsgService);
|
|
4692
4818
|
this.translateService = inject(TranslateService);
|
|
4819
|
+
this.userProfileApi = inject(UserProfileApi);
|
|
4693
4820
|
}
|
|
4694
|
-
|
|
4695
|
-
|
|
4821
|
+
async uploadPhoto(event) {
|
|
4822
|
+
const file = event.files?.[0];
|
|
4823
|
+
if (!file) {
|
|
4824
|
+
return;
|
|
4825
|
+
}
|
|
4826
|
+
try {
|
|
4827
|
+
await this.userProfileApi.postUserPhoto({ files: file });
|
|
4828
|
+
this.userService.refreshUserPhoto();
|
|
4829
|
+
this.msgService.success(this.translateService.instant('profileComponent.successfullyUploaded'));
|
|
4830
|
+
}
|
|
4831
|
+
catch (error) {
|
|
4832
|
+
this.msgService.error(error);
|
|
4833
|
+
}
|
|
4696
4834
|
}
|
|
4697
4835
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ProfileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4698
4836
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: ProfileComponent, isStandalone: true, selector: "user-profile", ngImport: i0, template: `
|
|
@@ -4711,10 +4849,9 @@ class ProfileComponent {
|
|
|
4711
4849
|
maxFileSize="1000000"
|
|
4712
4850
|
mode="basic"
|
|
4713
4851
|
name="files"
|
|
4714
|
-
url="/api/user-profile/post-user-photo"
|
|
4715
|
-
withCredentials="true"
|
|
4716
4852
|
[auto]="true"
|
|
4717
|
-
|
|
4853
|
+
[customUpload]="true"
|
|
4854
|
+
(uploadHandler)="uploadPhoto($event)" />
|
|
4718
4855
|
</div>
|
|
4719
4856
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FileUploadModule }, { kind: "component", type: i1$7.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$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
4720
4857
|
}
|
|
@@ -4723,7 +4860,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
4723
4860
|
args: [{
|
|
4724
4861
|
selector: 'user-profile',
|
|
4725
4862
|
standalone: true,
|
|
4726
|
-
imports: [FileUploadModule, ImageModule,
|
|
4863
|
+
imports: [FileUploadModule, ImageModule, AvatarModule, TranslatePipe],
|
|
4727
4864
|
template: `
|
|
4728
4865
|
<p-avatar
|
|
4729
4866
|
class="mr-2"
|
|
@@ -4740,10 +4877,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
4740
4877
|
maxFileSize="1000000"
|
|
4741
4878
|
mode="basic"
|
|
4742
4879
|
name="files"
|
|
4743
|
-
url="/api/user-profile/post-user-photo"
|
|
4744
|
-
withCredentials="true"
|
|
4745
4880
|
[auto]="true"
|
|
4746
|
-
|
|
4881
|
+
[customUpload]="true"
|
|
4882
|
+
(uploadHandler)="uploadPhoto($event)" />
|
|
4747
4883
|
</div>
|
|
4748
4884
|
`
|
|
4749
4885
|
}]
|
|
@@ -5045,7 +5181,7 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
5045
5181
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: DbMigrationComponent, isStandalone: true, selector: "db-migration", providers: [ConfirmationService], usesInheritance: true, ngImport: i0, template: `
|
|
5046
5182
|
@if (isContent) {
|
|
5047
5183
|
<div class="card" style="height: 100%">
|
|
5048
|
-
<p-confirmDialog/>
|
|
5184
|
+
<p-confirmDialog />
|
|
5049
5185
|
<div>
|
|
5050
5186
|
<h5>{{ 'db-migration.migrationManager' | translate }}</h5>
|
|
5051
5187
|
<div class="flex flex-row gap-2">
|
|
@@ -5055,14 +5191,14 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
5055
5191
|
tooltipPosition="bottom"
|
|
5056
5192
|
[outlined]="true"
|
|
5057
5193
|
[pTooltip]="'db-migration.actions.refresh' | translate"
|
|
5058
|
-
(click)="refreshAction()"/>
|
|
5194
|
+
(click)="refreshAction()" />
|
|
5059
5195
|
<p-button
|
|
5060
5196
|
icon="pi pi-filter-slash"
|
|
5061
5197
|
severity="secondary"
|
|
5062
5198
|
tooltipPosition="bottom"
|
|
5063
5199
|
[outlined]="true"
|
|
5064
5200
|
[pTooltip]="'db-migration.actions.cleanFilter' | translate"
|
|
5065
|
-
(click)="dt.clear()"/>
|
|
5201
|
+
(click)="dt.clear()" />
|
|
5066
5202
|
</div>
|
|
5067
5203
|
<div>
|
|
5068
5204
|
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
@@ -5070,7 +5206,7 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
5070
5206
|
<tr>
|
|
5071
5207
|
<th pSortableColumn="name" scope="col">
|
|
5072
5208
|
{{ 'db-migration.columns.name' | translate }}
|
|
5073
|
-
<p-columnFilter display="menu" field="name" type="text"/>
|
|
5209
|
+
<p-columnFilter display="menu" field="name" type="text" />
|
|
5074
5210
|
</th>
|
|
5075
5211
|
<th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
|
|
5076
5212
|
<th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
|
|
@@ -5091,7 +5227,7 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
5091
5227
|
</td>
|
|
5092
5228
|
<td>
|
|
5093
5229
|
@if (rowData.exist) {
|
|
5094
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"/>
|
|
5230
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true" />
|
|
5095
5231
|
}
|
|
5096
5232
|
</td>
|
|
5097
5233
|
<td>
|
|
@@ -5118,7 +5254,7 @@ class DbMigrationComponent extends BaseModuleComponent {
|
|
|
5118
5254
|
</div>
|
|
5119
5255
|
</div>
|
|
5120
5256
|
} @else if (isSecurity) {
|
|
5121
|
-
<security [controller]="controller" [id]="id"/>
|
|
5257
|
+
<security [controller]="controller" [id]="id" />
|
|
5122
5258
|
}
|
|
5123
5259
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$8.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$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$8.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i1$8.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i1$8.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i1$8.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" }] }); }
|
|
5124
5260
|
}
|
|
@@ -5142,7 +5278,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
5142
5278
|
template: `
|
|
5143
5279
|
@if (isContent) {
|
|
5144
5280
|
<div class="card" style="height: 100%">
|
|
5145
|
-
<p-confirmDialog/>
|
|
5281
|
+
<p-confirmDialog />
|
|
5146
5282
|
<div>
|
|
5147
5283
|
<h5>{{ 'db-migration.migrationManager' | translate }}</h5>
|
|
5148
5284
|
<div class="flex flex-row gap-2">
|
|
@@ -5152,14 +5288,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
5152
5288
|
tooltipPosition="bottom"
|
|
5153
5289
|
[outlined]="true"
|
|
5154
5290
|
[pTooltip]="'db-migration.actions.refresh' | translate"
|
|
5155
|
-
(click)="refreshAction()"/>
|
|
5291
|
+
(click)="refreshAction()" />
|
|
5156
5292
|
<p-button
|
|
5157
5293
|
icon="pi pi-filter-slash"
|
|
5158
5294
|
severity="secondary"
|
|
5159
5295
|
tooltipPosition="bottom"
|
|
5160
5296
|
[outlined]="true"
|
|
5161
5297
|
[pTooltip]="'db-migration.actions.cleanFilter' | translate"
|
|
5162
|
-
(click)="dt.clear()"/>
|
|
5298
|
+
(click)="dt.clear()" />
|
|
5163
5299
|
</div>
|
|
5164
5300
|
<div>
|
|
5165
5301
|
<p-table #dt dataKey="name" editMode="row" size="small" [scrollable]="true" [value]="data">
|
|
@@ -5167,7 +5303,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
5167
5303
|
<tr>
|
|
5168
5304
|
<th pSortableColumn="name" scope="col">
|
|
5169
5305
|
{{ 'db-migration.columns.name' | translate }}
|
|
5170
|
-
<p-columnFilter display="menu" field="name" type="text"/>
|
|
5306
|
+
<p-columnFilter display="menu" field="name" type="text" />
|
|
5171
5307
|
</th>
|
|
5172
5308
|
<th scope="col">{{ 'db-migration.columns.applied' | translate }}</th>
|
|
5173
5309
|
<th scope="col">{{ 'db-migration.columns.exist' | translate }}</th>
|
|
@@ -5188,7 +5324,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
5188
5324
|
</td>
|
|
5189
5325
|
<td>
|
|
5190
5326
|
@if (rowData.exist) {
|
|
5191
|
-
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true"/>
|
|
5327
|
+
<p-button icon="pi pi-check" severity="success" [rounded]="true" [text]="true" />
|
|
5192
5328
|
}
|
|
5193
5329
|
</td>
|
|
5194
5330
|
<td>
|
|
@@ -5215,13 +5351,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
5215
5351
|
</div>
|
|
5216
5352
|
</div>
|
|
5217
5353
|
} @else if (isSecurity) {
|
|
5218
|
-
<security [controller]="controller" [id]="id"/>
|
|
5354
|
+
<security [controller]="controller" [id]="id" />
|
|
5219
5355
|
}
|
|
5220
5356
|
`,
|
|
5221
5357
|
providers: [ConfirmationService]
|
|
5222
5358
|
}]
|
|
5223
5359
|
}], ctorParameters: () => [] });
|
|
5224
5360
|
|
|
5361
|
+
/* eslint-disable */
|
|
5362
|
+
/* tslint:disable */
|
|
5363
|
+
// @ts-nocheck
|
|
5364
|
+
class ExtensionModulesApi extends HttpClient {
|
|
5365
|
+
constructor() {
|
|
5366
|
+
super(...arguments);
|
|
5367
|
+
this.getExtensionModules = (params = {}) => this.request({
|
|
5368
|
+
path: `/api/extension-modules/get-extension-modules`,
|
|
5369
|
+
method: "GET",
|
|
5370
|
+
secure: true,
|
|
5371
|
+
format: "json",
|
|
5372
|
+
...params,
|
|
5373
|
+
});
|
|
5374
|
+
this.getExtensionModuleByKey = ({ extensionKey, ...query }, params = {}) => this.request({
|
|
5375
|
+
path: `/api/extension-modules/get-extension-module-by-key/${extensionKey}`,
|
|
5376
|
+
method: "GET",
|
|
5377
|
+
secure: true,
|
|
5378
|
+
format: "json",
|
|
5379
|
+
...params,
|
|
5380
|
+
});
|
|
5381
|
+
this.registerExtensionModule = (data, params = {}) => this.request({
|
|
5382
|
+
path: `/api/extension-modules/register-extension-module`,
|
|
5383
|
+
method: "POST",
|
|
5384
|
+
body: data,
|
|
5385
|
+
secure: true,
|
|
5386
|
+
type: ContentType.Json,
|
|
5387
|
+
format: "json",
|
|
5388
|
+
...params,
|
|
5389
|
+
});
|
|
5390
|
+
this.updateExtensionModule = ({ id, ...query }, data, params = {}) => this.request({
|
|
5391
|
+
path: `/api/extension-modules/update-extension-module/${id}`,
|
|
5392
|
+
method: "PUT",
|
|
5393
|
+
body: data,
|
|
5394
|
+
secure: true,
|
|
5395
|
+
type: ContentType.Json,
|
|
5396
|
+
format: "json",
|
|
5397
|
+
...params,
|
|
5398
|
+
});
|
|
5399
|
+
this.deleteExtensionModule = ({ id, ...query }, params = {}) => this.request({
|
|
5400
|
+
path: `/api/extension-modules/delete-extension-module/${id}`,
|
|
5401
|
+
method: "DELETE",
|
|
5402
|
+
secure: true,
|
|
5403
|
+
...params,
|
|
5404
|
+
});
|
|
5405
|
+
}
|
|
5406
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionModulesApi, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5407
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionModulesApi }); }
|
|
5408
|
+
}
|
|
5409
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionModulesApi, decorators: [{
|
|
5410
|
+
type: Injectable
|
|
5411
|
+
}] });
|
|
5412
|
+
|
|
5225
5413
|
/* eslint-disable */
|
|
5226
5414
|
/* tslint:disable */
|
|
5227
5415
|
// @ts-nocheck
|
|
@@ -5273,7 +5461,10 @@ class AppModulesComponent {
|
|
|
5273
5461
|
this.confirmationService = inject(ConfirmationService);
|
|
5274
5462
|
this.l10nService = inject(L10nService);
|
|
5275
5463
|
this.titleService = inject(AppTitleService);
|
|
5464
|
+
this.externalModuleManifestUrl = '';
|
|
5465
|
+
this.registeringExternalModule = false;
|
|
5276
5466
|
this.moduleService = inject(ModuleApi);
|
|
5467
|
+
this.extensionModulesService = inject(ExtensionModulesApi);
|
|
5277
5468
|
this.translationsReady = firstValueFrom(this.l10nService.loadComponentTranslations('app-modules'));
|
|
5278
5469
|
}
|
|
5279
5470
|
async ngOnInit() {
|
|
@@ -5284,6 +5475,30 @@ class AppModulesComponent {
|
|
|
5284
5475
|
async refreshAction() {
|
|
5285
5476
|
this.modules = await this.moduleService.getModulesWithLoadStatus();
|
|
5286
5477
|
}
|
|
5478
|
+
get canRegisterExternalModule() {
|
|
5479
|
+
return !!this.externalModuleManifestUrl.trim() && !this.registeringExternalModule;
|
|
5480
|
+
}
|
|
5481
|
+
async registerExternalModule() {
|
|
5482
|
+
if (!this.canRegisterExternalModule) {
|
|
5483
|
+
return;
|
|
5484
|
+
}
|
|
5485
|
+
await this.translationsReady;
|
|
5486
|
+
this.registeringExternalModule = true;
|
|
5487
|
+
try {
|
|
5488
|
+
await this.extensionModulesService.registerExtensionModule({
|
|
5489
|
+
manifestUrl: this.externalModuleManifestUrl.trim()
|
|
5490
|
+
});
|
|
5491
|
+
this.externalModuleManifestUrl = '';
|
|
5492
|
+
await this.refreshAction();
|
|
5493
|
+
this.msgService.success(this.t('app-modules.messages.registerSuccess'));
|
|
5494
|
+
}
|
|
5495
|
+
catch (error) {
|
|
5496
|
+
this.msgService.errorFromException(error, this.t('app-modules.messages.registerError'), this.t('app-modules.messages.registerError'));
|
|
5497
|
+
}
|
|
5498
|
+
finally {
|
|
5499
|
+
this.registeringExternalModule = false;
|
|
5500
|
+
}
|
|
5501
|
+
}
|
|
5287
5502
|
async deleteModule(module) {
|
|
5288
5503
|
await this.translationsReady;
|
|
5289
5504
|
this.confirmationService.confirm({
|
|
@@ -5308,7 +5523,7 @@ class AppModulesComponent {
|
|
|
5308
5523
|
this.msgService.success(this.t('app-modules.messages.deleteSuccess'));
|
|
5309
5524
|
}
|
|
5310
5525
|
catch (error) {
|
|
5311
|
-
this.msgService.error(
|
|
5526
|
+
this.msgService.errorFromException(error, this.t('app-modules.messages.deleteError'), this.t('app-modules.messages.deleteError'));
|
|
5312
5527
|
}
|
|
5313
5528
|
}
|
|
5314
5529
|
});
|
|
@@ -5317,7 +5532,7 @@ class AppModulesComponent {
|
|
|
5317
5532
|
return this.l10nService.instant(key);
|
|
5318
5533
|
}
|
|
5319
5534
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AppModulesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5320
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: AppModulesComponent, isStandalone: true, selector: "app-modules", providers: [ConfirmationService, ModuleApi], ngImport: i0, template: `
|
|
5535
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: AppModulesComponent, isStandalone: true, selector: "app-modules", providers: [ConfirmationService, ModuleApi, ExtensionModulesApi], ngImport: i0, template: `
|
|
5321
5536
|
<p-confirmDialog></p-confirmDialog>
|
|
5322
5537
|
<div class="flex flex-col md:flex-row gap-4">
|
|
5323
5538
|
<div class="card w-full">
|
|
@@ -5326,14 +5541,33 @@ class AppModulesComponent {
|
|
|
5326
5541
|
</div>
|
|
5327
5542
|
<div class="mb-4">
|
|
5328
5543
|
<p-toolbar>
|
|
5329
|
-
<
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5544
|
+
<div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
|
|
5545
|
+
<div class="flex flex-col sm:flex-row gap-2 flex-1">
|
|
5546
|
+
<input
|
|
5547
|
+
class="w-full"
|
|
5548
|
+
pInputText
|
|
5549
|
+
type="url"
|
|
5550
|
+
[disabled]="registeringExternalModule"
|
|
5551
|
+
[placeholder]="'app-modules.register.manifestUrlPlaceholder' | translate"
|
|
5552
|
+
[(ngModel)]="externalModuleManifestUrl"
|
|
5553
|
+
(keydown.enter)="registerExternalModule()" />
|
|
5554
|
+
<p-button
|
|
5555
|
+
icon="pi pi-plus"
|
|
5556
|
+
severity="success"
|
|
5557
|
+
[disabled]="!canRegisterExternalModule"
|
|
5558
|
+
[label]="'app-modules.register.button' | translate"
|
|
5559
|
+
[loading]="registeringExternalModule"
|
|
5560
|
+
(onClick)="registerExternalModule()"></p-button>
|
|
5561
|
+
</div>
|
|
5562
|
+
<p-button
|
|
5563
|
+
icon="pi pi-refresh"
|
|
5564
|
+
rounded="true"
|
|
5565
|
+
severity="secondary"
|
|
5566
|
+
text="true"
|
|
5567
|
+
tooltipPosition="bottom"
|
|
5568
|
+
[pTooltip]="'app-modules.refreshTooltip' | translate"
|
|
5569
|
+
(onClick)="refreshAction()"></p-button>
|
|
5570
|
+
</div>
|
|
5337
5571
|
</p-toolbar>
|
|
5338
5572
|
</div>
|
|
5339
5573
|
<p-table class="mt-4" [paginator]="true" [rows]="100" [value]="modules">
|
|
@@ -5371,13 +5605,23 @@ class AppModulesComponent {
|
|
|
5371
5605
|
</p-table>
|
|
5372
5606
|
</div>
|
|
5373
5607
|
</div>
|
|
5374
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$8.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$2.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:
|
|
5608
|
+
`, isInline: true, dependencies: [{ 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: TableModule }, { kind: "component", type: i1$8.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$2.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: i5$1.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: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
5375
5609
|
}
|
|
5376
5610
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AppModulesComponent, decorators: [{
|
|
5377
5611
|
type: Component,
|
|
5378
5612
|
args: [{
|
|
5379
|
-
imports: [
|
|
5380
|
-
|
|
5613
|
+
imports: [
|
|
5614
|
+
FormsModule,
|
|
5615
|
+
TableModule,
|
|
5616
|
+
Tag,
|
|
5617
|
+
ButtonModule,
|
|
5618
|
+
ToolbarModule,
|
|
5619
|
+
Tooltip,
|
|
5620
|
+
ConfirmDialog,
|
|
5621
|
+
TranslatePipe,
|
|
5622
|
+
InputTextModule
|
|
5623
|
+
],
|
|
5624
|
+
providers: [ConfirmationService, ModuleApi, ExtensionModulesApi],
|
|
5381
5625
|
selector: 'app-modules',
|
|
5382
5626
|
template: `
|
|
5383
5627
|
<p-confirmDialog></p-confirmDialog>
|
|
@@ -5388,14 +5632,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
5388
5632
|
</div>
|
|
5389
5633
|
<div class="mb-4">
|
|
5390
5634
|
<p-toolbar>
|
|
5391
|
-
<
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5635
|
+
<div class="flex flex-col md:flex-row md:items-center gap-2 w-full">
|
|
5636
|
+
<div class="flex flex-col sm:flex-row gap-2 flex-1">
|
|
5637
|
+
<input
|
|
5638
|
+
class="w-full"
|
|
5639
|
+
pInputText
|
|
5640
|
+
type="url"
|
|
5641
|
+
[disabled]="registeringExternalModule"
|
|
5642
|
+
[placeholder]="'app-modules.register.manifestUrlPlaceholder' | translate"
|
|
5643
|
+
[(ngModel)]="externalModuleManifestUrl"
|
|
5644
|
+
(keydown.enter)="registerExternalModule()" />
|
|
5645
|
+
<p-button
|
|
5646
|
+
icon="pi pi-plus"
|
|
5647
|
+
severity="success"
|
|
5648
|
+
[disabled]="!canRegisterExternalModule"
|
|
5649
|
+
[label]="'app-modules.register.button' | translate"
|
|
5650
|
+
[loading]="registeringExternalModule"
|
|
5651
|
+
(onClick)="registerExternalModule()"></p-button>
|
|
5652
|
+
</div>
|
|
5653
|
+
<p-button
|
|
5654
|
+
icon="pi pi-refresh"
|
|
5655
|
+
rounded="true"
|
|
5656
|
+
severity="secondary"
|
|
5657
|
+
text="true"
|
|
5658
|
+
tooltipPosition="bottom"
|
|
5659
|
+
[pTooltip]="'app-modules.refreshTooltip' | translate"
|
|
5660
|
+
(onClick)="refreshAction()"></p-button>
|
|
5661
|
+
</div>
|
|
5399
5662
|
</p-toolbar>
|
|
5400
5663
|
</div>
|
|
5401
5664
|
<p-table class="mt-4" [paginator]="true" [rows]="100" [value]="modules">
|
|
@@ -5649,9 +5912,7 @@ class ApplicationsComponent {
|
|
|
5649
5912
|
this.visibleApplications = this.filterApplications(this.globalFilter);
|
|
5650
5913
|
}
|
|
5651
5914
|
filterApplications(filter) {
|
|
5652
|
-
const source = this.draftApplication
|
|
5653
|
-
? [this.draftApplication, ...this.applications]
|
|
5654
|
-
: [...this.applications];
|
|
5915
|
+
const source = this.draftApplication ? [this.draftApplication, ...this.applications] : [...this.applications];
|
|
5655
5916
|
const normalizedFilter = filter.trim().toLocaleLowerCase();
|
|
5656
5917
|
if (!normalizedFilter) {
|
|
5657
5918
|
return source;
|
|
@@ -5750,7 +6011,7 @@ class ApplicationsComponent {
|
|
|
5750
6011
|
{{ 'applications.table.icon' | translate }}
|
|
5751
6012
|
<p-sortIcon field="icon"></p-sortIcon>
|
|
5752
6013
|
</th>
|
|
5753
|
-
<th
|
|
6014
|
+
<th class="text-right" pSortableColumn="order">
|
|
5754
6015
|
{{ 'applications.table.order' | translate }}
|
|
5755
6016
|
<p-sortIcon field="order"></p-sortIcon>
|
|
5756
6017
|
</th>
|
|
@@ -5823,16 +6084,16 @@ class ApplicationsComponent {
|
|
|
5823
6084
|
[severity]="application.enabled ? 'success' : 'danger'"
|
|
5824
6085
|
[value]="
|
|
5825
6086
|
(application.enabled ? 'applications.table.yes' : 'applications.table.no') | translate
|
|
5826
|
-
|
|
6087
|
+
"></p-tag>
|
|
5827
6088
|
}
|
|
5828
6089
|
</td>
|
|
5829
6090
|
<td>
|
|
5830
6091
|
@if (application._isEditing && application._editModel; as editModel) {
|
|
5831
6092
|
<p-select
|
|
6093
|
+
appendTo="body"
|
|
5832
6094
|
class="w-full min-w-36"
|
|
5833
6095
|
optionLabel="label"
|
|
5834
6096
|
optionValue="value"
|
|
5835
|
-
appendTo="body"
|
|
5836
6097
|
[options]="serviceTypeOptions"
|
|
5837
6098
|
[(ngModel)]="editModel.serviceType"></p-select>
|
|
5838
6099
|
} @else {
|
|
@@ -5853,33 +6114,33 @@ class ApplicationsComponent {
|
|
|
5853
6114
|
icon="pi pi-check"
|
|
5854
6115
|
severity="success"
|
|
5855
6116
|
text="true"
|
|
6117
|
+
tooltipPosition="bottom"
|
|
5856
6118
|
[disabled]="activeRowAction"
|
|
5857
6119
|
[pTooltip]="'applications.table.saveTooltip' | translate"
|
|
5858
|
-
tooltipPosition="bottom"
|
|
5859
6120
|
(onClick)="saveApplication(application)"></p-button>
|
|
5860
6121
|
<p-button
|
|
5861
6122
|
icon="pi pi-times"
|
|
5862
6123
|
severity="secondary"
|
|
5863
6124
|
text="true"
|
|
6125
|
+
tooltipPosition="bottom"
|
|
5864
6126
|
[disabled]="activeRowAction"
|
|
5865
6127
|
[pTooltip]="'applications.table.cancelTooltip' | translate"
|
|
5866
|
-
tooltipPosition="bottom"
|
|
5867
6128
|
(onClick)="cancelEdit(application)"></p-button>
|
|
5868
6129
|
} @else {
|
|
5869
6130
|
<p-button
|
|
5870
6131
|
icon="pi pi-pencil"
|
|
5871
6132
|
text="true"
|
|
6133
|
+
tooltipPosition="bottom"
|
|
5872
6134
|
[disabled]="activeRowAction"
|
|
5873
6135
|
[pTooltip]="'applications.table.editTooltip' | translate"
|
|
5874
|
-
tooltipPosition="bottom"
|
|
5875
6136
|
(onClick)="editApplication(application)"></p-button>
|
|
5876
6137
|
<p-button
|
|
5877
6138
|
icon="pi pi-trash"
|
|
5878
6139
|
severity="danger"
|
|
5879
6140
|
text="true"
|
|
6141
|
+
tooltipPosition="bottom"
|
|
5880
6142
|
[disabled]="activeRowAction"
|
|
5881
6143
|
[pTooltip]="'applications.table.deleteTooltip' | translate"
|
|
5882
|
-
tooltipPosition="bottom"
|
|
5883
6144
|
(onClick)="deleteApplication(application)"></p-button>
|
|
5884
6145
|
}
|
|
5885
6146
|
</div>
|
|
@@ -5889,7 +6150,7 @@ class ApplicationsComponent {
|
|
|
5889
6150
|
|
|
5890
6151
|
<ng-template pTemplate="emptymessage">
|
|
5891
6152
|
<tr>
|
|
5892
|
-
<td
|
|
6153
|
+
<td class="py-8 text-center text-surface-500" colspan="10">
|
|
5893
6154
|
{{ 'applications.empty' | translate }}
|
|
5894
6155
|
</td>
|
|
5895
6156
|
</tr>
|
|
@@ -5897,7 +6158,7 @@ class ApplicationsComponent {
|
|
|
5897
6158
|
</p-table>
|
|
5898
6159
|
</div>
|
|
5899
6160
|
</div>
|
|
5900
|
-
`, isInline: true, dependencies: [{ 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { 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: TableModule }, { kind: "component", type: i1$8.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$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$8.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i1$8.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { 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:
|
|
6161
|
+
`, isInline: true, dependencies: [{ 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { 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: TableModule }, { kind: "component", type: i1$8.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$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$8.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i1$8.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { 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: i5$1.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: "directive", type: 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: ToggleSwitchModule }, { kind: "component", type: i2$4.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
5901
6162
|
}
|
|
5902
6163
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ApplicationsComponent, decorators: [{
|
|
5903
6164
|
type: Component,
|
|
@@ -6000,7 +6261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
6000
6261
|
{{ 'applications.table.icon' | translate }}
|
|
6001
6262
|
<p-sortIcon field="icon"></p-sortIcon>
|
|
6002
6263
|
</th>
|
|
6003
|
-
<th
|
|
6264
|
+
<th class="text-right" pSortableColumn="order">
|
|
6004
6265
|
{{ 'applications.table.order' | translate }}
|
|
6005
6266
|
<p-sortIcon field="order"></p-sortIcon>
|
|
6006
6267
|
</th>
|
|
@@ -6073,16 +6334,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
6073
6334
|
[severity]="application.enabled ? 'success' : 'danger'"
|
|
6074
6335
|
[value]="
|
|
6075
6336
|
(application.enabled ? 'applications.table.yes' : 'applications.table.no') | translate
|
|
6076
|
-
|
|
6337
|
+
"></p-tag>
|
|
6077
6338
|
}
|
|
6078
6339
|
</td>
|
|
6079
6340
|
<td>
|
|
6080
6341
|
@if (application._isEditing && application._editModel; as editModel) {
|
|
6081
6342
|
<p-select
|
|
6343
|
+
appendTo="body"
|
|
6082
6344
|
class="w-full min-w-36"
|
|
6083
6345
|
optionLabel="label"
|
|
6084
6346
|
optionValue="value"
|
|
6085
|
-
appendTo="body"
|
|
6086
6347
|
[options]="serviceTypeOptions"
|
|
6087
6348
|
[(ngModel)]="editModel.serviceType"></p-select>
|
|
6088
6349
|
} @else {
|
|
@@ -6103,33 +6364,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
6103
6364
|
icon="pi pi-check"
|
|
6104
6365
|
severity="success"
|
|
6105
6366
|
text="true"
|
|
6367
|
+
tooltipPosition="bottom"
|
|
6106
6368
|
[disabled]="activeRowAction"
|
|
6107
6369
|
[pTooltip]="'applications.table.saveTooltip' | translate"
|
|
6108
|
-
tooltipPosition="bottom"
|
|
6109
6370
|
(onClick)="saveApplication(application)"></p-button>
|
|
6110
6371
|
<p-button
|
|
6111
6372
|
icon="pi pi-times"
|
|
6112
6373
|
severity="secondary"
|
|
6113
6374
|
text="true"
|
|
6375
|
+
tooltipPosition="bottom"
|
|
6114
6376
|
[disabled]="activeRowAction"
|
|
6115
6377
|
[pTooltip]="'applications.table.cancelTooltip' | translate"
|
|
6116
|
-
tooltipPosition="bottom"
|
|
6117
6378
|
(onClick)="cancelEdit(application)"></p-button>
|
|
6118
6379
|
} @else {
|
|
6119
6380
|
<p-button
|
|
6120
6381
|
icon="pi pi-pencil"
|
|
6121
6382
|
text="true"
|
|
6383
|
+
tooltipPosition="bottom"
|
|
6122
6384
|
[disabled]="activeRowAction"
|
|
6123
6385
|
[pTooltip]="'applications.table.editTooltip' | translate"
|
|
6124
|
-
tooltipPosition="bottom"
|
|
6125
6386
|
(onClick)="editApplication(application)"></p-button>
|
|
6126
6387
|
<p-button
|
|
6127
6388
|
icon="pi pi-trash"
|
|
6128
6389
|
severity="danger"
|
|
6129
6390
|
text="true"
|
|
6391
|
+
tooltipPosition="bottom"
|
|
6130
6392
|
[disabled]="activeRowAction"
|
|
6131
6393
|
[pTooltip]="'applications.table.deleteTooltip' | translate"
|
|
6132
|
-
tooltipPosition="bottom"
|
|
6133
6394
|
(onClick)="deleteApplication(application)"></p-button>
|
|
6134
6395
|
}
|
|
6135
6396
|
</div>
|
|
@@ -6139,7 +6400,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
6139
6400
|
|
|
6140
6401
|
<ng-template pTemplate="emptymessage">
|
|
6141
6402
|
<tr>
|
|
6142
|
-
<td
|
|
6403
|
+
<td class="py-8 text-center text-surface-500" colspan="10">
|
|
6143
6404
|
{{ 'applications.empty' | translate }}
|
|
6144
6405
|
</td>
|
|
6145
6406
|
</tr>
|
|
@@ -6468,7 +6729,9 @@ class DiscussionComponent {
|
|
|
6468
6729
|
deleteAttachment(comment, attachment) {
|
|
6469
6730
|
this.confirmationService.confirm({
|
|
6470
6731
|
header: this.translateService.instant('discussionComponent.warning'),
|
|
6471
|
-
message: this.translateService.instant('discussionComponent.confirmDeleteFile', {
|
|
6732
|
+
message: this.translateService.instant('discussionComponent.confirmDeleteFile', {
|
|
6733
|
+
fileName: attachment.fileName
|
|
6734
|
+
}),
|
|
6472
6735
|
icon: 'pi pi-trash',
|
|
6473
6736
|
rejectButtonProps: {
|
|
6474
6737
|
label: this.translateService.instant('discussionComponent.cancel'),
|
|
@@ -6671,27 +6934,24 @@ class DiscussionComponent {
|
|
|
6671
6934
|
}
|
|
6672
6935
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: DiscussionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6673
6936
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: DiscussionComponent, isStandalone: true, selector: "discussion", inputs: { objectTypeId: "objectTypeId", objectId: "objectId" }, providers: [ConfirmationService, DiscussionApi], usesOnChanges: true, ngImport: i0, template: `
|
|
6674
|
-
<p-confirmDialog/>
|
|
6937
|
+
<p-confirmDialog />
|
|
6675
6938
|
|
|
6676
6939
|
<section class="flex flex-col gap-4">
|
|
6677
|
-
|
|
6678
6940
|
<p-card class="block">
|
|
6679
6941
|
<div class="flex flex-col gap-4">
|
|
6680
6942
|
@if (!previewMode) {
|
|
6681
6943
|
<textarea
|
|
6682
|
-
pTextarea
|
|
6683
6944
|
class="min-h-28 w-full"
|
|
6684
|
-
|
|
6945
|
+
pTextarea
|
|
6685
6946
|
rows="5"
|
|
6686
|
-
[
|
|
6687
|
-
(ngModelChange)="onComposerInput()"
|
|
6947
|
+
[autoResize]="true"
|
|
6688
6948
|
[placeholder]="'discussionComponent.writeCommentPlaceholder' | translate"
|
|
6689
|
-
|
|
6949
|
+
[(ngModel)]="newComment"
|
|
6950
|
+
(ngModelChange)="onComposerInput()"></textarea>
|
|
6690
6951
|
} @else {
|
|
6691
6952
|
<div
|
|
6692
6953
|
class="markdown-preview min-h-28 rounded-2xl border border-surface-200 bg-surface-50 px-4 py-3 leading-7 dark:border-surface-700 dark:bg-surface-900/40"
|
|
6693
|
-
[innerHTML]="renderMarkdown(newComment)"
|
|
6694
|
-
></div>
|
|
6954
|
+
[innerHTML]="renderMarkdown(newComment)"></div>
|
|
6695
6955
|
}
|
|
6696
6956
|
|
|
6697
6957
|
@if (mentionSuggestions.length > 0) {
|
|
@@ -6706,10 +6966,9 @@ class DiscussionComponent {
|
|
|
6706
6966
|
<div class="flex flex-col gap-3">
|
|
6707
6967
|
@for (candidate of mentionSuggestions; track candidate.userId) {
|
|
6708
6968
|
<button
|
|
6709
|
-
type="button"
|
|
6710
6969
|
class="flex w-full items-center justify-between gap-4 rounded-xl border border-transparent px-3 py-3 text-left transition hover:border-primary-200 hover:bg-primary-50 dark:hover:border-primary-800 dark:hover:bg-primary-950/30"
|
|
6711
|
-
|
|
6712
|
-
|
|
6970
|
+
type="button"
|
|
6971
|
+
(click)="insertMention(candidate)">
|
|
6713
6972
|
<div class="min-w-0">
|
|
6714
6973
|
<strong>{{ candidate.displayName }}</strong>
|
|
6715
6974
|
<small class="mt-1 block text-surface-500">{{ candidate.email }}</small>
|
|
@@ -6729,15 +6988,14 @@ class DiscussionComponent {
|
|
|
6729
6988
|
<div class="inline-flex items-center gap-2">
|
|
6730
6989
|
<i class="pi pi-file"></i>
|
|
6731
6990
|
<span class="break-all">{{ file.name }}</span>
|
|
6732
|
-
<p-tag [value]="formatBytes(file.size)"
|
|
6991
|
+
<p-tag severity="contrast" [value]="formatBytes(file.size)" />
|
|
6733
6992
|
</div>
|
|
6734
6993
|
<p-button
|
|
6735
6994
|
icon="pi pi-times"
|
|
6736
6995
|
severity="danger"
|
|
6737
6996
|
[rounded]="true"
|
|
6738
6997
|
[text]="true"
|
|
6739
|
-
(onClick)="removePendingFile(file)"
|
|
6740
|
-
/>
|
|
6998
|
+
(onClick)="removePendingFile(file)" />
|
|
6741
6999
|
</div>
|
|
6742
7000
|
}
|
|
6743
7001
|
</div>
|
|
@@ -6745,33 +7003,28 @@ class DiscussionComponent {
|
|
|
6745
7003
|
|
|
6746
7004
|
<div class="flex flex-col gap-2 sm:flex-row sm:justify-end">
|
|
6747
7005
|
<p-button
|
|
7006
|
+
severity="secondary"
|
|
7007
|
+
[icon]="previewMode ? 'pi pi-pencil' : 'pi pi-eye'"
|
|
6748
7008
|
[label]="
|
|
6749
|
-
previewMode
|
|
6750
|
-
? ('discussionComponent.edit' | translate)
|
|
6751
|
-
: ('discussionComponent.preview' | translate)
|
|
7009
|
+
previewMode ? ('discussionComponent.edit' | translate) : ('discussionComponent.preview' | translate)
|
|
6752
7010
|
"
|
|
6753
|
-
[icon]="previewMode ? 'pi pi-pencil' : 'pi pi-eye'"
|
|
6754
|
-
severity="secondary"
|
|
6755
7011
|
[text]="true"
|
|
6756
|
-
(onClick)="previewMode = !previewMode"
|
|
6757
|
-
/>
|
|
7012
|
+
(onClick)="previewMode = !previewMode" />
|
|
6758
7013
|
|
|
6759
7014
|
<label class="file-trigger">
|
|
6760
7015
|
<p-button
|
|
6761
|
-
[label]="'discussionComponent.attachFiles' | translate"
|
|
6762
7016
|
icon="pi pi-paperclip"
|
|
6763
7017
|
severity="secondary"
|
|
6764
|
-
[
|
|
6765
|
-
|
|
6766
|
-
<input type="file"
|
|
7018
|
+
[label]="'discussionComponent.attachFiles' | translate"
|
|
7019
|
+
[text]="true" />
|
|
7020
|
+
<input multiple type="file" (change)="onFilesSelected($event)" />
|
|
6767
7021
|
</label>
|
|
6768
7022
|
<p-button
|
|
6769
|
-
[label]="'discussionComponent.send' | translate"
|
|
6770
7023
|
icon="pi pi-send"
|
|
6771
|
-
[loading]="submitting"
|
|
6772
7024
|
[disabled]="submitting || !newComment.trim()"
|
|
6773
|
-
|
|
6774
|
-
|
|
7025
|
+
[label]="'discussionComponent.send' | translate"
|
|
7026
|
+
[loading]="submitting"
|
|
7027
|
+
(onClick)="createComment()" />
|
|
6775
7028
|
</div>
|
|
6776
7029
|
</div>
|
|
6777
7030
|
</p-card>
|
|
@@ -6779,7 +7032,7 @@ class DiscussionComponent {
|
|
|
6779
7032
|
@if (loading) {
|
|
6780
7033
|
<div
|
|
6781
7034
|
class="flex min-h-20 flex-col items-center justify-center gap-3 rounded-2xl border border-surface-200 px-4 py-5 text-surface-500 dark:border-surface-700">
|
|
6782
|
-
<p-progressSpinner strokeWidth="4"/>
|
|
7035
|
+
<p-progressSpinner strokeWidth="4" />
|
|
6783
7036
|
<span>{{ 'discussionComponent.loadingComments' | translate }}</span>
|
|
6784
7037
|
</div>
|
|
6785
7038
|
} @else if (comments.length === 0) {
|
|
@@ -6795,24 +7048,25 @@ class DiscussionComponent {
|
|
|
6795
7048
|
<ng-template pTemplate="content">
|
|
6796
7049
|
<div class="grid gap-4 md:grid-cols-[3.2rem_minmax(0,1fr)]">
|
|
6797
7050
|
<div>
|
|
6798
|
-
<p-avatar
|
|
6799
|
-
[label]="getInitialsFromString(comment.authorDisplayName)"
|
|
6800
|
-
shape="circle"
|
|
6801
|
-
/>
|
|
7051
|
+
<p-avatar shape="circle" [label]="getInitialsFromString(comment.authorDisplayName)" />
|
|
6802
7052
|
</div>
|
|
6803
7053
|
|
|
6804
7054
|
<div class="flex flex-col gap-2">
|
|
6805
7055
|
<div class="flex flex-row gap-3 justify-between">
|
|
6806
7056
|
<div class="flex flex-wrap items-center gap-2">
|
|
6807
7057
|
<strong>{{ comment.authorDisplayName }}</strong>
|
|
6808
|
-
<span
|
|
6809
|
-
|
|
7058
|
+
<span class="text-sm text-surface-500">{{
|
|
7059
|
+
comment.createdAt | date: layoutService.dateTimeFormat()
|
|
7060
|
+
}}</span>
|
|
6810
7061
|
</div>
|
|
6811
7062
|
|
|
6812
7063
|
<div class="flex flex-wrap items-center justify-end gap-2">
|
|
6813
7064
|
<div class="flex flex-wrap items-center">
|
|
6814
7065
|
@if (comment.isEdited) {
|
|
6815
|
-
<p-tag
|
|
7066
|
+
<p-tag
|
|
7067
|
+
icon="pi pi-pencil"
|
|
7068
|
+
severity="warn"
|
|
7069
|
+
[value]="'discussionComponent.edited' | translate" />
|
|
6816
7070
|
}
|
|
6817
7071
|
</div>
|
|
6818
7072
|
@if (comment.canEdit) {
|
|
@@ -6821,8 +7075,7 @@ class DiscussionComponent {
|
|
|
6821
7075
|
severity="secondary"
|
|
6822
7076
|
[rounded]="true"
|
|
6823
7077
|
[text]="true"
|
|
6824
|
-
(onClick)="startEdit(comment)"
|
|
6825
|
-
/>
|
|
7078
|
+
(onClick)="startEdit(comment)" />
|
|
6826
7079
|
}
|
|
6827
7080
|
@if (comment.historyCount > 0) {
|
|
6828
7081
|
<p-button
|
|
@@ -6830,8 +7083,7 @@ class DiscussionComponent {
|
|
|
6830
7083
|
severity="secondary"
|
|
6831
7084
|
[rounded]="true"
|
|
6832
7085
|
[text]="true"
|
|
6833
|
-
(onClick)="toggleHistory(comment)"
|
|
6834
|
-
/>
|
|
7086
|
+
(onClick)="toggleHistory(comment)" />
|
|
6835
7087
|
}
|
|
6836
7088
|
@if (comment.canDelete) {
|
|
6837
7089
|
<p-button
|
|
@@ -6839,47 +7091,42 @@ class DiscussionComponent {
|
|
|
6839
7091
|
severity="danger"
|
|
6840
7092
|
[rounded]="true"
|
|
6841
7093
|
[text]="true"
|
|
6842
|
-
(onClick)="deleteComment(comment)"
|
|
6843
|
-
/>
|
|
7094
|
+
(onClick)="deleteComment(comment)" />
|
|
6844
7095
|
}
|
|
6845
7096
|
</div>
|
|
6846
7097
|
</div>
|
|
6847
7098
|
@if (editingCommentId === comment.commentId) {
|
|
6848
7099
|
<div class="flex flex-col gap-4">
|
|
6849
7100
|
<textarea
|
|
6850
|
-
pTextarea
|
|
6851
7101
|
class="min-h-24 w-full"
|
|
6852
|
-
|
|
7102
|
+
pTextarea
|
|
6853
7103
|
rows="4"
|
|
6854
|
-
[
|
|
7104
|
+
[autoResize]="true"
|
|
6855
7105
|
[placeholder]="'discussionComponent.editCommentPlaceholder' | translate"
|
|
6856
|
-
|
|
7106
|
+
[(ngModel)]="editContent"></textarea>
|
|
6857
7107
|
<div class="flex flex-col gap-2 sm:flex-row sm:justify-end">
|
|
6858
7108
|
<div>
|
|
6859
7109
|
<label class="file-trigger">
|
|
6860
7110
|
<p-button
|
|
6861
|
-
[label]="'discussionComponent.addAttachment' | translate"
|
|
6862
7111
|
icon="pi pi-paperclip"
|
|
6863
|
-
[text]="true"
|
|
6864
7112
|
severity="secondary"
|
|
6865
|
-
|
|
6866
|
-
|
|
7113
|
+
[label]="'discussionComponent.addAttachment' | translate"
|
|
7114
|
+
[text]="true" />
|
|
7115
|
+
<input multiple type="file" (change)="onInlineFilesSelected(comment, $event)" />
|
|
6867
7116
|
</label>
|
|
6868
7117
|
</div>
|
|
6869
7118
|
|
|
6870
7119
|
<p-button
|
|
6871
|
-
[label]="'discussionComponent.save' | translate"
|
|
6872
7120
|
icon="pi pi-check"
|
|
6873
7121
|
[disabled]="!editContent.trim()"
|
|
6874
|
-
|
|
6875
|
-
|
|
7122
|
+
[label]="'discussionComponent.save' | translate"
|
|
7123
|
+
(onClick)="saveEdit(comment)" />
|
|
6876
7124
|
<p-button
|
|
6877
|
-
[label]="'discussionComponent.cancel' | translate"
|
|
6878
7125
|
icon="pi pi-times"
|
|
6879
7126
|
severity="secondary"
|
|
7127
|
+
[label]="'discussionComponent.cancel' | translate"
|
|
6880
7128
|
[text]="true"
|
|
6881
|
-
(onClick)="cancelEdit()"
|
|
6882
|
-
/>
|
|
7129
|
+
(onClick)="cancelEdit()" />
|
|
6883
7130
|
</div>
|
|
6884
7131
|
</div>
|
|
6885
7132
|
} @else {
|
|
@@ -6894,13 +7141,12 @@ class DiscussionComponent {
|
|
|
6894
7141
|
<div class="inline-flex items-center gap-2">
|
|
6895
7142
|
<i class="pi pi-file"></i>
|
|
6896
7143
|
<button
|
|
6897
|
-
type="button"
|
|
6898
7144
|
class="break-all bg-transparent p-0 text-left font-semibold text-primary-600 transition hover:text-primary-500"
|
|
6899
|
-
|
|
6900
|
-
|
|
7145
|
+
type="button"
|
|
7146
|
+
(click)="downloadAttachment(attachment)">
|
|
6901
7147
|
{{ attachment.fileName }}
|
|
6902
7148
|
</button>
|
|
6903
|
-
<p-tag [value]="formatBytes(attachment.fileSize)"
|
|
7149
|
+
<p-tag severity="contrast" [value]="formatBytes(attachment.fileSize)" />
|
|
6904
7150
|
</div>
|
|
6905
7151
|
|
|
6906
7152
|
@if (comment.canEdit) {
|
|
@@ -6909,8 +7155,7 @@ class DiscussionComponent {
|
|
|
6909
7155
|
severity="danger"
|
|
6910
7156
|
[rounded]="true"
|
|
6911
7157
|
[text]="true"
|
|
6912
|
-
(onClick)="deleteAttachment(comment, attachment)"
|
|
6913
|
-
/>
|
|
7158
|
+
(onClick)="deleteAttachment(comment, attachment)" />
|
|
6914
7159
|
}
|
|
6915
7160
|
</div>
|
|
6916
7161
|
}
|
|
@@ -6921,11 +7166,10 @@ class DiscussionComponent {
|
|
|
6921
7166
|
<div class="flex flex-wrap items-center gap-2">
|
|
6922
7167
|
@for (reaction of getReactions(comment); track reaction.emojiCode) {
|
|
6923
7168
|
<p-button
|
|
6924
|
-
[label]="reaction.emojiCode + ' ' + reaction.count"
|
|
6925
7169
|
severity="secondary"
|
|
7170
|
+
[label]="reaction.emojiCode + ' ' + reaction.count"
|
|
6926
7171
|
[outlined]="false"
|
|
6927
|
-
(onClick)="toggleReaction(comment, reaction)"
|
|
6928
|
-
/>
|
|
7172
|
+
(onClick)="toggleReaction(comment, reaction)" />
|
|
6929
7173
|
}
|
|
6930
7174
|
|
|
6931
7175
|
@if (!hasUserReaction(comment)) {
|
|
@@ -6934,16 +7178,14 @@ class DiscussionComponent {
|
|
|
6934
7178
|
severity="secondary"
|
|
6935
7179
|
[rounded]="true"
|
|
6936
7180
|
[text]="true"
|
|
6937
|
-
(onClick)="reactionPopover.toggle($event)"
|
|
6938
|
-
/>
|
|
7181
|
+
(onClick)="reactionPopover.toggle($event)" />
|
|
6939
7182
|
<p-popover #reactionPopover>
|
|
6940
7183
|
<div class="emoji-popover">
|
|
6941
7184
|
@for (emoji of emojiPalette; track emoji) {
|
|
6942
7185
|
<button
|
|
6943
|
-
type="button"
|
|
6944
7186
|
class="emoji-option"
|
|
6945
|
-
|
|
6946
|
-
|
|
7187
|
+
type="button"
|
|
7188
|
+
(click)="reactWithEmoji(comment, emoji, reactionPopover)">
|
|
6947
7189
|
{{ emoji }}
|
|
6948
7190
|
</button>
|
|
6949
7191
|
}
|
|
@@ -6953,7 +7195,7 @@ class DiscussionComponent {
|
|
|
6953
7195
|
</div>
|
|
6954
7196
|
|
|
6955
7197
|
@if (historyByComment[comment.commentId]?.opened) {
|
|
6956
|
-
<p-panel class="block" [
|
|
7198
|
+
<p-panel class="block" [collapsed]="false" [toggleable]="true">
|
|
6957
7199
|
<ng-template pTemplate="header">
|
|
6958
7200
|
<div class="inline-flex items-center gap-2 text-sm font-medium">
|
|
6959
7201
|
<i class="pi pi-history"></i>
|
|
@@ -6963,12 +7205,15 @@ class DiscussionComponent {
|
|
|
6963
7205
|
|
|
6964
7206
|
@if (historyByComment[comment.commentId]?.loading) {
|
|
6965
7207
|
<div class="flex items-center gap-3 text-surface-500">
|
|
6966
|
-
<p-progressSpinner strokeWidth="4"/>
|
|
7208
|
+
<p-progressSpinner strokeWidth="4" />
|
|
6967
7209
|
<span>{{ 'discussionComponent.loadingHistory' | translate }}</span>
|
|
6968
7210
|
</div>
|
|
6969
7211
|
} @else {
|
|
6970
7212
|
<div class="flex flex-col gap-4">
|
|
6971
|
-
@for (
|
|
7213
|
+
@for (
|
|
7214
|
+
item of historyByComment[comment.commentId]?.items ?? [];
|
|
7215
|
+
track item.commentEditHistoryId
|
|
7216
|
+
) {
|
|
6972
7217
|
<div class="rounded-2xl border border-surface-200 px-4 py-4 dark:border-surface-700">
|
|
6973
7218
|
<div class="mb-3 inline-flex items-center gap-2 text-sm font-semibold">
|
|
6974
7219
|
<i class="pi pi-clock"></i>
|
|
@@ -6976,18 +7221,16 @@ class DiscussionComponent {
|
|
|
6976
7221
|
</div>
|
|
6977
7222
|
<div class="grid gap-4 lg:grid-cols-2">
|
|
6978
7223
|
<div class="flex flex-col gap-2">
|
|
6979
|
-
<p-tag [value]="'discussionComponent.before' | translate"
|
|
7224
|
+
<p-tag severity="secondary" [value]="'discussionComponent.before' | translate" />
|
|
6980
7225
|
<div
|
|
6981
7226
|
class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
|
|
6982
|
-
[innerHTML]="renderMarkdown(item.oldContent)"
|
|
6983
|
-
></div>
|
|
7227
|
+
[innerHTML]="renderMarkdown(item.oldContent)"></div>
|
|
6984
7228
|
</div>
|
|
6985
7229
|
<div class="flex flex-col gap-2">
|
|
6986
|
-
<p-tag [value]="'discussionComponent.after' | translate"
|
|
7230
|
+
<p-tag severity="success" [value]="'discussionComponent.after' | translate" />
|
|
6987
7231
|
<div
|
|
6988
7232
|
class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
|
|
6989
|
-
[innerHTML]="renderMarkdown(item.newContent)"
|
|
6990
|
-
></div>
|
|
7233
|
+
[innerHTML]="renderMarkdown(item.newContent)"></div>
|
|
6991
7234
|
</div>
|
|
6992
7235
|
</div>
|
|
6993
7236
|
</div>
|
|
@@ -7004,7 +7247,7 @@ class DiscussionComponent {
|
|
|
7004
7247
|
</div>
|
|
7005
7248
|
}
|
|
7006
7249
|
</section>
|
|
7007
|
-
`, 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$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i2$2.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$
|
|
7250
|
+
`, 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$1.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "directive", type: i2$2.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$2.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: i1$3.DatePipe, name: "date" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7008
7251
|
}
|
|
7009
7252
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: DiscussionComponent, decorators: [{
|
|
7010
7253
|
type: Component,
|
|
@@ -7024,27 +7267,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7024
7267
|
DatePipe,
|
|
7025
7268
|
TranslatePipe
|
|
7026
7269
|
], template: `
|
|
7027
|
-
<p-confirmDialog/>
|
|
7270
|
+
<p-confirmDialog />
|
|
7028
7271
|
|
|
7029
7272
|
<section class="flex flex-col gap-4">
|
|
7030
|
-
|
|
7031
7273
|
<p-card class="block">
|
|
7032
7274
|
<div class="flex flex-col gap-4">
|
|
7033
7275
|
@if (!previewMode) {
|
|
7034
7276
|
<textarea
|
|
7035
|
-
pTextarea
|
|
7036
7277
|
class="min-h-28 w-full"
|
|
7037
|
-
|
|
7278
|
+
pTextarea
|
|
7038
7279
|
rows="5"
|
|
7039
|
-
[
|
|
7040
|
-
(ngModelChange)="onComposerInput()"
|
|
7280
|
+
[autoResize]="true"
|
|
7041
7281
|
[placeholder]="'discussionComponent.writeCommentPlaceholder' | translate"
|
|
7042
|
-
|
|
7282
|
+
[(ngModel)]="newComment"
|
|
7283
|
+
(ngModelChange)="onComposerInput()"></textarea>
|
|
7043
7284
|
} @else {
|
|
7044
7285
|
<div
|
|
7045
7286
|
class="markdown-preview min-h-28 rounded-2xl border border-surface-200 bg-surface-50 px-4 py-3 leading-7 dark:border-surface-700 dark:bg-surface-900/40"
|
|
7046
|
-
[innerHTML]="renderMarkdown(newComment)"
|
|
7047
|
-
></div>
|
|
7287
|
+
[innerHTML]="renderMarkdown(newComment)"></div>
|
|
7048
7288
|
}
|
|
7049
7289
|
|
|
7050
7290
|
@if (mentionSuggestions.length > 0) {
|
|
@@ -7059,10 +7299,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7059
7299
|
<div class="flex flex-col gap-3">
|
|
7060
7300
|
@for (candidate of mentionSuggestions; track candidate.userId) {
|
|
7061
7301
|
<button
|
|
7062
|
-
type="button"
|
|
7063
7302
|
class="flex w-full items-center justify-between gap-4 rounded-xl border border-transparent px-3 py-3 text-left transition hover:border-primary-200 hover:bg-primary-50 dark:hover:border-primary-800 dark:hover:bg-primary-950/30"
|
|
7064
|
-
|
|
7065
|
-
|
|
7303
|
+
type="button"
|
|
7304
|
+
(click)="insertMention(candidate)">
|
|
7066
7305
|
<div class="min-w-0">
|
|
7067
7306
|
<strong>{{ candidate.displayName }}</strong>
|
|
7068
7307
|
<small class="mt-1 block text-surface-500">{{ candidate.email }}</small>
|
|
@@ -7082,15 +7321,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7082
7321
|
<div class="inline-flex items-center gap-2">
|
|
7083
7322
|
<i class="pi pi-file"></i>
|
|
7084
7323
|
<span class="break-all">{{ file.name }}</span>
|
|
7085
|
-
<p-tag [value]="formatBytes(file.size)"
|
|
7324
|
+
<p-tag severity="contrast" [value]="formatBytes(file.size)" />
|
|
7086
7325
|
</div>
|
|
7087
7326
|
<p-button
|
|
7088
7327
|
icon="pi pi-times"
|
|
7089
7328
|
severity="danger"
|
|
7090
7329
|
[rounded]="true"
|
|
7091
7330
|
[text]="true"
|
|
7092
|
-
(onClick)="removePendingFile(file)"
|
|
7093
|
-
/>
|
|
7331
|
+
(onClick)="removePendingFile(file)" />
|
|
7094
7332
|
</div>
|
|
7095
7333
|
}
|
|
7096
7334
|
</div>
|
|
@@ -7098,33 +7336,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7098
7336
|
|
|
7099
7337
|
<div class="flex flex-col gap-2 sm:flex-row sm:justify-end">
|
|
7100
7338
|
<p-button
|
|
7339
|
+
severity="secondary"
|
|
7340
|
+
[icon]="previewMode ? 'pi pi-pencil' : 'pi pi-eye'"
|
|
7101
7341
|
[label]="
|
|
7102
|
-
previewMode
|
|
7103
|
-
? ('discussionComponent.edit' | translate)
|
|
7104
|
-
: ('discussionComponent.preview' | translate)
|
|
7342
|
+
previewMode ? ('discussionComponent.edit' | translate) : ('discussionComponent.preview' | translate)
|
|
7105
7343
|
"
|
|
7106
|
-
[icon]="previewMode ? 'pi pi-pencil' : 'pi pi-eye'"
|
|
7107
|
-
severity="secondary"
|
|
7108
7344
|
[text]="true"
|
|
7109
|
-
(onClick)="previewMode = !previewMode"
|
|
7110
|
-
/>
|
|
7345
|
+
(onClick)="previewMode = !previewMode" />
|
|
7111
7346
|
|
|
7112
7347
|
<label class="file-trigger">
|
|
7113
7348
|
<p-button
|
|
7114
|
-
[label]="'discussionComponent.attachFiles' | translate"
|
|
7115
7349
|
icon="pi pi-paperclip"
|
|
7116
7350
|
severity="secondary"
|
|
7117
|
-
[
|
|
7118
|
-
|
|
7119
|
-
<input type="file"
|
|
7351
|
+
[label]="'discussionComponent.attachFiles' | translate"
|
|
7352
|
+
[text]="true" />
|
|
7353
|
+
<input multiple type="file" (change)="onFilesSelected($event)" />
|
|
7120
7354
|
</label>
|
|
7121
7355
|
<p-button
|
|
7122
|
-
[label]="'discussionComponent.send' | translate"
|
|
7123
7356
|
icon="pi pi-send"
|
|
7124
|
-
[loading]="submitting"
|
|
7125
7357
|
[disabled]="submitting || !newComment.trim()"
|
|
7126
|
-
|
|
7127
|
-
|
|
7358
|
+
[label]="'discussionComponent.send' | translate"
|
|
7359
|
+
[loading]="submitting"
|
|
7360
|
+
(onClick)="createComment()" />
|
|
7128
7361
|
</div>
|
|
7129
7362
|
</div>
|
|
7130
7363
|
</p-card>
|
|
@@ -7132,7 +7365,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7132
7365
|
@if (loading) {
|
|
7133
7366
|
<div
|
|
7134
7367
|
class="flex min-h-20 flex-col items-center justify-center gap-3 rounded-2xl border border-surface-200 px-4 py-5 text-surface-500 dark:border-surface-700">
|
|
7135
|
-
<p-progressSpinner strokeWidth="4"/>
|
|
7368
|
+
<p-progressSpinner strokeWidth="4" />
|
|
7136
7369
|
<span>{{ 'discussionComponent.loadingComments' | translate }}</span>
|
|
7137
7370
|
</div>
|
|
7138
7371
|
} @else if (comments.length === 0) {
|
|
@@ -7148,24 +7381,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7148
7381
|
<ng-template pTemplate="content">
|
|
7149
7382
|
<div class="grid gap-4 md:grid-cols-[3.2rem_minmax(0,1fr)]">
|
|
7150
7383
|
<div>
|
|
7151
|
-
<p-avatar
|
|
7152
|
-
[label]="getInitialsFromString(comment.authorDisplayName)"
|
|
7153
|
-
shape="circle"
|
|
7154
|
-
/>
|
|
7384
|
+
<p-avatar shape="circle" [label]="getInitialsFromString(comment.authorDisplayName)" />
|
|
7155
7385
|
</div>
|
|
7156
7386
|
|
|
7157
7387
|
<div class="flex flex-col gap-2">
|
|
7158
7388
|
<div class="flex flex-row gap-3 justify-between">
|
|
7159
7389
|
<div class="flex flex-wrap items-center gap-2">
|
|
7160
7390
|
<strong>{{ comment.authorDisplayName }}</strong>
|
|
7161
|
-
<span
|
|
7162
|
-
|
|
7391
|
+
<span class="text-sm text-surface-500">{{
|
|
7392
|
+
comment.createdAt | date: layoutService.dateTimeFormat()
|
|
7393
|
+
}}</span>
|
|
7163
7394
|
</div>
|
|
7164
7395
|
|
|
7165
7396
|
<div class="flex flex-wrap items-center justify-end gap-2">
|
|
7166
7397
|
<div class="flex flex-wrap items-center">
|
|
7167
7398
|
@if (comment.isEdited) {
|
|
7168
|
-
<p-tag
|
|
7399
|
+
<p-tag
|
|
7400
|
+
icon="pi pi-pencil"
|
|
7401
|
+
severity="warn"
|
|
7402
|
+
[value]="'discussionComponent.edited' | translate" />
|
|
7169
7403
|
}
|
|
7170
7404
|
</div>
|
|
7171
7405
|
@if (comment.canEdit) {
|
|
@@ -7174,8 +7408,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7174
7408
|
severity="secondary"
|
|
7175
7409
|
[rounded]="true"
|
|
7176
7410
|
[text]="true"
|
|
7177
|
-
(onClick)="startEdit(comment)"
|
|
7178
|
-
/>
|
|
7411
|
+
(onClick)="startEdit(comment)" />
|
|
7179
7412
|
}
|
|
7180
7413
|
@if (comment.historyCount > 0) {
|
|
7181
7414
|
<p-button
|
|
@@ -7183,8 +7416,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7183
7416
|
severity="secondary"
|
|
7184
7417
|
[rounded]="true"
|
|
7185
7418
|
[text]="true"
|
|
7186
|
-
(onClick)="toggleHistory(comment)"
|
|
7187
|
-
/>
|
|
7419
|
+
(onClick)="toggleHistory(comment)" />
|
|
7188
7420
|
}
|
|
7189
7421
|
@if (comment.canDelete) {
|
|
7190
7422
|
<p-button
|
|
@@ -7192,47 +7424,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7192
7424
|
severity="danger"
|
|
7193
7425
|
[rounded]="true"
|
|
7194
7426
|
[text]="true"
|
|
7195
|
-
(onClick)="deleteComment(comment)"
|
|
7196
|
-
/>
|
|
7427
|
+
(onClick)="deleteComment(comment)" />
|
|
7197
7428
|
}
|
|
7198
7429
|
</div>
|
|
7199
7430
|
</div>
|
|
7200
7431
|
@if (editingCommentId === comment.commentId) {
|
|
7201
7432
|
<div class="flex flex-col gap-4">
|
|
7202
7433
|
<textarea
|
|
7203
|
-
pTextarea
|
|
7204
7434
|
class="min-h-24 w-full"
|
|
7205
|
-
|
|
7435
|
+
pTextarea
|
|
7206
7436
|
rows="4"
|
|
7207
|
-
[
|
|
7437
|
+
[autoResize]="true"
|
|
7208
7438
|
[placeholder]="'discussionComponent.editCommentPlaceholder' | translate"
|
|
7209
|
-
|
|
7439
|
+
[(ngModel)]="editContent"></textarea>
|
|
7210
7440
|
<div class="flex flex-col gap-2 sm:flex-row sm:justify-end">
|
|
7211
7441
|
<div>
|
|
7212
7442
|
<label class="file-trigger">
|
|
7213
7443
|
<p-button
|
|
7214
|
-
[label]="'discussionComponent.addAttachment' | translate"
|
|
7215
7444
|
icon="pi pi-paperclip"
|
|
7216
|
-
[text]="true"
|
|
7217
7445
|
severity="secondary"
|
|
7218
|
-
|
|
7219
|
-
|
|
7446
|
+
[label]="'discussionComponent.addAttachment' | translate"
|
|
7447
|
+
[text]="true" />
|
|
7448
|
+
<input multiple type="file" (change)="onInlineFilesSelected(comment, $event)" />
|
|
7220
7449
|
</label>
|
|
7221
7450
|
</div>
|
|
7222
7451
|
|
|
7223
7452
|
<p-button
|
|
7224
|
-
[label]="'discussionComponent.save' | translate"
|
|
7225
7453
|
icon="pi pi-check"
|
|
7226
7454
|
[disabled]="!editContent.trim()"
|
|
7227
|
-
|
|
7228
|
-
|
|
7455
|
+
[label]="'discussionComponent.save' | translate"
|
|
7456
|
+
(onClick)="saveEdit(comment)" />
|
|
7229
7457
|
<p-button
|
|
7230
|
-
[label]="'discussionComponent.cancel' | translate"
|
|
7231
7458
|
icon="pi pi-times"
|
|
7232
7459
|
severity="secondary"
|
|
7460
|
+
[label]="'discussionComponent.cancel' | translate"
|
|
7233
7461
|
[text]="true"
|
|
7234
|
-
(onClick)="cancelEdit()"
|
|
7235
|
-
/>
|
|
7462
|
+
(onClick)="cancelEdit()" />
|
|
7236
7463
|
</div>
|
|
7237
7464
|
</div>
|
|
7238
7465
|
} @else {
|
|
@@ -7247,13 +7474,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7247
7474
|
<div class="inline-flex items-center gap-2">
|
|
7248
7475
|
<i class="pi pi-file"></i>
|
|
7249
7476
|
<button
|
|
7250
|
-
type="button"
|
|
7251
7477
|
class="break-all bg-transparent p-0 text-left font-semibold text-primary-600 transition hover:text-primary-500"
|
|
7252
|
-
|
|
7253
|
-
|
|
7478
|
+
type="button"
|
|
7479
|
+
(click)="downloadAttachment(attachment)">
|
|
7254
7480
|
{{ attachment.fileName }}
|
|
7255
7481
|
</button>
|
|
7256
|
-
<p-tag [value]="formatBytes(attachment.fileSize)"
|
|
7482
|
+
<p-tag severity="contrast" [value]="formatBytes(attachment.fileSize)" />
|
|
7257
7483
|
</div>
|
|
7258
7484
|
|
|
7259
7485
|
@if (comment.canEdit) {
|
|
@@ -7262,8 +7488,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7262
7488
|
severity="danger"
|
|
7263
7489
|
[rounded]="true"
|
|
7264
7490
|
[text]="true"
|
|
7265
|
-
(onClick)="deleteAttachment(comment, attachment)"
|
|
7266
|
-
/>
|
|
7491
|
+
(onClick)="deleteAttachment(comment, attachment)" />
|
|
7267
7492
|
}
|
|
7268
7493
|
</div>
|
|
7269
7494
|
}
|
|
@@ -7274,11 +7499,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7274
7499
|
<div class="flex flex-wrap items-center gap-2">
|
|
7275
7500
|
@for (reaction of getReactions(comment); track reaction.emojiCode) {
|
|
7276
7501
|
<p-button
|
|
7277
|
-
[label]="reaction.emojiCode + ' ' + reaction.count"
|
|
7278
7502
|
severity="secondary"
|
|
7503
|
+
[label]="reaction.emojiCode + ' ' + reaction.count"
|
|
7279
7504
|
[outlined]="false"
|
|
7280
|
-
(onClick)="toggleReaction(comment, reaction)"
|
|
7281
|
-
/>
|
|
7505
|
+
(onClick)="toggleReaction(comment, reaction)" />
|
|
7282
7506
|
}
|
|
7283
7507
|
|
|
7284
7508
|
@if (!hasUserReaction(comment)) {
|
|
@@ -7287,16 +7511,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7287
7511
|
severity="secondary"
|
|
7288
7512
|
[rounded]="true"
|
|
7289
7513
|
[text]="true"
|
|
7290
|
-
(onClick)="reactionPopover.toggle($event)"
|
|
7291
|
-
/>
|
|
7514
|
+
(onClick)="reactionPopover.toggle($event)" />
|
|
7292
7515
|
<p-popover #reactionPopover>
|
|
7293
7516
|
<div class="emoji-popover">
|
|
7294
7517
|
@for (emoji of emojiPalette; track emoji) {
|
|
7295
7518
|
<button
|
|
7296
|
-
type="button"
|
|
7297
7519
|
class="emoji-option"
|
|
7298
|
-
|
|
7299
|
-
|
|
7520
|
+
type="button"
|
|
7521
|
+
(click)="reactWithEmoji(comment, emoji, reactionPopover)">
|
|
7300
7522
|
{{ emoji }}
|
|
7301
7523
|
</button>
|
|
7302
7524
|
}
|
|
@@ -7306,7 +7528,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7306
7528
|
</div>
|
|
7307
7529
|
|
|
7308
7530
|
@if (historyByComment[comment.commentId]?.opened) {
|
|
7309
|
-
<p-panel class="block" [
|
|
7531
|
+
<p-panel class="block" [collapsed]="false" [toggleable]="true">
|
|
7310
7532
|
<ng-template pTemplate="header">
|
|
7311
7533
|
<div class="inline-flex items-center gap-2 text-sm font-medium">
|
|
7312
7534
|
<i class="pi pi-history"></i>
|
|
@@ -7316,12 +7538,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7316
7538
|
|
|
7317
7539
|
@if (historyByComment[comment.commentId]?.loading) {
|
|
7318
7540
|
<div class="flex items-center gap-3 text-surface-500">
|
|
7319
|
-
<p-progressSpinner strokeWidth="4"/>
|
|
7541
|
+
<p-progressSpinner strokeWidth="4" />
|
|
7320
7542
|
<span>{{ 'discussionComponent.loadingHistory' | translate }}</span>
|
|
7321
7543
|
</div>
|
|
7322
7544
|
} @else {
|
|
7323
7545
|
<div class="flex flex-col gap-4">
|
|
7324
|
-
@for (
|
|
7546
|
+
@for (
|
|
7547
|
+
item of historyByComment[comment.commentId]?.items ?? [];
|
|
7548
|
+
track item.commentEditHistoryId
|
|
7549
|
+
) {
|
|
7325
7550
|
<div class="rounded-2xl border border-surface-200 px-4 py-4 dark:border-surface-700">
|
|
7326
7551
|
<div class="mb-3 inline-flex items-center gap-2 text-sm font-semibold">
|
|
7327
7552
|
<i class="pi pi-clock"></i>
|
|
@@ -7329,18 +7554,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7329
7554
|
</div>
|
|
7330
7555
|
<div class="grid gap-4 lg:grid-cols-2">
|
|
7331
7556
|
<div class="flex flex-col gap-2">
|
|
7332
|
-
<p-tag [value]="'discussionComponent.before' | translate"
|
|
7557
|
+
<p-tag severity="secondary" [value]="'discussionComponent.before' | translate" />
|
|
7333
7558
|
<div
|
|
7334
7559
|
class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
|
|
7335
|
-
[innerHTML]="renderMarkdown(item.oldContent)"
|
|
7336
|
-
></div>
|
|
7560
|
+
[innerHTML]="renderMarkdown(item.oldContent)"></div>
|
|
7337
7561
|
</div>
|
|
7338
7562
|
<div class="flex flex-col gap-2">
|
|
7339
|
-
<p-tag [value]="'discussionComponent.after' | translate"
|
|
7563
|
+
<p-tag severity="success" [value]="'discussionComponent.after' | translate" />
|
|
7340
7564
|
<div
|
|
7341
7565
|
class="history-markdown rounded-2xl bg-surface-50 px-4 py-3 leading-7 dark:bg-surface-900/40"
|
|
7342
|
-
[innerHTML]="renderMarkdown(item.newContent)"
|
|
7343
|
-
></div>
|
|
7566
|
+
[innerHTML]="renderMarkdown(item.newContent)"></div>
|
|
7344
7567
|
</div>
|
|
7345
7568
|
</div>
|
|
7346
7569
|
</div>
|
|
@@ -7445,7 +7668,7 @@ class IframeModuleComponent extends BaseModuleComponent {
|
|
|
7445
7668
|
placeholder="{{ 'iframe-module.iframeModule.urlPlaceholder' | translate }}"
|
|
7446
7669
|
qa-id="iframe-module-settings-site-url-input"
|
|
7447
7670
|
type="text"
|
|
7448
|
-
[(ngModel)]="settings.url"/>
|
|
7671
|
+
[(ngModel)]="settings.url" />
|
|
7449
7672
|
</div>
|
|
7450
7673
|
<div class="flex justify-end">
|
|
7451
7674
|
<p-button
|
|
@@ -7459,7 +7682,7 @@ class IframeModuleComponent extends BaseModuleComponent {
|
|
|
7459
7682
|
</div>
|
|
7460
7683
|
</div>
|
|
7461
7684
|
} @else if (isSecurity) {
|
|
7462
|
-
<security [controller]="controller" [id]="id"/>
|
|
7685
|
+
<security [controller]="controller" [id]="id" />
|
|
7463
7686
|
}
|
|
7464
7687
|
`, isInline: true, dependencies: [{ kind: "component", type: SecurityComponent, selector: "security", inputs: ["id", "controller"] }, { kind: "directive", type: InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { 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: "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: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
7465
7688
|
}
|
|
@@ -7489,7 +7712,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7489
7712
|
placeholder="{{ 'iframe-module.iframeModule.urlPlaceholder' | translate }}"
|
|
7490
7713
|
qa-id="iframe-module-settings-site-url-input"
|
|
7491
7714
|
type="text"
|
|
7492
|
-
[(ngModel)]="settings.url"/>
|
|
7715
|
+
[(ngModel)]="settings.url" />
|
|
7493
7716
|
</div>
|
|
7494
7717
|
<div class="flex justify-end">
|
|
7495
7718
|
<p-button
|
|
@@ -7503,7 +7726,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7503
7726
|
</div>
|
|
7504
7727
|
</div>
|
|
7505
7728
|
} @else if (isSecurity) {
|
|
7506
|
-
<security [controller]="controller" [id]="id"/>
|
|
7729
|
+
<security [controller]="controller" [id]="id" />
|
|
7507
7730
|
}
|
|
7508
7731
|
`
|
|
7509
7732
|
}]
|
|
@@ -7512,6 +7735,563 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7512
7735
|
args: ['iframe']
|
|
7513
7736
|
}] } });
|
|
7514
7737
|
|
|
7738
|
+
const OIP_EXTENSION_EVENTS = {
|
|
7739
|
+
contextChange: 'oip:context-change',
|
|
7740
|
+
titleChange: 'oip:title-change',
|
|
7741
|
+
settingsChange: 'oip:settings-change',
|
|
7742
|
+
notify: 'oip:notify',
|
|
7743
|
+
navigate: 'oip:navigate',
|
|
7744
|
+
error: 'oip:error'
|
|
7745
|
+
};
|
|
7746
|
+
function emitOipTitleChange(element, title) {
|
|
7747
|
+
element.dispatchEvent(new CustomEvent(OIP_EXTENSION_EVENTS.titleChange, { detail: title, bubbles: true }));
|
|
7748
|
+
}
|
|
7749
|
+
function emitOipSettingsChange(element, settings) {
|
|
7750
|
+
element.dispatchEvent(new CustomEvent(OIP_EXTENSION_EVENTS.settingsChange, { detail: settings, bubbles: true }));
|
|
7751
|
+
}
|
|
7752
|
+
function emitOipNotify(element, notification) {
|
|
7753
|
+
element.dispatchEvent(new CustomEvent(OIP_EXTENSION_EVENTS.notify, { detail: notification, bubbles: true }));
|
|
7754
|
+
}
|
|
7755
|
+
function emitOipNavigate(element, navigation) {
|
|
7756
|
+
element.dispatchEvent(new CustomEvent(OIP_EXTENSION_EVENTS.navigate, { detail: navigation, bubbles: true }));
|
|
7757
|
+
}
|
|
7758
|
+
function emitOipError(element, error) {
|
|
7759
|
+
element.dispatchEvent(new CustomEvent(OIP_EXTENSION_EVENTS.error, { detail: error, bubbles: true }));
|
|
7760
|
+
}
|
|
7761
|
+
function emitOipContextChange(element, context) {
|
|
7762
|
+
element.dispatchEvent(new CustomEvent(OIP_EXTENSION_EVENTS.contextChange, { detail: context }));
|
|
7763
|
+
}
|
|
7764
|
+
|
|
7765
|
+
class ExtensionLoaderService {
|
|
7766
|
+
constructor() {
|
|
7767
|
+
this.loadedScripts = new Map();
|
|
7768
|
+
}
|
|
7769
|
+
loadScript(scriptUrl) {
|
|
7770
|
+
const existing = this.loadedScripts.get(scriptUrl);
|
|
7771
|
+
if (existing) {
|
|
7772
|
+
return existing;
|
|
7773
|
+
}
|
|
7774
|
+
const loadPromise = new Promise((resolve, reject) => {
|
|
7775
|
+
const script = document.createElement('script');
|
|
7776
|
+
script.type = 'module';
|
|
7777
|
+
script.src = scriptUrl;
|
|
7778
|
+
script.async = true;
|
|
7779
|
+
script.onload = () => resolve();
|
|
7780
|
+
script.onerror = () => {
|
|
7781
|
+
this.loadedScripts.delete(scriptUrl);
|
|
7782
|
+
reject(new Error(`Extension script could not be loaded: ${scriptUrl}`));
|
|
7783
|
+
};
|
|
7784
|
+
document.head.appendChild(script);
|
|
7785
|
+
});
|
|
7786
|
+
this.loadedScripts.set(scriptUrl, loadPromise);
|
|
7787
|
+
return loadPromise;
|
|
7788
|
+
}
|
|
7789
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
7790
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionLoaderService, providedIn: 'root' }); }
|
|
7791
|
+
}
|
|
7792
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionLoaderService, decorators: [{
|
|
7793
|
+
type: Injectable,
|
|
7794
|
+
args: [{ providedIn: 'root' }]
|
|
7795
|
+
}] });
|
|
7796
|
+
|
|
7797
|
+
class CustomElementExtensionModuleHostComponent extends BaseModuleComponent {
|
|
7798
|
+
set extensionContainer(element) {
|
|
7799
|
+
this.container = element;
|
|
7800
|
+
this.queueRenderExtension();
|
|
7801
|
+
}
|
|
7802
|
+
get showContent() {
|
|
7803
|
+
return this.isActiveTab('content');
|
|
7804
|
+
}
|
|
7805
|
+
get showSettings() {
|
|
7806
|
+
return this.isActiveTab('settings');
|
|
7807
|
+
}
|
|
7808
|
+
get showSecurity() {
|
|
7809
|
+
return this.isActiveTab('security');
|
|
7810
|
+
}
|
|
7811
|
+
get extensionKey() {
|
|
7812
|
+
return this.route.snapshot.paramMap.get('extensionKey') ?? '';
|
|
7813
|
+
}
|
|
7814
|
+
constructor() {
|
|
7815
|
+
super();
|
|
7816
|
+
this.extensionLoader = inject(ExtensionLoaderService);
|
|
7817
|
+
this.router = inject(Router);
|
|
7818
|
+
this.hostChangeDetectorRef = inject(ChangeDetectorRef);
|
|
7819
|
+
this.extensionModulesApi = inject(ExtensionModulesApi);
|
|
7820
|
+
this.removeListeners = [];
|
|
7821
|
+
this.renderQueued = false;
|
|
7822
|
+
this.activeTabSyncQueued = false;
|
|
7823
|
+
this.activeTabId = this.getCurrentActiveTabId();
|
|
7824
|
+
this.destroyed = false;
|
|
7825
|
+
this.loadError = null;
|
|
7826
|
+
this.subscriptions.push(this.topBarService.activeId$.subscribe(() => {
|
|
7827
|
+
this.queueActiveTabSync();
|
|
7828
|
+
}));
|
|
7829
|
+
}
|
|
7830
|
+
async onModuleInstanceChange() {
|
|
7831
|
+
await this.loadExtensionMetadata();
|
|
7832
|
+
await this.renderExtension();
|
|
7833
|
+
}
|
|
7834
|
+
onSecurityRightsChange() {
|
|
7835
|
+
this.updateExtensionContext();
|
|
7836
|
+
}
|
|
7837
|
+
ngOnDestroy() {
|
|
7838
|
+
this.destroyed = true;
|
|
7839
|
+
this.destroyExtensionElement();
|
|
7840
|
+
super.ngOnDestroy();
|
|
7841
|
+
}
|
|
7842
|
+
async reloadExtension() {
|
|
7843
|
+
this.loadError = null;
|
|
7844
|
+
this.extensionMetadata = undefined;
|
|
7845
|
+
await this.loadExtensionMetadata();
|
|
7846
|
+
await this.renderExtension();
|
|
7847
|
+
}
|
|
7848
|
+
async loadExtensionMetadata() {
|
|
7849
|
+
if (this.extensionMetadata) {
|
|
7850
|
+
return;
|
|
7851
|
+
}
|
|
7852
|
+
if (!this.extensionKey) {
|
|
7853
|
+
this.loadError = 'Extension key is missing.';
|
|
7854
|
+
return;
|
|
7855
|
+
}
|
|
7856
|
+
this.extensionMetadata = (await this.extensionModulesApi.getExtensionModuleByKey({
|
|
7857
|
+
extensionKey: this.extensionKey
|
|
7858
|
+
}));
|
|
7859
|
+
await this.loadExtensionTranslations(this.extensionMetadata);
|
|
7860
|
+
}
|
|
7861
|
+
async renderExtension() {
|
|
7862
|
+
if (this.destroyed || !this.container || !this.extensionMetadata || !this.showContent) {
|
|
7863
|
+
return;
|
|
7864
|
+
}
|
|
7865
|
+
try {
|
|
7866
|
+
this.loadError = null;
|
|
7867
|
+
this.destroyExtensionElement();
|
|
7868
|
+
await this.renderCustomElementExtension(this.extensionMetadata);
|
|
7869
|
+
}
|
|
7870
|
+
catch (error) {
|
|
7871
|
+
this.loadError = error instanceof Error ? error.message : 'Extension could not be loaded.';
|
|
7872
|
+
this.msgService.error(error);
|
|
7873
|
+
}
|
|
7874
|
+
}
|
|
7875
|
+
queueRenderExtension() {
|
|
7876
|
+
if (this.renderQueued) {
|
|
7877
|
+
return;
|
|
7878
|
+
}
|
|
7879
|
+
this.renderQueued = true;
|
|
7880
|
+
queueMicrotask(() => {
|
|
7881
|
+
this.renderQueued = false;
|
|
7882
|
+
void this.renderExtension();
|
|
7883
|
+
});
|
|
7884
|
+
}
|
|
7885
|
+
isActiveTab(id) {
|
|
7886
|
+
return this.activeTabId === id;
|
|
7887
|
+
}
|
|
7888
|
+
queueActiveTabSync() {
|
|
7889
|
+
const nextActiveTabId = this.getCurrentActiveTabId();
|
|
7890
|
+
if (this.activeTabId === nextActiveTabId || this.activeTabSyncQueued) {
|
|
7891
|
+
return;
|
|
7892
|
+
}
|
|
7893
|
+
this.activeTabSyncQueued = true;
|
|
7894
|
+
queueMicrotask(() => {
|
|
7895
|
+
this.activeTabSyncQueued = false;
|
|
7896
|
+
if (this.destroyed) {
|
|
7897
|
+
return;
|
|
7898
|
+
}
|
|
7899
|
+
this.activeTabId = this.getCurrentActiveTabId();
|
|
7900
|
+
this.hostChangeDetectorRef.detectChanges();
|
|
7901
|
+
if (this.showContent) {
|
|
7902
|
+
this.queueRenderExtension();
|
|
7903
|
+
}
|
|
7904
|
+
else {
|
|
7905
|
+
this.destroyExtensionElement();
|
|
7906
|
+
}
|
|
7907
|
+
});
|
|
7908
|
+
}
|
|
7909
|
+
getCurrentActiveTabId() {
|
|
7910
|
+
return this.topBarService.activeTopBarItem?.id ?? 'content';
|
|
7911
|
+
}
|
|
7912
|
+
updateExtensionContext() {
|
|
7913
|
+
if (!this.extensionElement || !this.extensionMetadata?.extensionKey) {
|
|
7914
|
+
return;
|
|
7915
|
+
}
|
|
7916
|
+
const context = {
|
|
7917
|
+
moduleInstanceId: this.id,
|
|
7918
|
+
extensionKey: this.extensionMetadata.extensionKey,
|
|
7919
|
+
apiBasePath: this.buildUrl(`api/extensions/${this.extensionMetadata.extensionKey}`),
|
|
7920
|
+
settings: this.settings,
|
|
7921
|
+
locale: this.layoutService.language(),
|
|
7922
|
+
theme: this.layoutService.layoutConfig(),
|
|
7923
|
+
user: this.securityService.getCurrentUser(),
|
|
7924
|
+
activeTabId: this.topBarService.activeId ?? 'content',
|
|
7925
|
+
permissions: {
|
|
7926
|
+
canRead: this.canRead,
|
|
7927
|
+
canEdit: this.canEdit,
|
|
7928
|
+
canDelete: this.canDelete
|
|
7929
|
+
}
|
|
7930
|
+
};
|
|
7931
|
+
Object.assign(this.extensionElement, { oipContext: context });
|
|
7932
|
+
emitOipContextChange(this.extensionElement, context);
|
|
7933
|
+
}
|
|
7934
|
+
attachListeners(element) {
|
|
7935
|
+
this.addListener(element, OIP_EXTENSION_EVENTS.titleChange, (event) => {
|
|
7936
|
+
const title = event.detail;
|
|
7937
|
+
if (title) {
|
|
7938
|
+
this.appTitleService.setTitle(title);
|
|
7939
|
+
}
|
|
7940
|
+
});
|
|
7941
|
+
this.addListener(element, OIP_EXTENSION_EVENTS.settingsChange, (event) => {
|
|
7942
|
+
this.settings = event.detail;
|
|
7943
|
+
void this.saveSettings(this.settings);
|
|
7944
|
+
});
|
|
7945
|
+
this.addListener(element, OIP_EXTENSION_EVENTS.notify, (event) => {
|
|
7946
|
+
const detail = event.detail;
|
|
7947
|
+
const severity = detail?.severity ?? 'info';
|
|
7948
|
+
const message = detail?.detail ?? detail?.summary ?? '';
|
|
7949
|
+
switch (severity) {
|
|
7950
|
+
case 'success':
|
|
7951
|
+
this.msgService.success(message, detail?.summary);
|
|
7952
|
+
break;
|
|
7953
|
+
case 'warn':
|
|
7954
|
+
this.msgService.warn(message, detail?.summary);
|
|
7955
|
+
break;
|
|
7956
|
+
case 'error':
|
|
7957
|
+
this.msgService.error(message, detail?.summary);
|
|
7958
|
+
break;
|
|
7959
|
+
default:
|
|
7960
|
+
this.msgService.info(message, detail?.summary);
|
|
7961
|
+
}
|
|
7962
|
+
});
|
|
7963
|
+
this.addListener(element, OIP_EXTENSION_EVENTS.navigate, (event) => {
|
|
7964
|
+
const detail = event.detail;
|
|
7965
|
+
if (detail?.commands) {
|
|
7966
|
+
void this.router.navigate(detail.commands);
|
|
7967
|
+
}
|
|
7968
|
+
else if (detail?.url) {
|
|
7969
|
+
void this.router.navigateByUrl(detail.url);
|
|
7970
|
+
}
|
|
7971
|
+
});
|
|
7972
|
+
this.addListener(element, OIP_EXTENSION_EVENTS.error, (event) => {
|
|
7973
|
+
this.msgService.error(event.detail);
|
|
7974
|
+
});
|
|
7975
|
+
}
|
|
7976
|
+
buildUrl(path) {
|
|
7977
|
+
const baseUrl = document.getElementsByTagName('base')[0]?.href ?? `${window.location.origin}/`;
|
|
7978
|
+
return `${baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`}${path}`;
|
|
7979
|
+
}
|
|
7980
|
+
async loadExtensionTranslations(metadata) {
|
|
7981
|
+
const extensionKey = metadata.extensionKey ?? this.extensionKey;
|
|
7982
|
+
const apiBaseUrl = metadata.apiBaseUrl;
|
|
7983
|
+
if (!extensionKey || !apiBaseUrl) {
|
|
7984
|
+
return;
|
|
7985
|
+
}
|
|
7986
|
+
const lang = this.translateService.currentLang || this.layoutService.language() || 'en';
|
|
7987
|
+
const url = this.buildExtensionI18nUrl(apiBaseUrl, extensionKey, lang);
|
|
7988
|
+
try {
|
|
7989
|
+
await firstValueFrom(this.l10nService.loadTranslationsFromUrl(extensionKey, url, lang));
|
|
7990
|
+
}
|
|
7991
|
+
catch (error) {
|
|
7992
|
+
console.error(`No translations found for extension ${extensionKey}.${lang}.json`, error);
|
|
7993
|
+
}
|
|
7994
|
+
}
|
|
7995
|
+
buildExtensionI18nUrl(apiBaseUrl, extensionKey, lang) {
|
|
7996
|
+
return `${apiBaseUrl.replace(/\/+$/, '')}/assets/i18n/${encodeURIComponent(extensionKey)}.${encodeURIComponent(lang)}.json`;
|
|
7997
|
+
}
|
|
7998
|
+
addListener(element, eventName, listener) {
|
|
7999
|
+
element.addEventListener(eventName, listener);
|
|
8000
|
+
this.removeListeners.push(() => element.removeEventListener(eventName, listener));
|
|
8001
|
+
}
|
|
8002
|
+
destroyExtensionElement() {
|
|
8003
|
+
this.removeListeners.forEach((remove) => remove());
|
|
8004
|
+
this.removeListeners = [];
|
|
8005
|
+
this.extensionElement?.remove();
|
|
8006
|
+
this.extensionElement = undefined;
|
|
8007
|
+
}
|
|
8008
|
+
async renderCustomElementExtension(metadata) {
|
|
8009
|
+
const { elementName, scriptUrl } = metadata;
|
|
8010
|
+
if (!this.container || !elementName || !scriptUrl) {
|
|
8011
|
+
this.loadError = 'Custom Element extension metadata is incomplete.';
|
|
8012
|
+
return;
|
|
8013
|
+
}
|
|
8014
|
+
await this.extensionLoader.loadScript(scriptUrl);
|
|
8015
|
+
await customElements.whenDefined(elementName);
|
|
8016
|
+
const element = document.createElement(elementName);
|
|
8017
|
+
this.extensionElement = element;
|
|
8018
|
+
this.attachListeners(element);
|
|
8019
|
+
this.container.nativeElement.appendChild(element);
|
|
8020
|
+
this.updateExtensionContext();
|
|
8021
|
+
}
|
|
8022
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CustomElementExtensionModuleHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8023
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: CustomElementExtensionModuleHostComponent, isStandalone: true, selector: "ng-component", providers: [ExtensionModulesApi], viewQueries: [{ propertyName: "extensionContainer", first: true, predicate: ["extensionContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
8024
|
+
@if (showContent) {
|
|
8025
|
+
<div class="min-h-[calc(100vh-10rem)] w-full">
|
|
8026
|
+
@if (loadError) {
|
|
8027
|
+
<div class="card flex flex-col gap-4">
|
|
8028
|
+
<div class="font-semibold text-xl">{{ loadError }}</div>
|
|
8029
|
+
<p-button icon="pi pi-refresh" label="Retry" (onClick)="reloadExtension()"></p-button>
|
|
8030
|
+
</div>
|
|
8031
|
+
} @else {
|
|
8032
|
+
<div #extensionContainer class="w-full"></div>
|
|
8033
|
+
}
|
|
8034
|
+
</div>
|
|
8035
|
+
} @else if (showSettings) {
|
|
8036
|
+
<div class="flex flex-col md:flex-row gap-8">
|
|
8037
|
+
<div class="md:w-1/2">
|
|
8038
|
+
<div class="card flex flex-col gap-4">
|
|
8039
|
+
<div class="font-semibold text-xl">{{ 'baseComponent.settings' | translate }}</div>
|
|
8040
|
+
<p-button icon="pi pi-save" label="Save" (onClick)="saveSettings(settings)"></p-button>
|
|
8041
|
+
</div>
|
|
8042
|
+
</div>
|
|
8043
|
+
</div>
|
|
8044
|
+
} @else if (showSecurity) {
|
|
8045
|
+
<security [controller]="controller" [id]="id" />
|
|
8046
|
+
}
|
|
8047
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SecurityComponent, selector: "security", inputs: ["id", "controller"] }, { 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: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
8048
|
+
}
|
|
8049
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: CustomElementExtensionModuleHostComponent, decorators: [{
|
|
8050
|
+
type: Component,
|
|
8051
|
+
args: [{
|
|
8052
|
+
standalone: true,
|
|
8053
|
+
imports: [CommonModule, SecurityComponent, TranslatePipe, Button],
|
|
8054
|
+
providers: [ExtensionModulesApi],
|
|
8055
|
+
template: `
|
|
8056
|
+
@if (showContent) {
|
|
8057
|
+
<div class="min-h-[calc(100vh-10rem)] w-full">
|
|
8058
|
+
@if (loadError) {
|
|
8059
|
+
<div class="card flex flex-col gap-4">
|
|
8060
|
+
<div class="font-semibold text-xl">{{ loadError }}</div>
|
|
8061
|
+
<p-button icon="pi pi-refresh" label="Retry" (onClick)="reloadExtension()"></p-button>
|
|
8062
|
+
</div>
|
|
8063
|
+
} @else {
|
|
8064
|
+
<div #extensionContainer class="w-full"></div>
|
|
8065
|
+
}
|
|
8066
|
+
</div>
|
|
8067
|
+
} @else if (showSettings) {
|
|
8068
|
+
<div class="flex flex-col md:flex-row gap-8">
|
|
8069
|
+
<div class="md:w-1/2">
|
|
8070
|
+
<div class="card flex flex-col gap-4">
|
|
8071
|
+
<div class="font-semibold text-xl">{{ 'baseComponent.settings' | translate }}</div>
|
|
8072
|
+
<p-button icon="pi pi-save" label="Save" (onClick)="saveSettings(settings)"></p-button>
|
|
8073
|
+
</div>
|
|
8074
|
+
</div>
|
|
8075
|
+
</div>
|
|
8076
|
+
} @else if (showSecurity) {
|
|
8077
|
+
<security [controller]="controller" [id]="id" />
|
|
8078
|
+
}
|
|
8079
|
+
`
|
|
8080
|
+
}]
|
|
8081
|
+
}], ctorParameters: () => [], propDecorators: { extensionContainer: [{
|
|
8082
|
+
type: ViewChild,
|
|
8083
|
+
args: ['extensionContainer']
|
|
8084
|
+
}] } });
|
|
8085
|
+
|
|
8086
|
+
class ExtensionModuleHostComponent extends BaseModuleComponent {
|
|
8087
|
+
set extensionViewContainer(viewContainer) {
|
|
8088
|
+
this.viewContainer = viewContainer;
|
|
8089
|
+
this.queueRenderExtension();
|
|
8090
|
+
}
|
|
8091
|
+
get extensionKey() {
|
|
8092
|
+
return this.route.snapshot.paramMap.get('extensionKey') ?? '';
|
|
8093
|
+
}
|
|
8094
|
+
constructor() {
|
|
8095
|
+
super();
|
|
8096
|
+
this.injector = inject(Injector);
|
|
8097
|
+
this.environmentInjector = inject(EnvironmentInjector);
|
|
8098
|
+
this.extensionModulesApi = inject(ExtensionModulesApi);
|
|
8099
|
+
this.renderQueued = false;
|
|
8100
|
+
this.destroyed = false;
|
|
8101
|
+
this.loadError = null;
|
|
8102
|
+
this.subscriptions.push(this.topBarService.activeId$.subscribe(() => {
|
|
8103
|
+
this.updateExtensionContext();
|
|
8104
|
+
}));
|
|
8105
|
+
}
|
|
8106
|
+
async reloadExtension() {
|
|
8107
|
+
this.loadError = null;
|
|
8108
|
+
this.extensionMetadata = undefined;
|
|
8109
|
+
await this.loadExtensionMetadata();
|
|
8110
|
+
await this.renderExtension();
|
|
8111
|
+
}
|
|
8112
|
+
async onModuleInstanceChange() {
|
|
8113
|
+
await this.loadExtensionMetadata();
|
|
8114
|
+
await this.renderExtension();
|
|
8115
|
+
}
|
|
8116
|
+
onSecurityRightsChange() {
|
|
8117
|
+
this.updateExtensionContext();
|
|
8118
|
+
}
|
|
8119
|
+
ngOnDestroy() {
|
|
8120
|
+
this.destroyed = true;
|
|
8121
|
+
this.destroyExtensionComponent();
|
|
8122
|
+
super.ngOnDestroy();
|
|
8123
|
+
}
|
|
8124
|
+
async loadExtensionMetadata() {
|
|
8125
|
+
if (this.extensionMetadata) {
|
|
8126
|
+
return;
|
|
8127
|
+
}
|
|
8128
|
+
if (!this.extensionKey) {
|
|
8129
|
+
this.loadError = 'Extension key is missing.';
|
|
8130
|
+
return;
|
|
8131
|
+
}
|
|
8132
|
+
this.extensionMetadata = (await this.extensionModulesApi.getExtensionModuleByKey({
|
|
8133
|
+
extensionKey: this.extensionKey
|
|
8134
|
+
}));
|
|
8135
|
+
await this.loadExtensionTranslations(this.extensionMetadata);
|
|
8136
|
+
}
|
|
8137
|
+
async renderExtension() {
|
|
8138
|
+
if (this.destroyed || !this.viewContainer) {
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
try {
|
|
8142
|
+
this.loadError = null;
|
|
8143
|
+
await this.loadExtensionMetadata();
|
|
8144
|
+
if (!this.extensionMetadata) {
|
|
8145
|
+
return;
|
|
8146
|
+
}
|
|
8147
|
+
this.destroyExtensionComponent();
|
|
8148
|
+
if (this.extensionMetadata.loadType === 'moduleFederation') {
|
|
8149
|
+
await this.renderFederatedExtension(this.extensionMetadata);
|
|
8150
|
+
}
|
|
8151
|
+
else {
|
|
8152
|
+
this.extensionComponent = this.viewContainer.createComponent(CustomElementExtensionModuleHostComponent, {
|
|
8153
|
+
injector: this.injector,
|
|
8154
|
+
environmentInjector: this.environmentInjector
|
|
8155
|
+
});
|
|
8156
|
+
}
|
|
8157
|
+
}
|
|
8158
|
+
catch (error) {
|
|
8159
|
+
this.loadError = error instanceof Error ? error.message : 'Extension could not be loaded.';
|
|
8160
|
+
console.error(error);
|
|
8161
|
+
}
|
|
8162
|
+
}
|
|
8163
|
+
queueRenderExtension() {
|
|
8164
|
+
if (this.renderQueued) {
|
|
8165
|
+
return;
|
|
8166
|
+
}
|
|
8167
|
+
this.renderQueued = true;
|
|
8168
|
+
queueMicrotask(() => {
|
|
8169
|
+
this.renderQueued = false;
|
|
8170
|
+
void this.renderExtension();
|
|
8171
|
+
});
|
|
8172
|
+
}
|
|
8173
|
+
destroyExtensionComponent() {
|
|
8174
|
+
this.extensionComponent?.destroy();
|
|
8175
|
+
this.extensionComponent = undefined;
|
|
8176
|
+
this.extensionElement = undefined;
|
|
8177
|
+
this.viewContainer?.clear();
|
|
8178
|
+
}
|
|
8179
|
+
async renderFederatedExtension(metadata) {
|
|
8180
|
+
const { remoteEntryUrl, exposedModule, componentName } = metadata;
|
|
8181
|
+
if (!remoteEntryUrl || !exposedModule || !componentName) {
|
|
8182
|
+
this.loadError = 'Module Federation extension metadata is incomplete.';
|
|
8183
|
+
return;
|
|
8184
|
+
}
|
|
8185
|
+
const remoteModule = await loadRemoteModule({
|
|
8186
|
+
type: 'module',
|
|
8187
|
+
remoteEntry: remoteEntryUrl,
|
|
8188
|
+
exposedModule
|
|
8189
|
+
});
|
|
8190
|
+
const component = remoteModule[componentName];
|
|
8191
|
+
if (!component) {
|
|
8192
|
+
throw new Error(`Remote component '${componentName}' was not exported by '${exposedModule}'.`);
|
|
8193
|
+
}
|
|
8194
|
+
this.extensionComponent = this.viewContainer?.createComponent(component, {
|
|
8195
|
+
environmentInjector: this.environmentInjector
|
|
8196
|
+
});
|
|
8197
|
+
this.extensionElement = this.extensionComponent?.location.nativeElement;
|
|
8198
|
+
this.updateExtensionContext();
|
|
8199
|
+
}
|
|
8200
|
+
async loadExtensionTranslations(metadata) {
|
|
8201
|
+
const extensionKey = metadata.extensionKey ?? this.extensionKey;
|
|
8202
|
+
const apiBaseUrl = metadata.apiBaseUrl;
|
|
8203
|
+
if (!extensionKey || !apiBaseUrl) {
|
|
8204
|
+
return;
|
|
8205
|
+
}
|
|
8206
|
+
const lang = this.translateService.currentLang || this.layoutService.language() || 'en';
|
|
8207
|
+
for (const namespace of this.getExtensionTranslationNamespaces(metadata, extensionKey)) {
|
|
8208
|
+
const url = this.buildExtensionI18nUrl(apiBaseUrl, namespace, lang);
|
|
8209
|
+
try {
|
|
8210
|
+
await firstValueFrom(this.l10nService.loadTranslationsFromUrl(namespace, url, lang));
|
|
8211
|
+
return;
|
|
8212
|
+
}
|
|
8213
|
+
catch (error) {
|
|
8214
|
+
console.error(`No translations found for extension ${namespace}.${lang}.json`, error);
|
|
8215
|
+
}
|
|
8216
|
+
}
|
|
8217
|
+
}
|
|
8218
|
+
buildExtensionI18nUrl(apiBaseUrl, extensionKey, lang) {
|
|
8219
|
+
return `${apiBaseUrl.replace(/\/+$/, '')}/assets/i18n/${encodeURIComponent(extensionKey)}.${encodeURIComponent(lang)}.json`;
|
|
8220
|
+
}
|
|
8221
|
+
getExtensionTranslationNamespaces(metadata, extensionKey) {
|
|
8222
|
+
const namespaces = [extensionKey];
|
|
8223
|
+
const componentNamespace = this.toKebabCase(metadata.componentName?.replace(/Component$/, '') ?? '');
|
|
8224
|
+
if (componentNamespace && !namespaces.includes(componentNamespace)) {
|
|
8225
|
+
namespaces.push(componentNamespace);
|
|
8226
|
+
}
|
|
8227
|
+
return namespaces;
|
|
8228
|
+
}
|
|
8229
|
+
toKebabCase(value) {
|
|
8230
|
+
return value
|
|
8231
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
8232
|
+
.replace(/[\s_]+/g, '-')
|
|
8233
|
+
.toLowerCase();
|
|
8234
|
+
}
|
|
8235
|
+
updateExtensionContext() {
|
|
8236
|
+
if (!this.extensionElement || !this.extensionMetadata?.extensionKey) {
|
|
8237
|
+
return;
|
|
8238
|
+
}
|
|
8239
|
+
const context = {
|
|
8240
|
+
moduleInstanceId: this.id,
|
|
8241
|
+
extensionKey: this.extensionMetadata.extensionKey,
|
|
8242
|
+
apiBasePath: this.buildUrl(`api/extensions/${this.extensionMetadata.extensionKey}`),
|
|
8243
|
+
settings: this.settings,
|
|
8244
|
+
locale: this.layoutService.language(),
|
|
8245
|
+
theme: this.layoutService.layoutConfig(),
|
|
8246
|
+
user: this.securityService.getCurrentUser(),
|
|
8247
|
+
activeTabId: this.topBarService.activeId ?? 'content',
|
|
8248
|
+
permissions: {
|
|
8249
|
+
canRead: this.canRead,
|
|
8250
|
+
canEdit: this.canEdit,
|
|
8251
|
+
canDelete: this.canDelete
|
|
8252
|
+
}
|
|
8253
|
+
};
|
|
8254
|
+
Object.assign(this.extensionElement, { oipContext: context });
|
|
8255
|
+
emitOipContextChange(this.extensionElement, context);
|
|
8256
|
+
}
|
|
8257
|
+
buildUrl(path) {
|
|
8258
|
+
const baseUrl = document.getElementsByTagName('base')[0]?.href ?? `${window.location.origin}/`;
|
|
8259
|
+
return `${baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`}${path}`;
|
|
8260
|
+
}
|
|
8261
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionModuleHostComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8262
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: ExtensionModuleHostComponent, isStandalone: true, selector: "ng-component", providers: [ExtensionModulesApi], viewQueries: [{ propertyName: "extensionViewContainer", first: true, predicate: ["extensionContainer"], descendants: true, read: ViewContainerRef }], usesInheritance: true, ngImport: i0, template: `
|
|
8263
|
+
@if (loadError) {
|
|
8264
|
+
<div class="card flex flex-col gap-4">
|
|
8265
|
+
<div class="font-semibold text-xl">{{ loadError }}</div>
|
|
8266
|
+
<p-button icon="pi pi-refresh" label="Retry" (onClick)="reloadExtension()"></p-button>
|
|
8267
|
+
</div>
|
|
8268
|
+
} @else {
|
|
8269
|
+
<ng-container #extensionContainer></ng-container>
|
|
8270
|
+
}
|
|
8271
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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"] }] }); }
|
|
8272
|
+
}
|
|
8273
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: ExtensionModuleHostComponent, decorators: [{
|
|
8274
|
+
type: Component,
|
|
8275
|
+
args: [{
|
|
8276
|
+
standalone: true,
|
|
8277
|
+
imports: [CommonModule, Button],
|
|
8278
|
+
providers: [ExtensionModulesApi],
|
|
8279
|
+
template: `
|
|
8280
|
+
@if (loadError) {
|
|
8281
|
+
<div class="card flex flex-col gap-4">
|
|
8282
|
+
<div class="font-semibold text-xl">{{ loadError }}</div>
|
|
8283
|
+
<p-button icon="pi pi-refresh" label="Retry" (onClick)="reloadExtension()"></p-button>
|
|
8284
|
+
</div>
|
|
8285
|
+
} @else {
|
|
8286
|
+
<ng-container #extensionContainer></ng-container>
|
|
8287
|
+
}
|
|
8288
|
+
`
|
|
8289
|
+
}]
|
|
8290
|
+
}], ctorParameters: () => [], propDecorators: { extensionViewContainer: [{
|
|
8291
|
+
type: ViewChild,
|
|
8292
|
+
args: ['extensionContainer', { read: ViewContainerRef }]
|
|
8293
|
+
}] } });
|
|
8294
|
+
|
|
7515
8295
|
/**
|
|
7516
8296
|
* A route guard that ensures the user is authenticated and has a valid access token.
|
|
7517
8297
|
* If the access token is expired, it attempts to refresh the session.
|
|
@@ -7520,24 +8300,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7520
8300
|
class AuthGuardService {
|
|
7521
8301
|
constructor() {
|
|
7522
8302
|
this.oidcSecurityService = inject(SecurityService);
|
|
7523
|
-
this.router = inject(Router);
|
|
7524
8303
|
}
|
|
7525
8304
|
/**
|
|
7526
8305
|
* Checks whether the route can be activated.
|
|
7527
8306
|
* - Returns `true` if the user is authenticated and the token is valid.
|
|
7528
8307
|
* - Attempts to refresh the token if expired.
|
|
7529
|
-
* -
|
|
8308
|
+
* - Starts the authorization flow if not authenticated or refresh fails.
|
|
7530
8309
|
*
|
|
7531
|
-
* @returns {Observable<boolean
|
|
8310
|
+
* @returns {Observable<boolean>} A stream resolving to true (allow), or false after starting authorization.
|
|
7532
8311
|
*/
|
|
7533
8312
|
canActivate(returnUrl = '/') {
|
|
7534
8313
|
this.oidcSecurityService.auth();
|
|
7535
|
-
return this.oidcSecurityService.isAuthenticated().pipe(map((authenticated) =>
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
8314
|
+
return this.oidcSecurityService.isAuthenticated().pipe(map((authenticated) => {
|
|
8315
|
+
if (authenticated) {
|
|
8316
|
+
return true;
|
|
8317
|
+
}
|
|
8318
|
+
this.oidcSecurityService.authorize(returnUrl);
|
|
8319
|
+
return false;
|
|
8320
|
+
}));
|
|
7541
8321
|
}
|
|
7542
8322
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AuthGuardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
7543
8323
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: AuthGuardService }); }
|
|
@@ -7618,13 +8398,55 @@ function replaceDefaults(themes) {
|
|
|
7618
8398
|
return provideAppThemes(themes, { mode: 'replaceDefaults' });
|
|
7619
8399
|
}
|
|
7620
8400
|
|
|
8401
|
+
const defaultTheme = [
|
|
8402
|
+
{
|
|
8403
|
+
id: 'Oip',
|
|
8404
|
+
label: 'Oip',
|
|
8405
|
+
preset: definePreset(Aura, {
|
|
8406
|
+
components: {
|
|
8407
|
+
toolbar: {
|
|
8408
|
+
colorScheme: {
|
|
8409
|
+
light: {
|
|
8410
|
+
root: {
|
|
8411
|
+
borderRadius: '0.7rem'
|
|
8412
|
+
}
|
|
8413
|
+
},
|
|
8414
|
+
dark: {
|
|
8415
|
+
root: {
|
|
8416
|
+
borderRadius: '0.7rem'
|
|
8417
|
+
}
|
|
8418
|
+
}
|
|
8419
|
+
}
|
|
8420
|
+
}
|
|
8421
|
+
}
|
|
8422
|
+
}),
|
|
8423
|
+
primaryColors: {
|
|
8424
|
+
rose: primitive['red']
|
|
8425
|
+
},
|
|
8426
|
+
surfaceColors: {
|
|
8427
|
+
zinc: {
|
|
8428
|
+
0: '#ffffff',
|
|
8429
|
+
50: '#fafafa',
|
|
8430
|
+
100: '#f4f4f5',
|
|
8431
|
+
200: '#e4e4e7',
|
|
8432
|
+
300: '#d4d4d8',
|
|
8433
|
+
400: '#a1a1aa',
|
|
8434
|
+
500: '#71717a',
|
|
8435
|
+
600: '#52525b',
|
|
8436
|
+
700: '#3f3f46',
|
|
8437
|
+
800: '#27272a',
|
|
8438
|
+
900: '#18181b',
|
|
8439
|
+
950: '#09090b'
|
|
8440
|
+
}
|
|
8441
|
+
}
|
|
8442
|
+
}
|
|
8443
|
+
];
|
|
8444
|
+
|
|
7621
8445
|
const langIntercept = (req, next) => {
|
|
7622
8446
|
const layoutService = inject(LayoutService);
|
|
7623
8447
|
const securityService = inject(SecurityService);
|
|
7624
8448
|
const lang = layoutService.language() ? layoutService.language() : 'en';
|
|
7625
|
-
const headers = req.headers
|
|
7626
|
-
.set('Accept-language', lang)
|
|
7627
|
-
.set('X-Timezone', layoutService.timeZone());
|
|
8449
|
+
const headers = req.headers.set('Accept-language', lang).set('X-Timezone', layoutService.timeZone());
|
|
7628
8450
|
const reqWithCredentials = req.clone({
|
|
7629
8451
|
headers,
|
|
7630
8452
|
withCredentials: true
|
|
@@ -7717,5 +8539,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImpo
|
|
|
7717
8539
|
* Generated bundle index. Do not edit.
|
|
7718
8540
|
*/
|
|
7719
8541
|
|
|
7720
|
-
export { APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AppTopbarApplicationSwitcherComponent, ApplicationRegistryService, ApplicationsApi, ApplicationsComponent, AuthGuardService, BaseModuleComponent, BffSecurityService, ConfigComponent, ContentType, DbMigrationComponent, DiscussionComponent, ErrorComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, 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 };
|
|
8542
|
+
export { APP_THEME_PRESETS, APP_THEME_PRESETS_MERGE_MODE, AppConfiguratorComponent, AppFloatingConfiguratorComponent, AppLayoutComponent, AppModulesComponent, AppTopbar, AppTopbarApplicationSwitcherComponent, ApplicationRegistryService, ApplicationsApi, ApplicationsComponent, AuthGuardService, BaseModuleComponent, BffSecurityService, ConfigComponent, ContentType, CustomElementExtensionModuleHostComponent, DbMigrationComponent, DiscussionComponent, ErrorComponent, ExtensionLoaderService, ExtensionModuleHostComponent, FolderModuleApi, FooterComponent, HttpClient, IframeModuleApi, IframeModuleComponent, L10nService, LOGO_COMPONENT_TOKEN, LayoutService, LogoComponent, LogoService, MenuComponent, MenuService, MsgService, NotfoundComponent, NotificationApi, NotificationService, OIP_EXTENSION_EVENTS, ProfileComponent, SecurityApi, SecurityComponent, SecurityService, SidebarComponent, TableFilterService, TopBarService, UnauthorizedComponent, UserNotificationsComponent, UserProfileApi, UserService, convertToPrimeNgDateFormat, defaultTheme, emitOipContextChange, emitOipError, emitOipNavigate, emitOipNotify, emitOipSettingsChange, emitOipTitleChange, langIntercept, mergeWithDefaults, provideAppThemes, provideLogoComponent, provideOip, replaceDefaults };
|
|
7721
8543
|
//# sourceMappingURL=oip-common.mjs.map
|