oip-common 0.1.2 → 0.1.4
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/fesm2022/oip-common.mjs +256 -222
- package/fesm2022/oip-common.mjs.map +1 -1
- package/index.d.ts +11 -3
- package/package.json +1 -1
package/fesm2022/oip-common.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import * as i2$4 from '@ngx-translate/core';
|
|
|
7
7
|
import { TranslateService, TranslatePipe, TranslateModule } from '@ngx-translate/core';
|
|
8
8
|
import * as i1$3 from '@angular/router';
|
|
9
9
|
import { ActivatedRoute, Router, RouterModule, NavigationEnd, RouterLinkActive, RouterLink } from '@angular/router';
|
|
10
|
-
import { lastValueFrom, BehaviorSubject, Subject, filter as filter$1, combineLatest, of, map as map$1, Observable } from 'rxjs';
|
|
10
|
+
import { lastValueFrom, BehaviorSubject, Subject, ReplaySubject, merge, filter as filter$1, combineLatest, of, map as map$1, Observable } from 'rxjs';
|
|
11
11
|
import { Title, DomSanitizer } from '@angular/platform-browser';
|
|
12
12
|
import * as i1 from 'primeng/multiselect';
|
|
13
13
|
import { MultiSelectModule } from 'primeng/multiselect';
|
|
@@ -29,7 +29,7 @@ import { PrimeNG } from 'primeng/config';
|
|
|
29
29
|
import * as i3 from 'primeng/selectbutton';
|
|
30
30
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
31
31
|
import { OidcSecurityService, PublicEventsService, EventTypes, StsConfigHttpLoader } from 'angular-auth-oidc-client';
|
|
32
|
-
import { filter, map, switchMap, catchError } from 'rxjs/operators';
|
|
32
|
+
import { filter, distinctUntilChanged, map, switchMap, catchError } from 'rxjs/operators';
|
|
33
33
|
import { Tabs, TabList, Tab } from 'primeng/tabs';
|
|
34
34
|
import * as i2$2 from 'primeng/avatar';
|
|
35
35
|
import { AvatarModule } from 'primeng/avatar';
|
|
@@ -1475,22 +1475,35 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
1475
1475
|
* Stores the decoded access token payload.
|
|
1476
1476
|
*/
|
|
1477
1477
|
this.payload = new BehaviorSubject(null);
|
|
1478
|
+
/**
|
|
1479
|
+
* Stores user-specific data from the login response.
|
|
1480
|
+
*/
|
|
1481
|
+
this.currentUser = new BehaviorSubject(null);
|
|
1482
|
+
/**
|
|
1483
|
+
* Emits access token updates from initial auth check, manual refresh,
|
|
1484
|
+
* and library authentication events.
|
|
1485
|
+
*/
|
|
1486
|
+
this.accessToken = new ReplaySubject(1);
|
|
1478
1487
|
this.publicEventsService
|
|
1479
1488
|
.registerForEvents()
|
|
1480
1489
|
.pipe(filter((event) => event.type === EventTypes.NewAuthenticationResult))
|
|
1481
1490
|
.subscribe(() => {
|
|
1491
|
+
super.getAccessToken().subscribe(token => { this.accessToken.next(token); });
|
|
1482
1492
|
this.auth();
|
|
1483
1493
|
});
|
|
1484
1494
|
}
|
|
1485
1495
|
getCurrentUser() {
|
|
1486
|
-
return this.
|
|
1496
|
+
return this.currentUser.getValue();
|
|
1497
|
+
}
|
|
1498
|
+
getCurrentUser$() {
|
|
1499
|
+
return this.currentUser.asObservable();
|
|
1487
1500
|
}
|
|
1488
1501
|
/**
|
|
1489
1502
|
* Returns the ID token for the sign-in.
|
|
1490
1503
|
* @returns A string with the id token.
|
|
1491
1504
|
*/
|
|
1492
|
-
getAccessToken() {
|
|
1493
|
-
return this.
|
|
1505
|
+
getAccessToken(configId) {
|
|
1506
|
+
return merge(super.getAccessToken(configId), this.accessToken.asObservable()).pipe(distinctUntilChanged());
|
|
1494
1507
|
}
|
|
1495
1508
|
/**
|
|
1496
1509
|
* Indicates whether the current user has the 'admin' role.
|
|
@@ -1507,7 +1520,7 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
1507
1520
|
auth() {
|
|
1508
1521
|
super.checkAuth().subscribe((_response) => {
|
|
1509
1522
|
this.loginResponse.next(_response);
|
|
1510
|
-
this.
|
|
1523
|
+
this.currentUser.next(_response.userData);
|
|
1511
1524
|
this.getPayloadFromAccessToken().subscribe((_token) => {
|
|
1512
1525
|
this.payload.next(_token);
|
|
1513
1526
|
});
|
|
@@ -1528,6 +1541,7 @@ class KeycloakSecurityService extends OidcSecurityService {
|
|
|
1528
1541
|
ngOnDestroy() {
|
|
1529
1542
|
this.loginResponse.complete();
|
|
1530
1543
|
this.payload.complete();
|
|
1544
|
+
this.currentUser.complete();
|
|
1531
1545
|
}
|
|
1532
1546
|
/**
|
|
1533
1547
|
* Checks whether the current access token is expired based on the 'exp' claim.
|
|
@@ -1554,6 +1568,7 @@ class UserService {
|
|
|
1554
1568
|
constructor() {
|
|
1555
1569
|
this.securityService = inject(SecurityService);
|
|
1556
1570
|
this.baseDataService = inject(BaseDataService);
|
|
1571
|
+
this.requestedPhotoEmail = null;
|
|
1557
1572
|
/**
|
|
1558
1573
|
* Stores the user's photo as a data URL or binary blob, depending on how it's processed.
|
|
1559
1574
|
*/
|
|
@@ -1562,7 +1577,12 @@ class UserService {
|
|
|
1562
1577
|
* Indicates whether the user photo has finished loading.
|
|
1563
1578
|
*/
|
|
1564
1579
|
this.photoLoaded = false;
|
|
1565
|
-
this.
|
|
1580
|
+
this.securityService
|
|
1581
|
+
.getCurrentUser$()
|
|
1582
|
+
.pipe(map((user) => user?.email ?? null), filter((email) => !!email), distinctUntilChanged())
|
|
1583
|
+
.subscribe(() => {
|
|
1584
|
+
this.getUserPhoto();
|
|
1585
|
+
});
|
|
1566
1586
|
}
|
|
1567
1587
|
/**
|
|
1568
1588
|
* Returns a short label composed of the user's initials.
|
|
@@ -1585,9 +1605,12 @@ class UserService {
|
|
|
1585
1605
|
getUserPhoto() {
|
|
1586
1606
|
const email = this.securityService.getCurrentUser()?.email;
|
|
1587
1607
|
if (!email) {
|
|
1588
|
-
this.photoLoaded = true;
|
|
1589
1608
|
return;
|
|
1590
1609
|
}
|
|
1610
|
+
if (this.requestedPhotoEmail === email && (this.photoLoaded || this.photo)) {
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
this.requestedPhotoEmail = email;
|
|
1591
1614
|
const url = this.baseDataService.buildUrl(`api/user-profile/get-user-photo?email=${email}`);
|
|
1592
1615
|
this.baseDataService.getBlob(url).then((data) => {
|
|
1593
1616
|
this.createImageFromBlob(data);
|
|
@@ -1719,101 +1742,101 @@ class AppTopbar {
|
|
|
1719
1742
|
}
|
|
1720
1743
|
}
|
|
1721
1744
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppTopbar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1722
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppTopbar, isStandalone: true, selector: "app-topbar", ngImport: i0, template: ` <div class="layout-topbar">
|
|
1723
|
-
<div class="layout-topbar-logo-container">
|
|
1724
|
-
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
1725
|
-
<i class="pi pi-bars"></i>
|
|
1726
|
-
</button>
|
|
1727
|
-
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
1728
|
-
<ng-container
|
|
1729
|
-
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
1730
|
-
<span>{{ 'app-info.title' | translate }}</span>
|
|
1731
|
-
</a>
|
|
1732
|
-
</div>
|
|
1733
|
-
|
|
1734
|
-
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
1735
|
-
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
1736
|
-
<p-tablist>
|
|
1737
|
-
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
1738
|
-
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
1739
|
-
<i class="pi {{ tab.icon }}"></i>
|
|
1740
|
-
<span class="ml-2">{{ tab.caption }}</span>
|
|
1741
|
-
</p-tab>
|
|
1742
|
-
}
|
|
1743
|
-
</p-tablist>
|
|
1744
|
-
</p-tabs>
|
|
1745
|
-
}
|
|
1746
|
-
<div class="layout-topbar-actions">
|
|
1747
|
-
<div class="layout-config-menu">
|
|
1748
|
-
<p-button
|
|
1749
|
-
class="layout-topbar-action"
|
|
1750
|
-
id="oip-app-topbar-theme-button"
|
|
1751
|
-
severity="secondary"
|
|
1752
|
-
type="button"
|
|
1753
|
-
[rounded]="true"
|
|
1754
|
-
[text]="true"
|
|
1755
|
-
(click)="toggleDarkMode()">
|
|
1756
|
-
<i
|
|
1757
|
-
class="pi"
|
|
1758
|
-
[ngClass]="{
|
|
1759
|
-
'pi-moon': layoutService.isDarkTheme(),
|
|
1760
|
-
'pi-sun': !layoutService.isDarkTheme()
|
|
1761
|
-
}"></i>
|
|
1762
|
-
</p-button>
|
|
1763
|
-
<div class="relative">
|
|
1764
|
-
<p-button
|
|
1765
|
-
class="layout-topbar-action layout-topbar-action-highlight"
|
|
1766
|
-
enterActiveClass="animate-scalein"
|
|
1767
|
-
enterFromClass="hidden"
|
|
1768
|
-
id="oip-app-topbar-palette-button"
|
|
1769
|
-
leaveActiveClass="animate-fadeout"
|
|
1770
|
-
leaveToClass="hidden"
|
|
1771
|
-
pStyleClass="@next"
|
|
1772
|
-
[hideOnOutsideClick]="true"
|
|
1773
|
-
[rounded]="true">
|
|
1774
|
-
<i class="pi pi-palette"></i>
|
|
1775
|
-
</p-button>
|
|
1776
|
-
<app-configurator />
|
|
1777
|
-
</div>
|
|
1778
|
-
</div>
|
|
1779
|
-
|
|
1780
|
-
<button
|
|
1781
|
-
class="layout-topbar-menu-button layout-topbar-action"
|
|
1782
|
-
enterActiveClass="animate-scalein"
|
|
1783
|
-
enterFromClass="hidden"
|
|
1784
|
-
id="oip-app-topbar-menu-expand-button"
|
|
1785
|
-
leaveActiveClass="animate-fadeout"
|
|
1786
|
-
leaveToClass="hidden"
|
|
1787
|
-
pStyleClass="@next"
|
|
1788
|
-
[hideOnOutsideClick]="true">
|
|
1789
|
-
<i class="pi pi-ellipsis-v"></i>
|
|
1790
|
-
</button>
|
|
1791
|
-
|
|
1792
|
-
<div class="layout-topbar-menu hidden lg:block">
|
|
1793
|
-
<div class="layout-topbar-menu-content">
|
|
1794
|
-
<button
|
|
1795
|
-
class="layout-topbar-action"
|
|
1796
|
-
id="oip-app-topbar-logout-button"
|
|
1797
|
-
type="button"
|
|
1798
|
-
(click)="securityService.logout()"
|
|
1799
|
-
(keydown)="logoutKeyDown($event)">
|
|
1800
|
-
<i class="pi pi-sign-out"></i>
|
|
1801
|
-
<span>{{ 'topbar.logout' | translate }}</span>
|
|
1802
|
-
</button>
|
|
1803
|
-
<button class="layout-topbar-action" routerLink="config">
|
|
1804
|
-
<p-avatar
|
|
1805
|
-
class="p-link flex align-items-center"
|
|
1806
|
-
id="oip-app-topbar-user-avatar"
|
|
1807
|
-
shape="circle"
|
|
1808
|
-
size="normal"
|
|
1809
|
-
[image]="userService.photoLoaded ? userService.photo : null"
|
|
1810
|
-
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
1811
|
-
</p-avatar>
|
|
1812
|
-
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
1813
|
-
</button>
|
|
1814
|
-
</div>
|
|
1815
|
-
</div>
|
|
1816
|
-
</div>
|
|
1745
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AppTopbar, isStandalone: true, selector: "app-topbar", ngImport: i0, template: ` <div class="layout-topbar">
|
|
1746
|
+
<div class="layout-topbar-logo-container">
|
|
1747
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
1748
|
+
<i class="pi pi-bars"></i>
|
|
1749
|
+
</button>
|
|
1750
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
1751
|
+
<ng-container
|
|
1752
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
1753
|
+
<span>{{ 'app-info.title' | translate }}</span>
|
|
1754
|
+
</a>
|
|
1755
|
+
</div>
|
|
1756
|
+
|
|
1757
|
+
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
1758
|
+
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
1759
|
+
<p-tablist>
|
|
1760
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
1761
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
1762
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
1763
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
1764
|
+
</p-tab>
|
|
1765
|
+
}
|
|
1766
|
+
</p-tablist>
|
|
1767
|
+
</p-tabs>
|
|
1768
|
+
}
|
|
1769
|
+
<div class="layout-topbar-actions">
|
|
1770
|
+
<div class="layout-config-menu">
|
|
1771
|
+
<p-button
|
|
1772
|
+
class="layout-topbar-action"
|
|
1773
|
+
id="oip-app-topbar-theme-button"
|
|
1774
|
+
severity="secondary"
|
|
1775
|
+
type="button"
|
|
1776
|
+
[rounded]="true"
|
|
1777
|
+
[text]="true"
|
|
1778
|
+
(click)="toggleDarkMode()">
|
|
1779
|
+
<i
|
|
1780
|
+
class="pi"
|
|
1781
|
+
[ngClass]="{
|
|
1782
|
+
'pi-moon': layoutService.isDarkTheme(),
|
|
1783
|
+
'pi-sun': !layoutService.isDarkTheme()
|
|
1784
|
+
}"></i>
|
|
1785
|
+
</p-button>
|
|
1786
|
+
<div class="relative">
|
|
1787
|
+
<p-button
|
|
1788
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
1789
|
+
enterActiveClass="animate-scalein"
|
|
1790
|
+
enterFromClass="hidden"
|
|
1791
|
+
id="oip-app-topbar-palette-button"
|
|
1792
|
+
leaveActiveClass="animate-fadeout"
|
|
1793
|
+
leaveToClass="hidden"
|
|
1794
|
+
pStyleClass="@next"
|
|
1795
|
+
[hideOnOutsideClick]="true"
|
|
1796
|
+
[rounded]="true">
|
|
1797
|
+
<i class="pi pi-palette"></i>
|
|
1798
|
+
</p-button>
|
|
1799
|
+
<app-configurator />
|
|
1800
|
+
</div>
|
|
1801
|
+
</div>
|
|
1802
|
+
|
|
1803
|
+
<button
|
|
1804
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
1805
|
+
enterActiveClass="animate-scalein"
|
|
1806
|
+
enterFromClass="hidden"
|
|
1807
|
+
id="oip-app-topbar-menu-expand-button"
|
|
1808
|
+
leaveActiveClass="animate-fadeout"
|
|
1809
|
+
leaveToClass="hidden"
|
|
1810
|
+
pStyleClass="@next"
|
|
1811
|
+
[hideOnOutsideClick]="true">
|
|
1812
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
1813
|
+
</button>
|
|
1814
|
+
|
|
1815
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
1816
|
+
<div class="layout-topbar-menu-content">
|
|
1817
|
+
<button
|
|
1818
|
+
class="layout-topbar-action"
|
|
1819
|
+
id="oip-app-topbar-logout-button"
|
|
1820
|
+
type="button"
|
|
1821
|
+
(click)="securityService.logout()"
|
|
1822
|
+
(keydown)="logoutKeyDown($event)">
|
|
1823
|
+
<i class="pi pi-sign-out"></i>
|
|
1824
|
+
<span>{{ 'topbar.logout' | translate }}</span>
|
|
1825
|
+
</button>
|
|
1826
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
1827
|
+
<p-avatar
|
|
1828
|
+
class="p-link flex align-items-center"
|
|
1829
|
+
id="oip-app-topbar-user-avatar"
|
|
1830
|
+
shape="circle"
|
|
1831
|
+
size="normal"
|
|
1832
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
1833
|
+
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
1834
|
+
</p-avatar>
|
|
1835
|
+
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
1836
|
+
</button>
|
|
1837
|
+
</div>
|
|
1838
|
+
</div>
|
|
1839
|
+
</div>
|
|
1817
1840
|
</div>`, isInline: true, dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1$3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: StyleClassModule }, { kind: "directive", type: i3$1.StyleClass, selector: "[pStyleClass]", inputs: ["pStyleClass", "enterFromClass", "enterActiveClass", "enterToClass", "leaveFromClass", "leaveActiveClass", "leaveToClass", "hideOnOutsideClick", "toggleClass", "hideOnEscape", "hideOnResize", "resizeSelector"] }, { kind: "component", type: AppConfiguratorComponent, selector: "app-configurator" }, { kind: "component", type: Tabs, selector: "p-tabs", inputs: ["value", "scrollable", "lazy", "selectOnFocus", "showNavigators", "tabindex"], outputs: ["valueChange"] }, { kind: "component", type: TabList, selector: "p-tablist" }, { kind: "component", type: Tab, selector: "p-tab", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "ngmodule", type: AvatarModule }, { kind: "component", type: i2$2.Avatar, selector: "p-avatar", inputs: ["label", "icon", "image", "size", "shape", "styleClass", "ariaLabel", "ariaLabelledBy"], outputs: ["onImageError"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "component", type: i1$2.Button, selector: "p-button", inputs: ["hostName", "type", "badge", "disabled", "raised", "rounded", "text", "plain", "outlined", "link", "tabindex", "size", "variant", "style", "styleClass", "badgeClass", "badgeSeverity", "ariaLabel", "autofocus", "iconPos", "icon", "label", "loading", "loadingIcon", "severity", "buttonProps", "fluid"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
1818
1841
|
}
|
|
1819
1842
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AppTopbar, decorators: [{
|
|
@@ -1833,101 +1856,101 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
1833
1856
|
ButtonModule,
|
|
1834
1857
|
TranslatePipe
|
|
1835
1858
|
],
|
|
1836
|
-
template: ` <div class="layout-topbar">
|
|
1837
|
-
<div class="layout-topbar-logo-container">
|
|
1838
|
-
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
1839
|
-
<i class="pi pi-bars"></i>
|
|
1840
|
-
</button>
|
|
1841
|
-
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
1842
|
-
<ng-container
|
|
1843
|
-
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
1844
|
-
<span>{{ 'app-info.title' | translate }}</span>
|
|
1845
|
-
</a>
|
|
1846
|
-
</div>
|
|
1847
|
-
|
|
1848
|
-
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
1849
|
-
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
1850
|
-
<p-tablist>
|
|
1851
|
-
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
1852
|
-
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
1853
|
-
<i class="pi {{ tab.icon }}"></i>
|
|
1854
|
-
<span class="ml-2">{{ tab.caption }}</span>
|
|
1855
|
-
</p-tab>
|
|
1856
|
-
}
|
|
1857
|
-
</p-tablist>
|
|
1858
|
-
</p-tabs>
|
|
1859
|
-
}
|
|
1860
|
-
<div class="layout-topbar-actions">
|
|
1861
|
-
<div class="layout-config-menu">
|
|
1862
|
-
<p-button
|
|
1863
|
-
class="layout-topbar-action"
|
|
1864
|
-
id="oip-app-topbar-theme-button"
|
|
1865
|
-
severity="secondary"
|
|
1866
|
-
type="button"
|
|
1867
|
-
[rounded]="true"
|
|
1868
|
-
[text]="true"
|
|
1869
|
-
(click)="toggleDarkMode()">
|
|
1870
|
-
<i
|
|
1871
|
-
class="pi"
|
|
1872
|
-
[ngClass]="{
|
|
1873
|
-
'pi-moon': layoutService.isDarkTheme(),
|
|
1874
|
-
'pi-sun': !layoutService.isDarkTheme()
|
|
1875
|
-
}"></i>
|
|
1876
|
-
</p-button>
|
|
1877
|
-
<div class="relative">
|
|
1878
|
-
<p-button
|
|
1879
|
-
class="layout-topbar-action layout-topbar-action-highlight"
|
|
1880
|
-
enterActiveClass="animate-scalein"
|
|
1881
|
-
enterFromClass="hidden"
|
|
1882
|
-
id="oip-app-topbar-palette-button"
|
|
1883
|
-
leaveActiveClass="animate-fadeout"
|
|
1884
|
-
leaveToClass="hidden"
|
|
1885
|
-
pStyleClass="@next"
|
|
1886
|
-
[hideOnOutsideClick]="true"
|
|
1887
|
-
[rounded]="true">
|
|
1888
|
-
<i class="pi pi-palette"></i>
|
|
1889
|
-
</p-button>
|
|
1890
|
-
<app-configurator />
|
|
1891
|
-
</div>
|
|
1892
|
-
</div>
|
|
1893
|
-
|
|
1894
|
-
<button
|
|
1895
|
-
class="layout-topbar-menu-button layout-topbar-action"
|
|
1896
|
-
enterActiveClass="animate-scalein"
|
|
1897
|
-
enterFromClass="hidden"
|
|
1898
|
-
id="oip-app-topbar-menu-expand-button"
|
|
1899
|
-
leaveActiveClass="animate-fadeout"
|
|
1900
|
-
leaveToClass="hidden"
|
|
1901
|
-
pStyleClass="@next"
|
|
1902
|
-
[hideOnOutsideClick]="true">
|
|
1903
|
-
<i class="pi pi-ellipsis-v"></i>
|
|
1904
|
-
</button>
|
|
1905
|
-
|
|
1906
|
-
<div class="layout-topbar-menu hidden lg:block">
|
|
1907
|
-
<div class="layout-topbar-menu-content">
|
|
1908
|
-
<button
|
|
1909
|
-
class="layout-topbar-action"
|
|
1910
|
-
id="oip-app-topbar-logout-button"
|
|
1911
|
-
type="button"
|
|
1912
|
-
(click)="securityService.logout()"
|
|
1913
|
-
(keydown)="logoutKeyDown($event)">
|
|
1914
|
-
<i class="pi pi-sign-out"></i>
|
|
1915
|
-
<span>{{ 'topbar.logout' | translate }}</span>
|
|
1916
|
-
</button>
|
|
1917
|
-
<button class="layout-topbar-action" routerLink="config">
|
|
1918
|
-
<p-avatar
|
|
1919
|
-
class="p-link flex align-items-center"
|
|
1920
|
-
id="oip-app-topbar-user-avatar"
|
|
1921
|
-
shape="circle"
|
|
1922
|
-
size="normal"
|
|
1923
|
-
[image]="userService.photoLoaded ? userService.photo : null"
|
|
1924
|
-
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
1925
|
-
</p-avatar>
|
|
1926
|
-
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
1927
|
-
</button>
|
|
1928
|
-
</div>
|
|
1929
|
-
</div>
|
|
1930
|
-
</div>
|
|
1859
|
+
template: ` <div class="layout-topbar">
|
|
1860
|
+
<div class="layout-topbar-logo-container">
|
|
1861
|
+
<button class="layout-menu-button layout-topbar-action" (click)="layoutService.onMenuToggle()">
|
|
1862
|
+
<i class="pi pi-bars"></i>
|
|
1863
|
+
</button>
|
|
1864
|
+
<a class="layout-topbar-logo" id="oip-app-topbar-logo-link" routerLink="">
|
|
1865
|
+
<ng-container
|
|
1866
|
+
*ngComponentOutlet="logoService.getLogoComponent(); inputs: { width: 36, height: 36 }"></ng-container>
|
|
1867
|
+
<span>{{ 'app-info.title' | translate }}</span>
|
|
1868
|
+
</a>
|
|
1869
|
+
</div>
|
|
1870
|
+
|
|
1871
|
+
@if (securityService.isAdmin() && topBarService.topBarItems.length > 0) {
|
|
1872
|
+
<p-tabs class="layout-topbar-tabs ml-2" [(value)]="topBarService.activeId">
|
|
1873
|
+
<p-tablist>
|
|
1874
|
+
@for (tab of topBarService.availableTopBarItems; track tab.id) {
|
|
1875
|
+
<p-tab id="oip-app-topbar-tab-{{ tab.id }}" [value]="tab.id">
|
|
1876
|
+
<i class="pi {{ tab.icon }}"></i>
|
|
1877
|
+
<span class="ml-2">{{ tab.caption }}</span>
|
|
1878
|
+
</p-tab>
|
|
1879
|
+
}
|
|
1880
|
+
</p-tablist>
|
|
1881
|
+
</p-tabs>
|
|
1882
|
+
}
|
|
1883
|
+
<div class="layout-topbar-actions">
|
|
1884
|
+
<div class="layout-config-menu">
|
|
1885
|
+
<p-button
|
|
1886
|
+
class="layout-topbar-action"
|
|
1887
|
+
id="oip-app-topbar-theme-button"
|
|
1888
|
+
severity="secondary"
|
|
1889
|
+
type="button"
|
|
1890
|
+
[rounded]="true"
|
|
1891
|
+
[text]="true"
|
|
1892
|
+
(click)="toggleDarkMode()">
|
|
1893
|
+
<i
|
|
1894
|
+
class="pi"
|
|
1895
|
+
[ngClass]="{
|
|
1896
|
+
'pi-moon': layoutService.isDarkTheme(),
|
|
1897
|
+
'pi-sun': !layoutService.isDarkTheme()
|
|
1898
|
+
}"></i>
|
|
1899
|
+
</p-button>
|
|
1900
|
+
<div class="relative">
|
|
1901
|
+
<p-button
|
|
1902
|
+
class="layout-topbar-action layout-topbar-action-highlight"
|
|
1903
|
+
enterActiveClass="animate-scalein"
|
|
1904
|
+
enterFromClass="hidden"
|
|
1905
|
+
id="oip-app-topbar-palette-button"
|
|
1906
|
+
leaveActiveClass="animate-fadeout"
|
|
1907
|
+
leaveToClass="hidden"
|
|
1908
|
+
pStyleClass="@next"
|
|
1909
|
+
[hideOnOutsideClick]="true"
|
|
1910
|
+
[rounded]="true">
|
|
1911
|
+
<i class="pi pi-palette"></i>
|
|
1912
|
+
</p-button>
|
|
1913
|
+
<app-configurator />
|
|
1914
|
+
</div>
|
|
1915
|
+
</div>
|
|
1916
|
+
|
|
1917
|
+
<button
|
|
1918
|
+
class="layout-topbar-menu-button layout-topbar-action"
|
|
1919
|
+
enterActiveClass="animate-scalein"
|
|
1920
|
+
enterFromClass="hidden"
|
|
1921
|
+
id="oip-app-topbar-menu-expand-button"
|
|
1922
|
+
leaveActiveClass="animate-fadeout"
|
|
1923
|
+
leaveToClass="hidden"
|
|
1924
|
+
pStyleClass="@next"
|
|
1925
|
+
[hideOnOutsideClick]="true">
|
|
1926
|
+
<i class="pi pi-ellipsis-v"></i>
|
|
1927
|
+
</button>
|
|
1928
|
+
|
|
1929
|
+
<div class="layout-topbar-menu hidden lg:block">
|
|
1930
|
+
<div class="layout-topbar-menu-content">
|
|
1931
|
+
<button
|
|
1932
|
+
class="layout-topbar-action"
|
|
1933
|
+
id="oip-app-topbar-logout-button"
|
|
1934
|
+
type="button"
|
|
1935
|
+
(click)="securityService.logout()"
|
|
1936
|
+
(keydown)="logoutKeyDown($event)">
|
|
1937
|
+
<i class="pi pi-sign-out"></i>
|
|
1938
|
+
<span>{{ 'topbar.logout' | translate }}</span>
|
|
1939
|
+
</button>
|
|
1940
|
+
<button class="layout-topbar-action" routerLink="config">
|
|
1941
|
+
<p-avatar
|
|
1942
|
+
class="p-link flex align-items-center"
|
|
1943
|
+
id="oip-app-topbar-user-avatar"
|
|
1944
|
+
shape="circle"
|
|
1945
|
+
size="normal"
|
|
1946
|
+
[image]="userService.photoLoaded ? userService.photo : null"
|
|
1947
|
+
>{{ !userService.photoLoaded ? userService.shortLabel : null }}
|
|
1948
|
+
</p-avatar>
|
|
1949
|
+
<span class="ml-2">{{ 'topbar.profile' | translate }}</span>
|
|
1950
|
+
</button>
|
|
1951
|
+
</div>
|
|
1952
|
+
</div>
|
|
1953
|
+
</div>
|
|
1931
1954
|
</div>`
|
|
1932
1955
|
}]
|
|
1933
1956
|
}] });
|
|
@@ -1988,15 +2011,18 @@ class HttpClient {
|
|
|
1988
2011
|
this.layoutService = inject(LayoutService);
|
|
1989
2012
|
this.baseUrl = "";
|
|
1990
2013
|
this.securityData = null;
|
|
1991
|
-
this.securityWorker = (securityData) =>
|
|
1992
|
-
headers
|
|
2014
|
+
this.securityWorker = (securityData) => {
|
|
2015
|
+
const headers = {
|
|
1993
2016
|
"Accept-language": this.layoutService.language()
|
|
1994
2017
|
? this.layoutService.language()
|
|
1995
2018
|
: "en",
|
|
1996
2019
|
"X-Timezone": this.layoutService.timeZone(),
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2020
|
+
};
|
|
2021
|
+
if (securityData) {
|
|
2022
|
+
headers.Authorization = `Bearer ${securityData}`;
|
|
2023
|
+
}
|
|
2024
|
+
return { headers };
|
|
2025
|
+
};
|
|
2000
2026
|
this.abortControllers = new Map();
|
|
2001
2027
|
this.customFetch = (...fetchParams) => fetch(...fetchParams);
|
|
2002
2028
|
this.baseApiParams = {
|
|
@@ -3128,7 +3154,8 @@ class MenuComponent {
|
|
|
3128
3154
|
];
|
|
3129
3155
|
}
|
|
3130
3156
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3131
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", 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: `
|
|
3157
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", 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: `
|
|
3158
|
+
<div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
3132
3159
|
<ul class="layout-menu">
|
|
3133
3160
|
@for (item of menuService.menu; track item; let i = $index) {
|
|
3134
3161
|
<ng-container>
|
|
@@ -3148,10 +3175,10 @@ class MenuComponent {
|
|
|
3148
3175
|
}
|
|
3149
3176
|
</ul>
|
|
3150
3177
|
</div>
|
|
3151
|
-
<p-contextMenu [target]="empty"
|
|
3152
|
-
@if (securityService.isAdmin) {
|
|
3153
|
-
<menu-item-create-dialog
|
|
3154
|
-
<menu-item-edit-dialog
|
|
3178
|
+
<p-contextMenu [target]="empty"/>
|
|
3179
|
+
@if (securityService.isAdmin()) {
|
|
3180
|
+
<menu-item-create-dialog/>
|
|
3181
|
+
<menu-item-edit-dialog/>
|
|
3155
3182
|
}`, 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$4.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"] }] }); }
|
|
3156
3183
|
}
|
|
3157
3184
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: MenuComponent, decorators: [{
|
|
@@ -3170,7 +3197,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3170
3197
|
providers: [MenuApi],
|
|
3171
3198
|
selector: 'app-menu',
|
|
3172
3199
|
standalone: true,
|
|
3173
|
-
template: `
|
|
3200
|
+
template: `
|
|
3201
|
+
<div #empty class="layout-sidebar" (contextmenu)="onContextMenu($event)">
|
|
3174
3202
|
<ul class="layout-menu">
|
|
3175
3203
|
@for (item of menuService.menu; track item; let i = $index) {
|
|
3176
3204
|
<ng-container>
|
|
@@ -3190,10 +3218,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
3190
3218
|
}
|
|
3191
3219
|
</ul>
|
|
3192
3220
|
</div>
|
|
3193
|
-
<p-contextMenu [target]="empty"
|
|
3194
|
-
@if (securityService.isAdmin) {
|
|
3195
|
-
<menu-item-create-dialog
|
|
3196
|
-
<menu-item-edit-dialog
|
|
3221
|
+
<p-contextMenu [target]="empty"/>
|
|
3222
|
+
@if (securityService.isAdmin()) {
|
|
3223
|
+
<menu-item-create-dialog/>
|
|
3224
|
+
<menu-item-edit-dialog/>
|
|
3197
3225
|
}`
|
|
3198
3226
|
}]
|
|
3199
3227
|
}], propDecorators: { menuItemCreateDialogComponent: [{
|
|
@@ -5925,17 +5953,10 @@ class NotificationService {
|
|
|
5925
5953
|
this.securityService = inject(SecurityService);
|
|
5926
5954
|
this.msgService = inject(MsgService);
|
|
5927
5955
|
this.frontendConfig = inject(OIP_FRONTEND_CONFIG);
|
|
5928
|
-
this.
|
|
5929
|
-
this.securityData = token;
|
|
5930
|
-
if (token) {
|
|
5931
|
-
this.connection.stop().then(() => {
|
|
5932
|
-
this.connection.start().then();
|
|
5933
|
-
});
|
|
5934
|
-
}
|
|
5935
|
-
});
|
|
5956
|
+
this.securityData = null;
|
|
5936
5957
|
this.connection = new signalR.HubConnectionBuilder()
|
|
5937
5958
|
.withUrl(this.resolveHubUrl(), {
|
|
5938
|
-
accessTokenFactory: () => this.securityData,
|
|
5959
|
+
accessTokenFactory: () => this.securityData ?? '',
|
|
5939
5960
|
skipNegotiation: true,
|
|
5940
5961
|
transport: signalR.HttpTransportType.WebSockets
|
|
5941
5962
|
})
|
|
@@ -5950,6 +5971,19 @@ class NotificationService {
|
|
|
5950
5971
|
};
|
|
5951
5972
|
this.msgService.add(opt);
|
|
5952
5973
|
});
|
|
5974
|
+
this.securityService.getAccessToken().subscribe((token) => {
|
|
5975
|
+
this.securityData = token;
|
|
5976
|
+
if (!token) {
|
|
5977
|
+
return;
|
|
5978
|
+
}
|
|
5979
|
+
if (this.connection.state === signalR.HubConnectionState.Disconnected) {
|
|
5980
|
+
this.connection.start().catch((error) => console.error('Failed to start notification connection', error));
|
|
5981
|
+
return;
|
|
5982
|
+
}
|
|
5983
|
+
this.connection.stop().then(() => {
|
|
5984
|
+
this.connection.start().catch((error) => console.error('Failed to restart notification connection', error));
|
|
5985
|
+
});
|
|
5986
|
+
});
|
|
5953
5987
|
}
|
|
5954
5988
|
resolveHubUrl() {
|
|
5955
5989
|
if (this.frontendConfig.notificationHubUrl) {
|