@tapsellorg/angular-material-library
Version:
Angular library for Tapsell
792 lines (778 loc) • 62.9 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, Inject, Injectable, input, HostListener, Directive, signal, ChangeDetectionStrategy, ViewEncapsulation, Component, Pipe, NgModule, output } from '@angular/core';
import * as i1$1 from '@tapsellorg/angular-material-library/src/lib/common';
import { PghStorageFactory, withDestroy, UrlUtils, ObjectUtils } from '@tapsellorg/angular-material-library/src/lib/common';
import { Subject, interval, timer, BehaviorSubject, race, takeWhile, last, concatMap, of, catchError as catchError$1, throwError, take as take$1, switchMap as switchMap$1, EMPTY } from 'rxjs';
import { takeUntil, map, filter, switchMap, catchError, take, tap } from 'rxjs/operators';
import * as i1$2 from '@angular/common/http';
import { HttpParams, HttpClient, HttpHeaders } from '@angular/common/http';
import Cookies from 'js-cookie';
import * as i1 from '@angular/router';
import { RouterModule } from '@angular/router';
import * as i2 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i3 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i4 from '@angular/material/button';
import { MatButtonModule } from '@angular/material/button';
import * as i5 from '@tapsellorg/angular-material-library/src/lib/overlay';
import { PghOverlayModule } from '@tapsellorg/angular-material-library/src/lib/overlay';
import * as i6 from '@angular/cdk/overlay';
import * as i7 from '@tapsellorg/angular-material-library/src/lib/status-label';
import { PghStatusLabelModule } from '@tapsellorg/angular-material-library/src/lib/status-label';
import * as i8 from '@angular/material/core';
import { MatRippleModule } from '@angular/material/core';
import * as i10 from '@tapsellorg/angular-material-library/src/lib/indicator';
import { PghIndicatorModule } from '@tapsellorg/angular-material-library/src/lib/indicator';
import * as i11 from '@tapsellorg/angular-material-library/media';
import { PghMediaModule } from '@tapsellorg/angular-material-library/media';
import * as i12 from '@tapsellorg/angular-material-library/src/lib/translate';
import { TranslateModule } from '@tapsellorg/angular-material-library/src/lib/translate';
import * as i10$1 from '@tapsellorg/angular-material-library';
import { UrlUtils as UrlUtils$1, PghGravatarModule } from '@tapsellorg/angular-material-library';
import * as i5$1 from '@angular/material/menu';
import { MatMenuModule } from '@angular/material/menu';
const PGH_REFRESH_TOKEN_REQUEST = (http, refreshToken, config) => {
const refreshTokenUrl = `${config.ssoApiBaseUrl}/sso/flow/refresh_token`;
const payload = new HttpParams().set('refreshToken', refreshToken);
return http.post(refreshTokenUrl, payload);
};
const PGH_GET_UUID_REQUEST = (http, authData, config) => {
const payload = new HttpParams()
.set('refresh_token', authData.refresh_token)
.set('access_token', authData.access_token);
const getUUidUrl = `${config.ssoApiBaseUrl}/sso/token2uuid`;
return http.post(getUUidUrl, payload, {
withCredentials: true,
});
};
const PGH_GET_TOKEN_REQUEST = (http, uuid, config) => {
const getUUidUrl = `${config.ssoApiBaseUrl}/sso/uuid2token/${uuid}`;
return http.get(getUUidUrl);
};
const PGH_TRUSTED_DOMAINS = [
'https://web.tapsell.com',
'https://app.tapsell.com',
'https://admin-web.tapsell.com',
'https://admin-app.tapsell.com',
'https://gravity.pegah.tech',
];
const PGH_EXPIRE_TOKEN_AFTER_LOGOUT = (http, authData, config) => {
const payload = new HttpParams()
.set('refresh_token', authData.refresh_token)
.set('access_token', authData.access_token);
const getUUidUrl = `${config.ssoApiBaseUrl}/sso/logout`;
return http.post(getUUidUrl, payload, {
withCredentials: true,
});
};
const PGH_SSO_CONFIG = new InjectionToken('sso-config', {
providedIn: 'root',
factory: () => ({}),
});
/**
* PGH_SSO_CONFIG is a partial version of PGH_SSO_ENRICHED_CONFIG so that it'll merge it with the default values
*/
const PGH_SSO_ENRICHED_CONFIG = new InjectionToken('sso-enriched-config', {
providedIn: 'root',
factory: () => {
const httpClient = inject(HttpClient);
const ssoConfig = inject(PGH_SSO_CONFIG);
const result = {
ssoPanelUrl: 'https://sso-panel.pegah.tech',
ssoApiBaseUrl: 'https://sso-api.pegah.tech',
restrictedUrls: ['https://unified-api.pegah.tech'],
impersonateApiUrl: 'https://sso-api.pegah.tech/impersonate/login',
sharedIframeUrl: 'https://auth-client.tapsell.ir',
isInsideSsoPanel: false,
changePasswordRoute: '/change-password',
profileRoute: '/profile',
trustedDomains: PGH_TRUSTED_DOMAINS,
isDevMode: false,
redirectToSsoAfterLogout: true,
pghCookieStoreDomain: 'tapsell.ir',
pghRedirectUrlParam: 'redirect',
refreshTokenRequest: refreshToken => PGH_REFRESH_TOKEN_REQUEST(httpClient, refreshToken, result),
getUUidRequest: authData => PGH_GET_UUID_REQUEST(httpClient, authData, result),
getTokenRequest: uuid => PGH_GET_TOKEN_REQUEST(httpClient, uuid, result),
expireTokenAfterLogout: authData => PGH_EXPIRE_TOKEN_AFTER_LOGOUT(httpClient, authData, result),
accessTokenExpiredError: err => err === 'webApi.unAuthorized.ExpiredAccessToken',
refreshTokenExpiredError: err => err === 'iam.unAuthorized.ExpiredAccessToken',
...ssoConfig,
};
return result;
},
});
// @dynamic
class PghSsoUtils {
static { this.AUTH_DATA_REQUIRED_KEYS = [
'accessToken',
'refreshToken',
]; }
static { this.AUTH_DATA_KEYS = ['accessToken', 'refreshToken']; }
static { this.UUID_PARAM = 'uuid'; }
static validateAuthData(data) {
return (this.AUTH_DATA_REQUIRED_KEYS.reduce((res, key) => res && !!data[key], true) &&
data.accessToken?.split('.').length === 3);
}
static isTokenMessage(data) {
return data.type === 'sso:auth';
}
static isLogoutMessage(data) {
return data.type === 'sso:logout';
}
static decodeJwtToken(accessToken) {
const base64Url = accessToken.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(atob(base64)
.split('')
.map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
.join(''));
return JSON.parse(jsonPayload);
}
static parseError(error) {
if (typeof error === 'string') {
try {
return JSON.parse(error);
}
catch {
throw new Error('Invalid JSON error response');
}
}
if (typeof error === 'object' && error !== null) {
return error;
}
throw new Error('Unsupported error format');
}
}
class PghSsoStorageService {
constructor(ssoConfig) {
this.ssoConfig = ssoConfig;
this.localStorageFactory = PghStorageFactory.localStorageFactory();
this.iframeIncomingMessages$ = new Subject();
this.isIframeLoaded = false;
this.IFRAME_ID = 'tapsell-sso-shared';
this.iframeMessageListener = ({ data, origin, source }) => {
if (origin !== this.ssoConfig.sharedIframeUrl || source !== this.sharedIframe.contentWindow)
return;
// console.log('#ee data, origin, source', data, origin, source);
this.iframeIncomingMessages$.next(data.tapsell);
};
this.setupIframeEventListeners();
this.initSharedIframe();
this.sharedIframe.addEventListener('load', () => (this.isIframeLoaded = true));
}
getDataFromStorage(key) {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
return this.localStorageFactory.getItem(key) || Cookies.get(key);
}
setDataInStorage(key, value) {
if (!value)
return;
if (this.getDataFromStorage(key) === value)
return;
this.storeCookieSecureCrossSite(key, value);
this.storeInLocalStorage(key, value);
}
deleteDataFromStorage(key) {
this.deleteCookie(key);
this.deleteFromLocalStorage(key);
}
storeCookieSecureCrossSite(key, value) {
Cookies.set(key, value, {
domain: this.ssoConfig.pghCookieStoreDomain,
path: '/',
sameSite: 'None',
secure: true,
expires: new Date(9999, 0),
});
}
deleteCookie(key) {
Cookies.remove(key, {
domain: this.ssoConfig.pghCookieStoreDomain,
path: '/',
sameSite: 'None',
secure: true,
});
}
storeInLocalStorage(key, value) {
this.localStorageFactory.setItem(key, value);
}
deleteFromLocalStorage(key) {
this.localStorageFactory.removeItem(key);
}
initSharedIframe() {
this.sharedIframe = document.getElementById(this.IFRAME_ID);
if (this.sharedIframe) {
this.isIframeLoaded = true;
return;
}
this.sharedIframe = document.createElement('iframe');
this.sharedIframe.src = this.ssoConfig.sharedIframeUrl;
this.sharedIframe.style.setProperty('display', 'none');
this.sharedIframe.id = this.IFRAME_ID;
this.sharedIframe.height = '0';
this.sharedIframe.name = this.IFRAME_ID;
this.sharedIframe.setAttribute('role', 'none');
document.body.appendChild(this.sharedIframe);
}
postMessageToIframe(data) {
if (!this.isIframeLoaded) {
const _interval$ = interval(50)
.pipe(takeUntil(timer(1000)))
.subscribe(() => {
if (this.isIframeLoaded) {
this.postMessageToIframe(data);
_interval$.unsubscribe();
}
});
return;
}
this.sharedIframe.contentWindow?.postMessage({ tapsell: data }, '*'); // todo targetOrigin
}
setupIframeEventListeners() {
window.addEventListener('message', this.iframeMessageListener);
}
ngOnDestroy() {
window.removeEventListener('message', this.iframeMessageListener);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoStorageService, deps: [{ token: PGH_SSO_ENRICHED_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoStorageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoStorageService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [PGH_SSO_ENRICHED_CONFIG]
}] }] });
class PghSsoService extends withDestroy() {
constructor(ssoConfig, ssoStorageService, router) {
super();
this.ssoConfig = ssoConfig;
this.ssoStorageService = ssoStorageService;
this.router = router;
this._authData$ = new BehaviorSubject(undefined);
this.authData$ = this._authData$.pipe(map(authData => {
if (!authData || !PghSsoUtils.validateAuthData(authData))
return;
const { userAccountData, adminAccountData, sub: email, } = PghSsoUtils.decodeJwtToken(authData.accessToken);
return {
...authData,
userId: userAccountData?.userId,
email,
impersonatedByAdmin: !!adminAccountData?.impersonated,
};
}));
this.isLoggedIn$ = race(this.authData$.pipe(filter(d => !!d)), interval(100).pipe(takeWhile(() => !this.ssoStorageService.isIframeLoaded, true), takeUntil(timer(1000)), last())).pipe(switchMap(_ => this.authData$.pipe(map(d => !!d))));
this.lastAuthStorePriority = 0;
this.setupIframeEventListeners();
this.retrieveTokenFromStorage();
this.retrieveTokenFromUrl();
this.authData$.pipe(takeUntil(this._destroyed$)).subscribe(data => {
this.authData = data;
});
}
retrieveTokenFromStorage() {
const partialAuthData = {
accessToken: this.ssoStorageService.getDataFromStorage('accessToken'),
refreshToken: this.ssoStorageService.getDataFromStorage('refreshToken'),
};
if (PghSsoUtils.validateAuthData(partialAuthData)) {
this._authData$.next(partialAuthData);
}
}
retrieveTokenFromUrl() {
const params = {};
new URLSearchParams(location.search).forEach((value, key) => {
params[key] = value;
});
if (!PghSsoUtils.validateAuthData(params))
return;
this.storeAuthData(params, 1);
UrlUtils.removeQueryParams(this.router, PghSsoUtils.AUTH_DATA_KEYS);
}
setupIframeEventListeners() {
let priority = 1;
this.ssoStorageService.iframeIncomingMessages$
.pipe(takeUntil(this._destroyed$), concatMap((value, index) => {
priority = index === 0 ? 0 : 1; // first emit has less priority
return of(value);
}))
.subscribe(data => {
// console.log('#ee iframe message', data);
if (PghSsoUtils.isTokenMessage(data)) {
if (!data.value)
return;
if (!PghSsoUtils.validateAuthData(data.value))
return;
this.storeAuthData(data.value, priority);
}
else if (PghSsoUtils.isLogoutMessage(data)) {
// Check for UUID in the URL
const uuid = new URLSearchParams(location.search).get(PghSsoUtils.UUID_PARAM);
if (!uuid) {
this.logout(priority);
}
}
});
}
storeAuthData(data, priority = 1) {
// console.log('#ee store auth data', data, priority, this.lastAuthStorePriority);
if (!PghSsoUtils.validateAuthData(data))
return;
if (priority < this.lastAuthStorePriority)
return;
this.lastAuthStorePriority = priority;
if (this.authData && ObjectUtils.isEqualObject(data, this.authData))
return;
this._authData$.next(data);
// console.log('#ee data', data);
this.ssoStorageService.postMessageToIframe({
type: 'sso:auth',
value: data,
});
PghSsoUtils.AUTH_DATA_KEYS.forEach(key => {
this.ssoStorageService.setDataInStorage(key, data[key]);
});
}
logout(priority = 1) {
// console.log('#ee logout', priority, this.lastAuthStorePriority);
if (priority < this.lastAuthStorePriority)
return;
this.lastAuthStorePriority = priority;
if (!this.authData)
return;
this.ssoConfig
.expireTokenAfterLogout({
access_token: this.authData.accessToken,
refresh_token: this.authData.refreshToken,
})
.pipe(switchMap(() => {
this._authData$.next(undefined);
this.ssoStorageService.postMessageToIframe({
type: 'sso:logout',
value: {},
});
PghSsoUtils.AUTH_DATA_KEYS.forEach(key => {
this.ssoStorageService.deleteDataFromStorage(key);
});
if (this.ssoConfig.redirectToSsoAfterLogout) {
this.redirectToLoginPageInSso();
}
return of(null);
}))
.subscribe();
}
redirectToLoginPageInSso() {
if (this.ssoConfig.isInsideSsoPanel) {
this.router.navigate(['/login']);
}
else {
location.href = `${this.ssoConfig.ssoPanelUrl}?${this.ssoConfig.pghRedirectUrlParam}=${encodeURIComponent(location.href)}`;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoService, deps: [{ token: PGH_SSO_ENRICHED_CONFIG }, { token: PghSsoStorageService }, { token: i1.Router }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [PGH_SSO_ENRICHED_CONFIG]
}] }, { type: PghSsoStorageService }, { type: i1.Router }] });
const PGH_SERVICES_SHORTCUTS_DEFAULT = [
{
link: 'https://sso-panel.pegah.tech',
name: 'SSO',
desc: 'مدیریت حساب',
logo: 'https://cdn.tapture.ir/tapsell/web/front/web-logo/tapsell-new/icons/circle/colored/color/Icon+50px.svg',
quickLinks: [
{
link: 'https://sso-panel.pegah.tech/profile',
name: 'پروفایل و حساب',
exposeTokenInUrl: false,
},
{
link: 'https://sso-panel.pegah.tech/financial-management',
name: 'مدیریت مالی',
exposeTokenInUrl: false,
},
{
link: 'https://sso-panel.pegah.tech/financial-management',
name: 'افزایش اعتبار',
exposeTokenInUrl: false,
},
],
exposeTokenInUrl: false,
},
{
link: 'https://dashboard.tapsell.ir',
name: 'تپسل',
desc: 'پلتفرم تبلیغات موبایل',
logo: 'https://cdn.tapture.ir/tapsell/web/front/web-logo/tapsell-new/icons/circle/colored/blue/Icon+50px.svg',
nightLogo: 'https://cdn.tapture.ir/tapsell/web/front/web-logo/tapsell-new/icons/circle/colored/blue/Icon+50px.svg',
quickLinks: [
{ link: 'https://dashboard.tapsell.ir/campaigns', name: 'کمپینها', exposeTokenInUrl: false },
{ link: 'https://dashboard.tapsell.ir/apps', name: 'اپلیکیشنها', exposeTokenInUrl: false },
{ link: 'https://college.tapsell.ir/', name: 'کالج', exposeTokenInUrl: false },
],
exposeTokenInUrl: false,
},
{
link: 'https://panel.mediaad.org',
name: 'مدیااد',
desc: 'پلتفرم تبلیغات وب',
logo: 'https://cdn.tapture.ir/tapsell/web/front/web-logo/tapsell-new/icons/circle/colored/green/Icon+50px.svg',
nightLogo: 'https://cdn.tapture.ir/tapsell/web/front/web-logo/tapsell-new/icons/circle/colored/green/Icon+50px.svg',
quickLinks: [
{ link: 'https://panel.mediaad.org/campaigns', name: 'کمپینها', exposeTokenInUrl: false },
],
exposeTokenInUrl: false,
},
];
class PghAuthorizedLinkDirective {
constructor(router, ssoService, elementRef, ssoConfig) {
this.router = router;
this.ssoService = ssoService;
this.elementRef = elementRef;
this.ssoConfig = ssoConfig;
this.exposeTokenInUrl = input(true);
}
onClick(event) {
event.preventDefault();
const linkElement = this.elementRef.nativeElement;
const href = linkElement.getAttribute('href');
const target = linkElement.getAttribute('target') ?? '_self';
if (!href || !this.ssoService.authData)
return;
const { accessToken, refreshToken } = this.ssoService.authData;
const isInternal = linkElement.hostname === window.location.hostname;
const mappedTokenData = {
access_token: accessToken,
refresh_token: refreshToken,
};
if (isInternal) {
const url = UrlUtils.removeOrigin(href);
this.router.navigateByUrl(url).then();
return;
}
(this.exposeTokenInUrl()
? of(UrlUtils.mergeParamsToUrl(href, { accessToken, refreshToken }))
: this.ssoConfig
.getUUidRequest(mappedTokenData)
.pipe(map(uuid => UrlUtils.mergeParamsToUrl(href, { [PghSsoUtils.UUID_PARAM]: uuid })))).subscribe({
next: newUrl => window.open(newUrl, target),
error: () => {
console.error('Failed to fetch UUID for authorized link.');
},
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghAuthorizedLinkDirective, deps: [{ token: i1.Router }, { token: PghSsoService }, { token: i0.ElementRef }, { token: PGH_SSO_ENRICHED_CONFIG }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.13", type: PghAuthorizedLinkDirective, isStandalone: false, selector: "a[pghAuthorizedLink]", inputs: { exposeTokenInUrl: { classPropertyName: "exposeTokenInUrl", publicName: "exposeTokenInUrl", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick($event)" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghAuthorizedLinkDirective, decorators: [{
type: Directive,
args: [{
selector: 'a[pghAuthorizedLink]',
standalone: false,
}]
}], ctorParameters: () => [{ type: i1.Router }, { type: PghSsoService }, { type: i0.ElementRef }, { type: undefined, decorators: [{
type: Inject,
args: [PGH_SSO_ENRICHED_CONFIG]
}] }], propDecorators: { onClick: [{
type: HostListener,
args: ['click', ['$event']]
}] } });
class PghServicesShortcutComponent {
constructor(darkModeService) {
this.darkModeService = darkModeService;
this.hideIndicator = input(false);
this.indicatorColor = input('primary');
this.servicesShortcuts = input(PGH_SERVICES_SHORTCUTS_DEFAULT);
this.isAdmin = input(false);
this.services = signal([]);
this.indicatorPersistData = signal({
persistId: 'services-shortcut',
persistDays: 7,
});
}
ngOnInit() {
this.setServicesShortcuts();
}
ngOnChanges(changes) {
if (changes.servicesShortcuts) {
this.setServicesShortcuts();
}
}
setServicesShortcuts() {
this.services.set(this.servicesShortcuts().map(service => ({
...service,
isCurrentService: service.link.includes(location.hostname),
})));
}
get isDarkModeEnabled() {
return this.darkModeService.isDarkModeEnabled;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghServicesShortcutComponent, deps: [{ token: i1$1.PghDarkModeService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.13", type: PghServicesShortcutComponent, isStandalone: false, selector: "pgh-services-shortcut", inputs: { hideIndicator: { classPropertyName: "hideIndicator", publicName: "hideIndicator", isSignal: true, isRequired: false, transformFunction: null }, indicatorColor: { classPropertyName: "indicatorColor", publicName: "indicatorColor", isSignal: true, isRequired: false, transformFunction: null }, servicesShortcuts: { classPropertyName: "servicesShortcuts", publicName: "servicesShortcuts", isSignal: true, isRequired: false, transformFunction: null }, isAdmin: { classPropertyName: "isAdmin", publicName: "isAdmin", isSignal: true, isRequired: false, transformFunction: null } }, usesOnChanges: true, ngImport: i0, template: "<pgh-overlay\n [origin]=\"servicesMenuOriginRef\"\n #servicesMenuRef\n [panelClasses]=\"['pgh-services-shortcut-menu']\"\n>\n <ng-template #pghOverlayContent>\n <a\n *ngFor=\"let s of services()\"\n pghAuthorizedLink\n [href]=\"s.link\"\n [exposeTokenInUrl]=\"s.exposeTokenInUrl\"\n target=\"_blank\"\n class=\"pgh-service-shortcut-item text-gray\"\n [class.is-active]=\"s.isCurrentService\"\n matRipple\n >\n <div class=\"pgh-service-item-img\">\n <img\n class=\"max-width-100\"\n [src]=\"isDarkModeEnabled ? (s.nightLogo ? s.nightLogo : s.logo) : s.logo\"\n [alt]=\"s.name\"\n />\n </div>\n <div class=\"pgh-service-item-name d-flex align-items-center\">\n <h2 class=\"mb-0 font-weight-bold text-gray-700\">{{ s.name }}</h2>\n <ng-container *ngIf=\"s.desc\">\n <span class=\"mx-2\">-</span>\n <span class=\"text-gray\">{{ s.desc }}</span>\n </ng-container>\n </div>\n <div class=\"pgh-service-item-quick-links d-flex\">\n <a\n *ngFor=\"let q of s.quickLinks\"\n pghAuthorizedLink\n [href]=\"q.link\"\n target=\"_blank\"\n [exposeTokenInUrl]=\"s.exposeTokenInUrl\"\n >\n <pgh-status-label\n [showIcon]=\"false\"\n [label]=\"q.name\"\n labelSize=\"mini\"\n type=\"gray\"\n ></pgh-status-label>\n </a>\n </div>\n </a>\n </ng-template>\n</pgh-overlay>\n\n<button\n mat-button\n cdkOverlayOrigin\n #servicesMenuOriginRef=\"cdkOverlayOrigin\"\n (click)=\"servicesMenuRef.open()\"\n>\n <mat-icon\n svgIcon=\"apps\"\n pghIndicator\n [pghIndicatorHidden]=\"hideIndicator()\"\n [pghIndicatorColor]=\"indicatorColor()\"\n [pghIndicatorPersistData]=\"indicatorPersistData()\"\n [pghIndicatorPosition]=\"'top start'\"\n ></mat-icon>\n <ng-container *ngIf=\"isAdmin(); else userServices\">\n <span *ifMedia=\"'sm'\">{{ 'SSO_ADMIN_SERVICES_SHORTCUT_TITLE' | translate }}</span>\n </ng-container>\n <ng-template #userServices>\n <span *ifMedia=\"'sm'\">{{ 'SSO_SERVICES_SHORTCUT_TITLE' | translate }}</span>\n </ng-template>\n</button>\n", styles: [".pgh-service-shortcut-item{cursor:pointer;padding:1rem;display:grid;grid-template-areas:\"logo title\" \"logo quicklinks\";grid-template-rows:auto auto;grid-template-columns:3.5rem minmax(15rem,auto);align-items:center;grid-gap:0 1rem}.pgh-service-shortcut-item:hover{background:var(--eee)}.pgh-service-shortcut-item:not(:last-child){border-bottom:1px solid var(--light-border-color)}.pgh-service-shortcut-item.is-active{background-color:var(--primary-50)}.pgh-service-item-img{grid-area:logo}.pgh-service-item-name{grid-area:title}.pgh-service-item-quick-links{grid-area:quicklinks}.pgh-services-shortcut-menu.pgh-overlay{padding-block:.5rem;padding-inline:0}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i5.PghOverlayComponent, selector: "pgh-overlay", inputs: ["origin", "panelClasses"], exportAs: ["pghOverlay"] }, { kind: "directive", type: i6.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: i7.PghStatusLabelComponent, selector: "pgh-status-label", inputs: ["type", "label", "showIcon", "typeMapping", "styleMode", "labelSize"] }, { kind: "directive", type: i8.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "directive", type: PghAuthorizedLinkDirective, selector: "a[pghAuthorizedLink]", inputs: ["exposeTokenInUrl"] }, { kind: "directive", type: i10.PghIndicatorDirective, selector: "[pghIndicator]", inputs: ["pghIndicatorColor", "pghIndicatorPersistData", "pghIndicatorPosition", "pghIndicatorHidden"], outputs: ["pghIndicatorHiddenChange"], exportAs: ["pghIndicator"] }, { kind: "directive", type: i11.PghMediaDirective, selector: "[ifMedia]", inputs: ["ifMedia"] }, { kind: "pipe", type: i12.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghServicesShortcutComponent, decorators: [{
type: Component,
args: [{ selector: 'pgh-services-shortcut', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<pgh-overlay\n [origin]=\"servicesMenuOriginRef\"\n #servicesMenuRef\n [panelClasses]=\"['pgh-services-shortcut-menu']\"\n>\n <ng-template #pghOverlayContent>\n <a\n *ngFor=\"let s of services()\"\n pghAuthorizedLink\n [href]=\"s.link\"\n [exposeTokenInUrl]=\"s.exposeTokenInUrl\"\n target=\"_blank\"\n class=\"pgh-service-shortcut-item text-gray\"\n [class.is-active]=\"s.isCurrentService\"\n matRipple\n >\n <div class=\"pgh-service-item-img\">\n <img\n class=\"max-width-100\"\n [src]=\"isDarkModeEnabled ? (s.nightLogo ? s.nightLogo : s.logo) : s.logo\"\n [alt]=\"s.name\"\n />\n </div>\n <div class=\"pgh-service-item-name d-flex align-items-center\">\n <h2 class=\"mb-0 font-weight-bold text-gray-700\">{{ s.name }}</h2>\n <ng-container *ngIf=\"s.desc\">\n <span class=\"mx-2\">-</span>\n <span class=\"text-gray\">{{ s.desc }}</span>\n </ng-container>\n </div>\n <div class=\"pgh-service-item-quick-links d-flex\">\n <a\n *ngFor=\"let q of s.quickLinks\"\n pghAuthorizedLink\n [href]=\"q.link\"\n target=\"_blank\"\n [exposeTokenInUrl]=\"s.exposeTokenInUrl\"\n >\n <pgh-status-label\n [showIcon]=\"false\"\n [label]=\"q.name\"\n labelSize=\"mini\"\n type=\"gray\"\n ></pgh-status-label>\n </a>\n </div>\n </a>\n </ng-template>\n</pgh-overlay>\n\n<button\n mat-button\n cdkOverlayOrigin\n #servicesMenuOriginRef=\"cdkOverlayOrigin\"\n (click)=\"servicesMenuRef.open()\"\n>\n <mat-icon\n svgIcon=\"apps\"\n pghIndicator\n [pghIndicatorHidden]=\"hideIndicator()\"\n [pghIndicatorColor]=\"indicatorColor()\"\n [pghIndicatorPersistData]=\"indicatorPersistData()\"\n [pghIndicatorPosition]=\"'top start'\"\n ></mat-icon>\n <ng-container *ngIf=\"isAdmin(); else userServices\">\n <span *ifMedia=\"'sm'\">{{ 'SSO_ADMIN_SERVICES_SHORTCUT_TITLE' | translate }}</span>\n </ng-container>\n <ng-template #userServices>\n <span *ifMedia=\"'sm'\">{{ 'SSO_SERVICES_SHORTCUT_TITLE' | translate }}</span>\n </ng-template>\n</button>\n", styles: [".pgh-service-shortcut-item{cursor:pointer;padding:1rem;display:grid;grid-template-areas:\"logo title\" \"logo quicklinks\";grid-template-rows:auto auto;grid-template-columns:3.5rem minmax(15rem,auto);align-items:center;grid-gap:0 1rem}.pgh-service-shortcut-item:hover{background:var(--eee)}.pgh-service-shortcut-item:not(:last-child){border-bottom:1px solid var(--light-border-color)}.pgh-service-shortcut-item.is-active{background-color:var(--primary-50)}.pgh-service-item-img{grid-area:logo}.pgh-service-item-name{grid-area:title}.pgh-service-item-quick-links{grid-area:quicklinks}.pgh-services-shortcut-menu.pgh-overlay{padding-block:.5rem;padding-inline:0}\n"] }]
}], ctorParameters: () => [{ type: i1$1.PghDarkModeService }] });
class PghAuthorizedLinkPipe {
constructor(ssoService) {
this.ssoService = ssoService;
}
transform(link) {
if (!link)
return link;
if (!this.ssoService.authData)
return link;
return UrlUtils$1.mergeParamsToUrl(link, this.ssoService.authData);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghAuthorizedLinkPipe, deps: [{ token: PghSsoService }], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.13", ngImport: i0, type: PghAuthorizedLinkPipe, isStandalone: false, name: "pghAuthorizedLink" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghAuthorizedLinkPipe, decorators: [{
type: Pipe,
args: [{
name: 'pghAuthorizedLink',
standalone: false,
}]
}], ctorParameters: () => [{ type: PghSsoService }] });
class PghSsoAuthorizedLinkModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedLinkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedLinkModule, declarations: [PghAuthorizedLinkDirective, PghAuthorizedLinkPipe], imports: [CommonModule], exports: [PghAuthorizedLinkDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedLinkModule, imports: [CommonModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedLinkModule, decorators: [{
type: NgModule,
args: [{
declarations: [PghAuthorizedLinkDirective, PghAuthorizedLinkPipe],
imports: [CommonModule],
exports: [PghAuthorizedLinkDirective],
}]
}] });
class PghServicesShortcutModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghServicesShortcutModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.13", ngImport: i0, type: PghServicesShortcutModule, declarations: [PghServicesShortcutComponent], imports: [CommonModule,
MatIconModule,
MatButtonModule,
PghOverlayModule,
PghStatusLabelModule,
MatRippleModule,
PghSsoAuthorizedLinkModule,
PghIndicatorModule,
PghMediaModule,
TranslateModule], exports: [PghServicesShortcutComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghServicesShortcutModule, imports: [CommonModule,
MatIconModule,
MatButtonModule,
PghOverlayModule,
PghStatusLabelModule,
MatRippleModule,
PghSsoAuthorizedLinkModule,
PghIndicatorModule,
PghMediaModule,
TranslateModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghServicesShortcutModule, decorators: [{
type: NgModule,
args: [{
declarations: [PghServicesShortcutComponent],
imports: [
CommonModule,
MatIconModule,
MatButtonModule,
PghOverlayModule,
PghStatusLabelModule,
MatRippleModule,
PghSsoAuthorizedLinkModule,
PghIndicatorModule,
PghMediaModule,
TranslateModule,
],
exports: [PghServicesShortcutComponent],
}]
}] });
class PghSsoRedirectService extends withDestroy() {
constructor(activatedRoute, router, pghSsoService, ssoConfig) {
super();
this.activatedRoute = activatedRoute;
this.router = router;
this.pghSsoService = pghSsoService;
this.ssoConfig = ssoConfig;
this.setupRedirectUrlRetriever();
}
setupRedirectUrlRetriever() {
const params = {};
new URLSearchParams(location.search).forEach((value, key) => {
params[key] = value;
});
this.retrieveRedirectUrl(params);
this.activatedRoute.queryParams.pipe(takeUntil(this._destroyed$)).subscribe(queryParams => {
this.retrieveRedirectUrl(queryParams);
});
}
retrieveRedirectUrl(queryParams) {
const { redirect } = queryParams;
if (!redirect)
return;
try {
const redirectUrl = new URL(redirect.trim());
const trustedOrigins = this.ssoConfig.trustedDomains.map(url => new URL(url).origin);
const { isDevMode } = this.ssoConfig;
const isLocalhost = isDevMode && ['localhost', '127.0.0.1', '::1'].includes(redirectUrl.hostname);
const isTrusted = isLocalhost || trustedOrigins.includes(redirectUrl.origin);
if (!isTrusted)
return;
this.redirectUrl = redirectUrl.href;
return this.redirectUrl;
}
catch (error) {
// If the redirect URL is invalid or malformed, silently ignore
return;
}
}
retrieveUuidAndNavigate(tokenData) {
this.ssoConfig.getUUidRequest(tokenData).subscribe({
next: uuid => {
const uuidParam = { [PghSsoUtils.UUID_PARAM]: uuid };
location.href = UrlUtils.mergeParamsToUrl(this.redirectUrl, uuidParam);
},
error: error => {
console.error('UUID retrieval failed', error);
},
});
}
navigateToRetrievedRedirectUrl(useParseUrl = false) {
const routerNavigateFunction = (route) => useParseUrl ? this.router.parseUrl(route) : this.router.navigateByUrl(route);
if (!this.redirectUrl) {
return routerNavigateFunction('/');
}
const redirectUrlParsed = new URL(this.redirectUrl);
if (redirectUrlParsed.origin === location.origin) {
return routerNavigateFunction(redirectUrlParsed.pathname);
}
if (!this.pghSsoService.authData) {
location.href = this.redirectUrl;
return false;
}
const tokenData = {
access_token: this.pghSsoService.authData.accessToken,
refresh_token: this.pghSsoService.authData.refreshToken,
};
this.retrieveUuidAndNavigate(tokenData);
return false;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoRedirectService, deps: [{ token: i1.ActivatedRoute }, { token: i1.Router }, { token: PghSsoService }, { token: PGH_SSO_ENRICHED_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoRedirectService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoRedirectService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i1.Router }, { type: PghSsoService }, { type: undefined, decorators: [{
type: Inject,
args: [PGH_SSO_ENRICHED_CONFIG]
}] }] });
class PghSsoAuthorizedGuard {
constructor(ssoService, pghSsoRedirectService, router, ssoConfig) {
this.ssoService = ssoService;
this.pghSsoRedirectService = pghSsoRedirectService;
this.router = router;
this.ssoConfig = ssoConfig;
}
canActivate(route, _state) {
if (this.ssoConfig.isInsideSsoPanel) {
this.pghSsoRedirectService.retrieveRedirectUrl(route.queryParams);
}
const uuid = route.queryParamMap.get(PghSsoUtils.UUID_PARAM);
return uuid ? this.authenticateWithUuid(uuid) : this.verifyLoginStatus();
}
authenticateWithUuid(uuid) {
return this.ssoConfig.getTokenRequest(uuid).pipe(switchMap(authData => this.handleAuthData(authData)), catchError(() => this.redirectToLogin()));
}
handleAuthData(authData) {
if (!authData?.access_token)
return this.redirectToLogin();
this.ssoService.storeAuthData({
accessToken: authData.access_token,
refreshToken: authData.refresh_token,
});
UrlUtils.removeQueryParams(this.router, [PghSsoUtils.UUID_PARAM]);
return this.verifyLoginStatus();
}
verifyLoginStatus() {
return this.ssoService.isLoggedIn$.pipe(take(1), map(authData => {
if (authData) {
return true;
}
this.ssoService.redirectToLoginPageInSso();
return false;
}));
}
redirectToLogin() {
this.ssoService.redirectToLoginPageInSso();
return of(false);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedGuard, deps: [{ token: PghSsoService }, { token: PghSsoRedirectService }, { token: i1.Router }, { token: PGH_SSO_ENRICHED_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedGuard, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghSsoAuthorizedGuard, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: () => [{ type: PghSsoService }, { type: PghSsoRedirectService }, { type: i1.Router }, { type: undefined, decorators: [{
type: Inject,
args: [PGH_SSO_ENRICHED_CONFIG]
}] }] });
class PghUserMenuComponent extends withDestroy() {
constructor(ssoConfig, ssoService, router, cdr, darkModeService) {
super();
this.ssoConfig = ssoConfig;
this.ssoService = ssoService;
this.router = router;
this.cdr = cdr;
this.darkModeService = darkModeService;
this.userEmail = signal(this.ssoService.authData?.email);
this.isAvatarNotLoaded = signal(false);
this.userName = input(undefined);
this.handleLogout = input(true);
this.logout = output();
this._destroyed$ = new Subject();
}
ngOnInit() {
this.ssoService.authData$.pipe(takeUntil(this._destroyed$)).subscribe(data => {
this.userEmail.set(data?.email);
this.isAvatarNotLoaded.set(false);
this.cdr.detectChanges();
});
}
onLogout() {
this.logout.emit();
if (!this.handleLogout())
return;
this.ssoService.logout();
}
toggleDarkMode() {
this.darkModeService.toggleDarkMode();
}
get isDarkModeEnabled() {
return this.darkModeService.isDarkModeEnabled;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghUserMenuComponent, deps: [{ token: PGH_SSO_ENRICHED_CONFIG }, { token: PghSsoService }, { token: i1.Router }, { token: i0.ChangeDetectorRef }, { token: i1$1.PghDarkModeService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.13", type: PghUserMenuComponent, isStandalone: false, selector: "pgh-user-menu", inputs: { userName: { classPropertyName: "userName", publicName: "userName", isSignal: true, isRequired: false, transformFunction: null }, handleLogout: { classPropertyName: "handleLogout", publicName: "handleLogout", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { logout: "logout" }, usesInheritance: true, ngImport: i0, template: "<button class=\"py-2\" mat-button [matMenuTriggerFor]=\"menuRef\" [class.px-0]=\"!userName()\">\n <img\n *ngIf=\"userEmail()\"\n [src]=\"userEmail() | pghGravatar : 80\"\n class=\"border-radius-circle\"\n [width]=\"userName() ? 30 : 40\"\n [height]=\"userName() ? 30 : 40\"\n alt=\"\"\n (error)=\"isAvatarNotLoaded.set(true)\"\n />\n <mat-icon\n *ngIf=\"!userEmail() || isAvatarNotLoaded()\"\n svgIcon=\"account_circle\"\n class=\"square-40 text-gray\"\n ></mat-icon>\n <ng-template [ngIf]=\"userName()\">\n <span *ifMedia=\"'sm'\" class=\"ms-2\">{{ userName() }}</span>\n </ng-template>\n</button>\n\n<mat-menu #menuRef=\"matMenu\">\n <a\n [href]=\"ssoConfig.ssoPanelUrl + ssoConfig.profileRoute\"\n pghAuthorizedLink\n [exposeTokenInUrl]=\"false\"\n mat-menu-item\n class=\"text-black\"\n target=\"_blank\"\n >\n <mat-icon svgIcon=\"account_circle\"></mat-icon>\n <span *ifMedia=\"'sm'\">{{ 'SSO_USER_MENU_USER_PROFILE' | translate }}</span>\n <span *ifMedia=\"'max-xs'\">\n {{ userName() ? userName() : ('SSO_USER_MENU_USER_PROFILE' | translate) }}\n </span>\n </a>\n\n <button mat-menu-item (click)=\"toggleDarkMode()\">\n <mat-icon [svgIcon]=\"isDarkModeEnabled ? 'light_mode' : 'dark_mode'\"></mat-icon>\n <span>\n {{ (isDarkModeEnabled ? 'SSO_USER_MENU_LIGHT_MODE' : 'SSO_USER_MENU_DARK_MODE') | translate }}\n </span>\n </button>\n\n <a\n [href]=\"ssoConfig.ssoPanelUrl + ssoConfig.changePasswordRoute\"\n pghAuthorizedLink\n [exposeTokenInUrl]=\"false\"\n mat-menu-item\n class=\"text-black\"\n target=\"_blank\"\n >\n <mat-icon svgIcon=\"lock\"></mat-icon>\n <span>{{ 'SSO_USER_MENU_CHANGE_PASSWORD' | translate }}</span>\n </a>\n\n <button mat-menu-item (click)=\"onLogout()\">\n <mat-icon svgIcon=\"logout\"></mat-icon>\n <span>{{ 'SSO_USER_MENU_LOGOUT' | translate }}</span>\n </button>\n</mat-menu>\n", styles: [""], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i5$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PghAuthorizedLinkDirective, selector: "a[pghAuthorizedLink]", inputs: ["exposeTokenInUrl"] }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i11.PghMediaDirective, selector: "[ifMedia]", inputs: ["ifMedia"] }, { kind: "pipe", type: i10$1.PghGravatarPipe, name: "pghGravatar" }, { kind: "pipe", type: i12.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: PghUserMenuComponent, decorators: [{
type: Component,
args: [{ selector: 'pgh-user-menu', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<button class=\"py-2\" mat-button [matMenuTriggerFor]=\"menuRef\" [class.px-0]=\"!userName()\">\n <img\n *ngIf=\"userEmail()\"\n [src]=\"userEmail() | pghGravatar : 80\"\n class=\"border-radius-circle\"\n [width]=\"userName() ? 30 : 40\"\n [height]=\"userName() ? 30 : 40\"\n alt=\"\"\n (error)=\"isAvatarNotLoaded.set(true)\"\n />\n <mat-icon\n *ngIf=\"!userEmail() || isAvatarNotLoaded()\"\n svgIcon=\"account_circle\"\n class=\"square-40 text-gray\"\n ></mat-icon>\n <ng-template [ngIf]=\"userName()\">\n <span *ifMedia=\"'sm'\" class=\"ms-2\">{{ userName() }}</span>\n </ng-template>\n</button>\n\n<mat-menu #menuRef=\"matMenu\">\n <a\n [href]=\"ssoConfig.ssoPanelUrl + ssoConfig.profileRoute\"\n pghAuthorizedLink\n [exposeTokenInUrl]=\"false\"\n mat-menu-item\n class=\"text-black\"\n target=\"_blank\"\n >\n <mat-icon svgIcon=\"account_circle\"></mat-icon>\n <span *ifMedia=\"'sm'\">{{ 'SSO_USER_MENU_USER