@engie-group/ngx-gem-spaas
Version:
This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.
2,546 lines • 183 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, Component, InjectionToken, Inject, Optional, Input, ViewChild, EventEmitter, Output, NgModule, ElementRef, Directive, HostListener, ContentChild, Injector, ChangeDetectionStrategy, provideAppInitializer, inject } from '@angular/core';
import { ReplaySubject, Subject, filter, timer, fromEvent, BehaviorSubject, catchError, throwError } from 'rxjs';
import * as i1 from '@angular/material/bottom-sheet';
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
import * as i2 from '@angular/service-worker';
import { ServiceWorkerModule } from '@angular/service-worker';
import { take, takeUntil, map } from 'rxjs/operators';
import * as i3 from '@angular/cdk/platform';
import * as i1$1 from '@angular/common';
import { CommonModule } from '@angular/common';
import * as i2$1 from '@angular/platform-browser';
import * as i4$1 from '@angular/forms';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
import * as i3$1 from '@angular/router';
import { NavigationStart, RouterModule } from '@angular/router';
import { OktaAuth } from '@okta/okta-auth-js';
import * as i5 from '@angular/material/progress-bar';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import * as i1$2 from '@angular/material/snack-bar';
import { MatSnackBarModule, MatSnackBarConfig } from '@angular/material/snack-bar';
import * as i5$1 from '@angular/material/radio';
import { MatRadioModule, MAT_RADIO_DEFAULT_OPTIONS } from '@angular/material/radio';
import * as i3$3 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';
import * as i4 from '@angular/material/tooltip';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import * as i3$2 from '@angular/cdk/drag-drop';
import { DragDropModule } from '@angular/cdk/drag-drop';
import * as i3$4 from '@angular/material/menu';
import { MatMenuModule } from '@angular/material/menu';
var EmbedModeEnum;
(function (EmbedModeEnum) {
EmbedModeEnum["none"] = "";
EmbedModeEnum["iframe"] = "iframe";
})(EmbedModeEnum || (EmbedModeEnum = {}));
class EmbedModeModel {
constructor() {
this.parent = '';
this.pwd = '';
this.type = EmbedModeEnum.none;
this.usr = '';
}
isIframe() {
return this.type === EmbedModeEnum.iframe;
}
}
class EmbedModeService {
constructor() {
this.POST_MESSAGE_GETTHEME = 'getTheme';
this.embedMode = new EmbedModeModel();
this.embedMode$ = new ReplaySubject(1);
this.embeddedWindow = null;
}
static getIframeParent() {
const ref = document.referrer || '';
if (ref) {
const url = new URL(ref);
if (url.pathname !== '/') {
return url.pathname.replace(/\//g, '');
}
else {
const subdomain = url.hostname.split('.')[0] || '';
if (!subdomain.includes('cylon')) {
return subdomain;
}
}
}
return '';
}
// setEmbedMode is called from the app-init.service
setEmbedMode() {
if (window.location !== window.parent.location) {
// iframe mode
this.embedMode.type = EmbedModeEnum.iframe;
this.embedMode.parent = EmbedModeService.getIframeParent();
}
this.newEmbedMode();
}
// ********************************************************************************************************
// LOAD DATA
// ********************************************************************************************************
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newEmbedMode() {
// console.log('embed mode set: ' + (this.embedMode.type || 'none'));
this.embedMode$.next(this.embedMode);
}
onNewEmbedMode() {
return this.embedMode$.asObservable();
}
getEmbedMode() {
return this.embedMode;
}
getEmbeddedWindow() {
return this.embeddedWindow;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbedModeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbedModeService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbedModeService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
class BaseComponent {
constructor() {
this.onDestroy$ = new Subject();
}
ngOnDestroy() {
this.onDestroy$.next();
this.onDestroy$.complete();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: BaseComponent, isStandalone: false, selector: "spaas-base", ngImport: i0, template: '', isInline: true }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BaseComponent, decorators: [{
type: Component,
args: [{
selector: 'spaas-base',
template: '',
standalone: false
}]
}] });
const WINDOW = new InjectionToken('Window', {
providedIn: 'root',
factory: () => window
});
class WindowUtilsService {
constructor(window) {
this.window = window;
}
getWindowWidth() {
return this.window.innerWidth;
}
getWindowHeight() {
return this.window.innerHeight;
}
getUserAgent() {
return this.window.navigator.userAgent;
}
getLanguage() {
return this.window.navigator.language;
}
isOnline() {
return this.window.navigator.onLine;
}
getOrigin() {
return this.window.location.origin;
}
reloadPage() {
this.window.location.reload();
}
redirectTo(url) {
this.window.location.href = url;
}
getLocation() {
return this.window.location;
}
openWindow(url) {
this.window.open(url, '_blank');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: WindowUtilsService, deps: [{ token: WINDOW }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: WindowUtilsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: WindowUtilsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: Window, decorators: [{
type: Inject,
args: [WINDOW]
}] }] });
class NewVersionComponent extends BaseComponent {
constructor(bottomSheetRef, windowUtilsService) {
super();
this.bottomSheetRef = bottomSheetRef;
this.windowUtilsService = windowUtilsService;
}
reload() {
this.bottomSheetRef.dismiss();
this.windowUtilsService.reloadPage();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NewVersionComponent, deps: [{ token: i1.MatBottomSheetRef }, { token: WindowUtilsService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: NewVersionComponent, isStandalone: false, selector: "spaas-new-version", usesInheritance: true, ngImport: i0, template: "<div class=\"txt-center\">\r\n new version available\r\n <div class=\"flex center pad-big-top\">\r\n <button class=\"primary bold\" (click)=\"reload()\">\r\n load it now\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NewVersionComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-new-version', standalone: false, template: "<div class=\"txt-center\">\r\n new version available\r\n <div class=\"flex center pad-big-top\">\r\n <button class=\"primary bold\" (click)=\"reload()\">\r\n load it now\r\n </button>\r\n </div>\r\n</div>\r\n" }]
}], ctorParameters: () => [{ type: i1.MatBottomSheetRef }, { type: WindowUtilsService }] });
class UtilsService {
static copy(objIn) {
return JSON.parse(JSON.stringify(objIn));
}
// DISTINCT SORTED LIST WITHOUT NULL/UNDEFINED VALUES
static distinct(listIn, prefix = '', sortAsc = true) {
const sortCorr = sortAsc ? 1 : -1;
let listOut = listIn
.filter((value, index, self) => value && self.indexOf(value) === index)
.sort((a, b) => a < b ? -1 * sortCorr : 1 * sortCorr);
if (prefix) {
listOut = listOut.map((c) => prefix + c);
}
return listOut;
}
static round(num, dec) {
if (num === null || num === undefined) {
return null;
}
return Number((num).toFixed(dec));
}
static checkJSON(itemToCheck) {
let item = {};
try {
item = JSON.parse(itemToCheck);
}
catch (e) {
return false;
}
return typeof item === 'object' && item !== null;
}
static convertToValidNumOrNull(inputValue, isToFloor = false) {
if (inputValue === null || inputValue === '') {
return null;
}
const nv = inputValue.toString().trim().toLowerCase();
const nvNum = Number(nv.replace(',', '.'));
return Number.isNaN(nvNum) ? null : isToFloor ? Math.floor(nvNum) : nvNum;
}
static hasProp(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UtilsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UtilsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
/**
* Okta configuration object to be provided via "forRoot" method of the SpaasModule.
*
* @property {string[]} additionalScopes the scopes needed for your particular back-end
* @property {string} clientId the client id of your SPA
* @property {boolean} interceptAddContentHeader whether to automatically add the "json" content-type header
* to non-GET, intercepted http-requests (optional, default is true)
* @property {string[]} interceptUrls the urls to intercept and add an Authorization - Bearer header to
* @property {string} tenantId the tenant id of your Okta issuer
* @property {string} url the url of your Okta issuer
* @property {boolean} withPath false for subdomains, true for context (optional, default is false)
*/
class OktaConfigModel {
constructor(objIn) {
this.additionalScopes = [];
this.clientId = '';
this.interceptAddContentHeader = true;
this.interceptUrls = [];
this.tenantId = '';
this.url = '';
this.withPath = false;
this.additionalScopes = objIn.additionalScopes || [];
this.clientId = objIn.clientId || '';
this.interceptAddContentHeader = UtilsService.hasProp(objIn, 'interceptAddContentHeader') ? objIn.interceptAddContentHeader : true;
this.interceptUrls = objIn.interceptUrls || [];
this.tenantId = objIn.tenantId || '';
this.url = objIn.url || '';
this.withPath = UtilsService.hasProp(objIn, 'withPath') ? objIn.withPath : false;
}
}
class OktaUserModel {
constructor(props) {
this.email = props?.email || '';
this.firstName = props?.firstName || '';
this.groups = props?.groups || [];
this.lastName = props?.lastName || '';
this.userId = props.userid || props.userId || ''; // props.userId is for when OktaUserModel is extended and fed itself as props
}
static stripMail(strIn) {
return strIn ? strIn.replace('@engie.com', '').replace('@external.engie.com', '') : '';
}
checkGroup(group) {
return this.groups.some((g) => g.toLowerCase().startsWith((group || '').toLowerCase()));
}
}
/**
* New version configuration object to be provided via "forRoot" method of the SpaasModule.
*
* @property {number} reminder default is zero. If not zero and hasBackdrop === true, this sets the interval
* (in minutes) at which to prompt the user to load the newly deployed version. Will be floored to a 5-minute minimum.
* @property {boolean} hasBackdrop default is true. If false, no backdrop is shown for the bottom-sheet pop-up (and
* so the pop-up can only be dismissed by accepting the new version).
*/
class NewVersionConfigModel {
constructor(objIn) {
this.reminder = 0;
this.hasBackdrop = true;
this.reminder = objIn.reminder ? Math.max(objIn.reminder, 5) : 0;
this.hasBackdrop = objIn.hasOwnProperty('hasBackdrop') ? objIn.hasBackdrop : true;
}
}
/**
* Library configuration object to be provided via "forRoot" method of the SpaasModule.
*
* @property {string} appName the application name. Will be shown in browser tab and will be used as storage prefix
* @property {string} environment will be used as storage prefix, in combination with appName
* @property {OktaConfigModel} oktaConfig the Okta configuration for this project
* @property {NewVersionConfigModel} newVersionConfig the configuration for the new version handling
*/
class SpaasConfigModel {
constructor(objIn) {
this.appName = '';
this.environment = '';
this.oktaConfig = new OktaConfigModel({});
this.newVersionConfig = new NewVersionConfigModel({});
this.appName = objIn.appName || '';
this.environment = objIn.environment || '';
this.oktaConfig = new OktaConfigModel(objIn.oktaConfig || {});
this.newVersionConfig = new NewVersionConfigModel(objIn.newVersionConfig || {});
}
}
class SpaasExtConfigModel extends SpaasConfigModel {
constructor(conf) {
super(conf);
this.cleanAppName = this.appName.charAt(0).toUpperCase() + this.appName.substring(1, this.appName.length).toLowerCase();
this.storagePrefix = (this.appName || this.oktaConfig?.clientId) + '-' + this.environment + '-';
}
}
class NewVersionService {
constructor(spaasConfig, bottomSheet, swUpdate) {
this.spaasConfig = spaasConfig;
this.bottomSheet = bottomSheet;
this.swUpdate = swUpdate;
// we get the raw spaasConfig provided by the client app, not the one from the ConfigService (because
// this is called from appInit, so we cannot rely on the NewVersionConfigModel constructor making things clean.
// Hence, always do a new NewVersionConfigModel
}
getNewVersion() {
// LISTEN FOR NEW VERSIONS
if (!this.swUpdate?.isEnabled) {
return;
}
this.swUpdate.versionUpdates
.pipe(filter((evt) => evt.type === 'VERSION_READY'))
.subscribe(() => {
const cfg = new NewVersionConfigModel(this.spaasConfig?.newVersionConfig || {});
this.bottomSheet.open(NewVersionComponent, { hasBackdrop: cfg.hasBackdrop });
this.startTimer();
});
}
startTimer() {
const cfg = new NewVersionConfigModel(this.spaasConfig?.newVersionConfig || {});
if (cfg.reminder && cfg.hasBackdrop) {
// if reminder is set and hasBackdrop is true, just start the timer (if no backdrop, the pop-up will stay open, no need for a reminder)
// if the user has accepted the new version anyway, the page will reload
// and after page reload, the timer will not be started again, because there will no longer be a new version
timer(cfg.reminder * 60000, cfg.reminder * 60000)
.subscribe(() => {
this.bottomSheet.open(NewVersionComponent, { hasBackdrop: cfg.hasBackdrop });
});
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NewVersionService, deps: [{ token: SpaasConfigModel, optional: true }, { token: i1.MatBottomSheet }, { token: i2.SwUpdate }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NewVersionService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NewVersionService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: SpaasConfigModel, decorators: [{
type: Optional
}, {
type: Inject,
args: [SpaasConfigModel]
}] }, { type: i1.MatBottomSheet }, { type: i2.SwUpdate }] });
class PwaInstallComponent extends BaseComponent {
constructor(bottomSheetRef, pwaInstallService) {
super();
this.bottomSheetRef = bottomSheetRef;
this.pwaInstallService = pwaInstallService;
}
doInstall() {
this.pwaInstallService.doInstall();
this.bottomSheetRef.dismiss();
}
ignoreInstall() {
this.pwaInstallService.ignoreInstall();
this.bottomSheetRef.dismiss();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PwaInstallComponent, deps: [{ token: i1.MatBottomSheetRef }, { token: PwaInstallService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: PwaInstallComponent, isStandalone: false, selector: "spaas-pwa-install", usesInheritance: true, ngImport: i0, template: "<div class=\"txt-center\">\r\n install as an app?\r\n <div class=\"flex center column-gap-10 pad-big-top\">\r\n <button class=\"error bold\" (click)=\"ignoreInstall()\" data-testid=\"ignore-install\">\r\n no thanx\r\n </button>\r\n <button class=\"primary bold\" (click)=\"doInstall()\" data-testid=\"install\">\r\n yes please\r\n </button>\r\n </div>\r\n</div>\r\n", styles: [""] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PwaInstallComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-pwa-install', standalone: false, template: "<div class=\"txt-center\">\r\n install as an app?\r\n <div class=\"flex center column-gap-10 pad-big-top\">\r\n <button class=\"error bold\" (click)=\"ignoreInstall()\" data-testid=\"ignore-install\">\r\n no thanx\r\n </button>\r\n <button class=\"primary bold\" (click)=\"doInstall()\" data-testid=\"install\">\r\n yes please\r\n </button>\r\n </div>\r\n</div>\r\n" }]
}], ctorParameters: () => [{ type: i1.MatBottomSheetRef }, { type: PwaInstallService }] });
class ConfigService {
constructor(spaasConfig) {
this.spaasConfig = spaasConfig;
if (!spaasConfig) {
throw new Error('please provide a SpaasConfigModel using the forRoot method of the SpaasModule');
}
this.config = new SpaasExtConfigModel(this.spaasConfig);
}
getConfig() {
return this.config;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ConfigService, deps: [{ token: SpaasConfigModel, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ConfigService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ConfigService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: SpaasConfigModel, decorators: [{
type: Optional
}, {
type: Inject,
args: [SpaasConfigModel]
}] }] });
class LocalStorageService {
constructor(configService) {
this.configService = configService;
this.storagePrefix = this.configService.getConfig().storagePrefix;
}
getItem(lsKey) {
const lsVal = localStorage.getItem(this.storagePrefix + lsKey) || '';
return UtilsService.checkJSON(lsVal) ? JSON.parse(lsVal) : Number.isNaN(Number(lsVal)) ? lsVal : Number(lsVal);
}
getItems(searchString) {
const tempResults = [];
for (const key in localStorage) {
if (localStorage.hasOwnProperty(key)) {
if (key.indexOf(searchString) > -1) {
if (UtilsService.checkJSON(localStorage[key])) {
tempResults.push(JSON.parse(localStorage[key]));
}
else {
tempResults.push(localStorage[key]);
}
}
}
}
return tempResults;
}
setItem(lsKey, lsValue) {
if (typeof lsValue === 'object') {
localStorage.setItem(this.storagePrefix + lsKey, JSON.stringify(lsValue));
}
else {
localStorage.setItem(this.storagePrefix + lsKey, lsValue);
}
}
removeItem(lsKey) {
localStorage.removeItem(this.storagePrefix + lsKey);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LocalStorageService, deps: [{ token: ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LocalStorageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: LocalStorageService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: ConfigService }] });
class PwaInstallService {
constructor(bottomSheet, lsService, platform) {
this.bottomSheet = bottomSheet;
this.lsService = lsService;
this.platform = platform;
this.LS_ALREADY_PROMPTED = 'installPrompted';
}
installPrompt() {
if (!this.platform.IOS) {
fromEvent(window, 'beforeinstallprompt')
.subscribe((e) => {
e.preventDefault();
this.promptEvent = e;
this.openBottomSheet();
});
}
else {
const isInStandaloneMode = ('standalone' in window.navigator) && (window.navigator['standalone']);
if (!isInStandaloneMode) {
this.openBottomSheet();
}
}
}
openBottomSheet() {
console.log('will prompt install');
if (this.lsService.getItem(this.LS_ALREADY_PROMPTED) === 'true') {
return;
}
timer(3000)
.pipe(take(1))
.subscribe(() => {
this.bottomSheet.open(PwaInstallComponent);
});
}
doInstall() {
this.promptEvent.prompt();
}
ignoreInstall() {
this.lsService.setItem(this.LS_ALREADY_PROMPTED, true);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PwaInstallService, deps: [{ token: i1.MatBottomSheet }, { token: LocalStorageService }, { token: i3.Platform }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PwaInstallService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PwaInstallService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1.MatBottomSheet }, { type: LocalStorageService }, { type: i3.Platform }] });
const DATA__HAS_MENU = { menu: 'yes' };
const DATA__THEME_DARK = { theme: 'dark' };
const DATA__THEME_LIGHT = { theme: 'light' };
const FONT_FAMILY = 'Lato, Arial, sans-serif';
class ThemeModel {
constructor(name, props) {
this.name = name;
this.properties = props;
}
getRgb(color, alpha = 1) {
const h = Number(this.properties['--' + color + '-h']);
let s = Number(this.properties['--' + color + '-s'].replace('%', ''));
let l = Number(this.properties['--' + color + '-l'].replace('%', ''));
// Must be fractions of 1
s /= 100;
l /= 100;
const c = (1 - Math.abs(2 * l - 1)) * s, x = c * (1 - Math.abs((h / 60) % 2 - 1)), m = l - c / 2;
let r = 0, g = 0, b = 0;
if (0 <= h && h < 60) {
r = c;
g = x;
b = 0;
}
else if (60 <= h && h < 120) {
r = x;
g = c;
b = 0;
}
else if (120 <= h && h < 180) {
r = 0;
g = c;
b = x;
}
else if (180 <= h && h < 240) {
r = 0;
g = x;
b = c;
}
else if (240 <= h && h < 300) {
r = x;
g = 0;
b = c;
}
else if (300 <= h && h < 360) {
r = c;
g = 0;
b = x;
}
r = Math.round((r + m) * 255);
g = Math.round((g + m) * 255);
b = Math.round((b + m) * 255);
return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
}
}
// THEMES
// IMPORTANT: IF YOU UPDATE THE SETTINGS FOR PRIMARY, ACCENT OR ERROR HERE,
// ALSO UPDATE THEM IN MATERIAL.SCSS !
const light = new ThemeModel('light', {
'--primary-h': 204,
'--primary-s': '100%',
'--primary-l': '40%',
'--primary-op-min': 0.8,
'--primary-op-max': 0.4,
'--secondary-h': 27,
'--secondary-s': '93%',
'--secondary-l': '58%',
'--secondary-op-min': 0.8,
'--secondary-op-max': 0.4,
'--accent-h': 144,
'--accent-s': '100%',
'--accent-l': '27%',
'--accent-op-min': 0.95,
'--accent-op-max': 0.4,
'--error-h': 1,
'--error-s': '70%',
'--error-l': '53%',
'--error-op-min': 0.6,
'--error-op-max': 0.4,
'--bg-h': 0,
'--bg-s': '0%',
'--bg-l': '98%',
'--bg-accent': '-6%',
'--bg-lighten': '6%',
'--bg-darken': '-14%',
'--bg-op-overlay': 0.4,
'--bg-op-min': 0.84,
'--bg-op-max': 0.2,
'--color-h': 0,
'--color-s': '0%',
'--color-l': '13.4%',
'--color-op-min': 0.8,
'--color-op-max': 0.4,
'--disabled-h': 0,
'--disabled-s': '0%',
'--disabled-l': '62%',
'--disabled-op-min': 0.8,
'--disabled-op-max': 0.4,
'--table-even': '-8%',
'--table-odd': '-3%',
'--hover-lighten': '-12%',
});
// IMPORTANT: IF YOU UPDATE THE SETTINGS FOR PRIMARY, ACCENT OR ERROR HERE,
// ALSO UPDATE THEM IN MATERIAL.SCSS !
const dark = new ThemeModel('dark', {
'--primary-h': 200,
'--primary-s': '75%',
'--primary-l': '55%',
'--primary-op-min': 0.8,
'--primary-op-max': 0.4,
'--secondary-h': 27,
'--secondary-s': '93%',
'--secondary-l': '58%',
'--secondary-op-min': 0.8,
'--secondary-op-max': 0.4,
'--accent-h': 136,
'--accent-s': '80%',
'--accent-l': '38%',
'--accent-op-min': 0.95,
'--accent-op-max': 0.4,
'--error-h': 1,
'--error-s': '70%',
'--error-l': '56%',
'--error-op-min': 0.6,
'--error-op-max': 0.4,
'--bg-h': 210,
'--bg-s': '16%',
'--bg-l': '10%',
'--bg-accent': '10%',
'--bg-lighten': '4%',
'--bg-darken': '-8%',
'--bg-op-overlay': 0.4,
'--bg-op-min': 0.84,
'--bg-op-max': 0.2,
'--color-h': 0,
'--color-s': '0%',
'--color-l': '98%',
'--color-op-min': 0.8,
'--color-op-max': 0.4,
'--disabled-h': 0,
'--disabled-s': '0%',
'--disabled-l': '49.4%',
'--disabled-op-min': 0.8,
'--disabled-op-max': 0.4,
'--table-even': '10%',
'--table-odd': '3%',
'--hover-lighten': '22%',
});
/**
* Settings model, used by the settings component to store data on user settings and preferences
*
* @property {boolean} dark the application theme, defaults to light
* @property {ExportExtensionType} exportExtension the preferred extension for data exports, either xlsx or csv
* @property {DecimalSeparatorType} decimalSeparator the user's decimal separator in Excel, used for exporting and
* importing data
* @property {any} extraData any extra data that you want the user to set and store via the settings component
*/
class SettingsModel {
constructor(objIn) {
this.dark = objIn.hasOwnProperty('dark') ? objIn.dark : false; // if you update the default, also update material.scss default!!
this.decimalSeparator = objIn.decimalSeparator || 'dot';
this.exportExtension = objIn.exportExtension || 'xlsx';
this.extraData = objIn.extraData || {};
}
getCsvDelimiter() {
return this.decimalSeparator === 'comma' ? ';' : ',';
}
}
class SettingsService {
constructor(lsService) {
this.lsService = lsService;
this.LS_SETTINGS = 'settings';
this.settings$ = new BehaviorSubject(new SettingsModel(this.lsService.getItem(this.LS_SETTINGS) || {}));
}
// ********************************************************************************************************
// LOAD DATA
// ********************************************************************************************************
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newSettings(settings) {
this.lsService.setItem(this.LS_SETTINGS, settings);
this.settings$.next(settings);
}
onNewSettings() {
return this.settings$.asObservable();
}
getSettings() {
return this.settings$.getValue();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SettingsService, deps: [{ token: LocalStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SettingsService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SettingsService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: LocalStorageService }] });
class ThemeService {
constructor(settingsService) {
this.settingsService = settingsService;
this.activeTheme = new ThemeModel('', {});
this.activeTheme$ = new ReplaySubject(1);
}
// initTheme is called from the app-init.service
initTheme() {
if (!this.activeTheme?.name) {
this.setActiveTheme(this.settingsService.getSettings().dark ? 'dark' : 'light');
}
}
toggleTheme() {
if (this.activeTheme?.name === 'light') {
this.setActiveTheme('dark');
}
else {
this.setActiveTheme('light');
}
}
setActiveTheme(theme) {
// console.log('setting theme to ' + theme);
this.activeTheme = theme === 'dark' ? dark : light;
this.setCssVariables(this.activeTheme.properties);
this.setBodyData(theme === 'dark' ? DATA__THEME_DARK : DATA__THEME_LIGHT);
this.newTheme();
}
setCssVariables(props) {
for (const prop in props) {
if (props.hasOwnProperty(prop)) {
document.documentElement.style.setProperty(prop, props[prop]);
}
}
}
setBodyData(props) {
for (const prop in props) {
if (props.hasOwnProperty(prop)) {
document.body.dataset[prop] = props[prop];
}
}
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newTheme() {
this.activeTheme$.next(this.activeTheme);
}
onNewActiveTheme() {
return this.activeTheme$.asObservable();
}
getActiveTheme() {
return this.activeTheme;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ThemeService, deps: [{ token: SettingsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ThemeService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ThemeService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: SettingsService }] });
class AppInitService {
constructor(embedModeService, newVersionService, pwaInstallService, themeService) {
this.embedModeService = embedModeService;
this.newVersionService = newVersionService;
this.pwaInstallService = pwaInstallService;
this.themeService = themeService;
}
// initApp is called from the spaas.module using APP_INITIALIZER
initApp() {
this.embedModeService.setEmbedMode();
this.themeService.initTheme();
this.pwaInstallService.installPrompt();
this.newVersionService.getNewVersion();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AppInitService, deps: [{ token: EmbedModeService }, { token: NewVersionService }, { token: PwaInstallService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AppInitService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: AppInitService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: EmbedModeService }, { type: NewVersionService }, { type: PwaInstallService }, { type: ThemeService }] });
const BG_LIST = {
employee_solar: { url: './assets/images/bgs/employee_solar', alt: 'Employee at a solar plant' },
kathu_mirrors: {
url: './assets/images/bgs/kathu_mirrors',
alt: 'Cylindro-parabolic mirrors of Kathu Solar Park in South Africa'
},
outeiro_ccgt: {
url: './assets/images/bgs/outeiro_ccgt',
alt: 'Portugal Tapada do Outeiro combined cycle gas turbine power station'
},
shem_mareges: { url: './assets/images/bgs/shem_mareges', alt: 'SHEM Mareges hydro station' },
shem_thues: { url: './assets/images/bgs/shem_thues', alt: 'SHEM Thues hydro dam' },
tarfaya_windfarm: { url: './assets/images/bgs/tarfaya_windfarm', alt: 'The Tarfaya wind farm' },
};
class BgComponent extends BaseComponent {
constructor() {
super(...arguments);
this.imgExt = '.webp';
this.imgList = BG_LIST;
// LEFT: ALIGN BG IMG LEFT INSTEAD OF DEFAULT RIGHT
// PORTRAIT: SWITCHES BACKGROUND-SIZE FROM COVER TO AUTO (SO PORTRAIT IMGS ARE NOT STRETCHED OVER FULL WIDTH OF SCREEN)
this.bgX = 100;
this.bgY = 50;
this.bgPortrait = false;
this.bgImg = 'employee_solar';
this.bgAnimate = true;
}
ngOnInit() {
this.bg = this.imgList[this.bgImg];
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BgComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: BgComponent, isStandalone: false, selector: "spaas-bg", inputs: { bgX: "bgX", bgY: "bgY", bgPortrait: "bgPortrait", bgImg: "bgImg", bgAnimate: "bgAnimate" }, usesInheritance: true, ngImport: i0, template: "<div class=\"bg\">\r\n <div class=\"bg__img-wrapper\"\r\n [title]=\"bg.alt\"\r\n [class.with-anim]=\"bgAnimate\"\r\n [style.background-position-x.%]=\"bgX\"\r\n [style.background-position-y.%]=\"bgY\"\r\n [class.portrait]=\"bgPortrait\"\r\n [style.background-image]=\"'url(' + bg.url + imgExt + ')'\">\r\n </div>\r\n</div>\r\n", styles: [".bg{height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:-1}.bg__img-wrapper{background-repeat:no-repeat;background-size:cover;height:100%;overflow:hidden;width:100%}.bg__img-wrapper.with-anim{animation:kenburns-bottom 4s ease-out both}.bg__img-wrapper.visible{opacity:1}.bg__img-wrapper.invisible{opacity:0}.bg__img-wrapper.portrait{background-size:auto;left:0;right:auto;width:60%}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.bg__img-wrapper.portrait{width:100%}}@keyframes kenburns-bottom{0%{transform:scale(1) translate(0);transform-origin:14% 14%}to{transform:scale(1.04) translate(-14px,-4px);transform-origin:top left}}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: BgComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-bg', standalone: false, template: "<div class=\"bg\">\r\n <div class=\"bg__img-wrapper\"\r\n [title]=\"bg.alt\"\r\n [class.with-anim]=\"bgAnimate\"\r\n [style.background-position-x.%]=\"bgX\"\r\n [style.background-position-y.%]=\"bgY\"\r\n [class.portrait]=\"bgPortrait\"\r\n [style.background-image]=\"'url(' + bg.url + imgExt + ')'\">\r\n </div>\r\n</div>\r\n", styles: [".bg{height:100%;left:0;overflow:hidden;position:absolute;top:0;width:100%;z-index:-1}.bg__img-wrapper{background-repeat:no-repeat;background-size:cover;height:100%;overflow:hidden;width:100%}.bg__img-wrapper.with-anim{animation:kenburns-bottom 4s ease-out both}.bg__img-wrapper.visible{opacity:1}.bg__img-wrapper.invisible{opacity:0}.bg__img-wrapper.portrait{background-size:auto;left:0;right:auto;width:60%}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.bg__img-wrapper.portrait{width:100%}}@keyframes kenburns-bottom{0%{transform:scale(1) translate(0);transform-origin:14% 14%}to{transform:scale(1.04) translate(-14px,-4px);transform-origin:top left}}\n"] }]
}], propDecorators: { bgX: [{
type: Input
}], bgY: [{
type: Input
}], bgPortrait: [{
type: Input
}], bgImg: [{
type: Input
}], bgAnimate: [{
type: Input
}] } });
class EmbedComponent extends BaseComponent {
constructor(embedModeService, sanitizer) {
super();
this.embedModeService = embedModeService;
this.sanitizer = sanitizer;
/** The url of the application to embed */
this.url = '';
/** Use as fullscreen component, or within parent div */
this.takeOver = false;
}
ngOnInit() {
if (this.url) {
this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
}
}
ngAfterViewInit() {
this.embedModeService.embeddedWindow = this.iframeDiv?.nativeElement.contentWindow || null;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbedComponent, deps: [{ token: EmbedModeService }, { token: i2$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: EmbedComponent, isStandalone: false, selector: "spaas-embed", inputs: { url: "url", takeOver: "takeOver" }, viewQueries: [{ propertyName: "iframeDiv", first: true, predicate: ["iframe_div"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (safeUrl) {\r\n <div [class.fullscreen]=\"takeOver\"\r\n class=\"embed flex\">\r\n <iframe #iframe_div [src]=\"safeUrl\"></iframe>\r\n </div>\r\n}\r\n", styles: [".embed{height:100%;width:100%}.embed.fullscreen{height:100vh;width:100vw;left:0;position:fixed;top:0;z-index:9994}.embed iframe{border:none;height:100%;width:100%}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbedComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-embed', standalone: false, template: "@if (safeUrl) {\r\n <div [class.fullscreen]=\"takeOver\"\r\n class=\"embed flex\">\r\n <iframe #iframe_div [src]=\"safeUrl\"></iframe>\r\n </div>\r\n}\r\n", styles: [".embed{height:100%;width:100%}.embed.fullscreen{height:100vh;width:100vw;left:0;position:fixed;top:0;z-index:9994}.embed iframe{border:none;height:100%;width:100%}\n"] }]
}], ctorParameters: () => [{ type: EmbedModeService }, { type: i2$1.DomSanitizer }], propDecorators: { url: [{
type: Input
}], takeOver: [{
type: Input
}], iframeDiv: [{
type: ViewChild,
args: ['iframe_div']
}] } });
class SessionStorageService {
constructor(configService) {
this.configService = configService;
this.storagePrefix = this.configService.getConfig().storagePrefix;
}
getItem(lsKey) {
const lsVal = sessionStorage.getItem(this.storagePrefix + lsKey) || '';
return UtilsService.checkJSON(lsVal) ? JSON.parse(lsVal) : Number.isNaN(Number(lsVal)) ? lsVal : Number(lsVal);
}
getItems(searchString) {
const tempResults = [];
for (const key in sessionStorage) {
if (sessionStorage.hasOwnProperty(key)) {
if (key.indexOf(searchString) > -1) {
if (UtilsService.checkJSON(sessionStorage[key])) {
tempResults.push(JSON.parse(sessionStorage[key]));
}
else {
tempResults.push(sessionStorage[key]);
}
}
}
}
return tempResults;
}
setItem(lsKey, lsValue) {
if (typeof lsValue === 'object') {
sessionStorage.setItem(this.storagePrefix + lsKey, JSON.stringify(lsValue));
}
else {
sessionStorage.setItem(this.storagePrefix + lsKey, lsValue);
}
}
removeItem(lsKey) {
sessionStorage.removeItem(this.storagePrefix + lsKey);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SessionStorageService, deps: [{ token: ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SessionStorageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SessionStorageService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: ConfigService }] });
class OktaService {
constructor(configService, lsService, router, ssService, windowUtilsService) {
this.configService = configService;
this.lsService = lsService;
this.router = router;
this.ssService = ssService;
this.windowUtilsService = windowUtilsService;
this.LS_ACTIVEROUTE = 'activeRoute';
this.SS_ERROR = 'oktaError';
this.oktaError = null;
this.oktaError$ = new BehaviorSubject(null);
this.oktaUserInfo = new OktaUserModel({});
this.oktaUserInfo$ = new ReplaySubject(1);
this.onDestroy$ = new Subject();
this.oktaClientConfig = this.setConfig();
// CLIENT, TOKENPARAMS AND TOKENMANAGER
this.oktaClient = new OktaAuth(this.oktaClientConfig);
this.oktaClient.start(); // as of v5, needs to be started as a service to auto-renew
this.tokenParams = { scopes: this.oktaClientConfig.scopes };
this.tokenManager = this.oktaClient.tokenManager;
this.tokenManager.on('error', (error) => {
// auto-renew failed, usually cuz user deleted cookies or something (no more valid okta session), so sign out
console.log(error);
this.oktaClient.signOut({ postLogoutRedirectUri: null }).catch((err) => console.log(err));
});
// SUBSCRIBE TO ROUTING
this.onRouting();
}
ngOnDestroy() {
this.onDestroy$.next();
this.onDestroy$.complete();
}
// ********************************************************************************************************
// GENERIC STUFF
// ********************************************************************************************************
setConfig() {
const spaasConfig = this.configService.getConfig();
if (!spaasConfig?.oktaConfig) {
throw new Error('please provide a valid Okta configuration via the "forRoot" method of the SpaasModule');
}
if (spaasConfig?.oktaConfig?.url?.slice(-1) === '/') {
throw new Error('the okta url should not have a trailing slash');
}
if (spaasConfig?.oktaConfig?.tenantId.includes('/')) {
throw new Error('the okta tenant id should not contain slashes');
}
return {
clientId: spaasConfig.oktaConfig.clientId,
issuer: spaasConfig.oktaConfig.url + '/oauth2/' + spaasConfig.oktaConfig.tenantId,
pkce: true,
redirectUri: spaasConfig.oktaConfig.withPath ? this.windowUtilsService.getLocation().origin + this.windowUtilsService.getLocation().pathname : this.windowUtilsService.getLocation().origin,
responseType: ['id_token', 'token'],
scopes: ['openid', 'email'].concat(spaasConfig.oktaConfig.additionalScopes || []),
tokenManager: {
storage: 'sessionStorage',
storageKey: spaasConfig.storagePrefix + 'tokens',
expireEarlySeconds: 300
},
transactionManager: {
saveNonceCookie: false,
saveParamsCookie: false,
saveStateCookie: false,
},
};
}
onRouting() {
this.router.events
.pipe(takeUntil(this.onDestroy$))
.subscribe((event) => {
if (event instanceof NavigationStart) {
// set active route here, so we know where to route to after token redirection
if (event.url !== '/') {
this.setActiveRoute(event.url);
}
// BECAUSE WE HANDLE THE CALLBACK BEFORE ROUTING, THE HIDDEN IFRAME REMAINS EMPTY
this.handleRedirect();
}
});
}
// ********************************************************************************************************
// OKTA STUFF
// ********************************************************************************************************
handleRedirect() {
if (this.oktaClient.token.isLoginRedirect() || this.windowUtilsService.getLocation().search.includes('error=')) {
// IS REDIRECT OR OKTA ERROR
this.updateOktaError(null);
this.parseFromUrl();
}
else if (!this.oktaError) {
// IS REGULAR NAVIGATION: CHECK USER INFO
this.getUserInfoFromToken();
}
}
parseFromUrl() {
this.oktaClient.token.parseFromUrl()
.then((tokenResponse) => {
this.tokenManager.setTokens(tokenResponse.tokens);
// NOW SET USER INFO FROM THE TOKEN
// IT'S THE USER INFO OBSERVABLE THAT OTHER COMPONENTS OR SERVICES SHOULD USE AS INDICATION THAT ALL IS GOOD TO GO
this.getUserInfoFromToken();
})
.catch((err) => {
this.updateOktaError(err);
});
}
getUserInfoFromToken() {
if (this.oktaUserInfo.email) {
return;
}
this.oktaClient.getUser()
.then((claims) => {
this.newUserInfo(claims);
// set a default url. If it exists, fine, if not, it will force the configured redirects to kick in
this.router.navigate([this.getActiveRoute() || '/home']);
})
.catch(() => {
this.getTokenWithRedirect();
});
}
getTokenWithRedirect() {
this.oktaClient.token.getWithRedirect(this.tokenParams)
.catch((e) => console.log(e));
}
getCachedAccessToken() {
// TO BE USED IN CANACTIVE AND/OR CANLOAD AND/OR HTTP INTERCEPTOR
if (this.oktaClient && this.tokenManager) {
return this.oktaClient.getAccessToken() || '';
}
else {
console.log('should never happen: tokenmanager is null! Nothing left to do but redirect');
this.getTokenWithRedirect();
return '';
}
}
updateOktaError(newState) {
this.oktaError = newState;
this.ssService.setItem(this.SS_ERROR, this.oktaError);
this.newOktaError();
}
forceRetry() {
// METHOD THAT CAN BE CALLED BY WHICHEVER COMPONENT YOU HAVE TO HANDLE/DISPLAY OKTA ERRORS
// FOR EXAMPLE ON A BUTTON CLICK 'TRY AGAIN' SO USER CAN FORCE AN OKTA RETRY
this.updateOktaError(null);
this.getTokenWithRedirect();
}
setActiveRoute(url) {
this.lsService.setItem(this.LS_ACTIVEROUTE, url);
}
getActiveRoute() {
return this.lsService.getItem(this.LS_ACTIVEROUTE) || '';
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newUserInfo(userInfo) {
this.oktaUserInfo = new OktaUserModel(userInfo);
this.oktaUserInfo$.next(this.oktaUserInfo);
}
onNewUserInfo() {
return this.oktaUserInfo$.asObservable();
}
getUserInfo() {
return UtilsService.copy(this.oktaUserInfo);
}
newOktaError() {
this.oktaError$.next(this.oktaError);
}
onNewOktaError() {
return this.oktaError$.asObservable();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaService, deps: [{ token: ConfigService }, { token: LocalStorageService }, { token: i3$1.Router }, { token: SessionStorageService }, { token: WindowUtilsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: ConfigService }, { type: LocalStorageService }, { type: i3$1.Router }, { type: SessionStorageService }, { type: WindowUtilsService }] });
class IntroComponent extends BaseComponent {
constructor(configService, embedModeService, oktaService, windowUtilsService) {
super();
this.configService = configService;
this.embedModeService = embedModeService;
this.oktaService = oktaService;
this.windowUtilsService = windowUtilsService;
this.introText = 'all good, loading your data';
this.checkingAccessText = 'checking your access';
this.tryAgainButtonTitle = 'try again';
this.contactGuardButtonTitle = 'contact guard';
this.goToSnowButtonTitle = 'request access in Snow';
this.bgImg = 'employee_solar';
this.isDone = false;
this.introDone = new EventEmitter();
this.oktaError = null;
this.userReceived = false;
this.isIframe = false;
this.config = this.configService.getConfig();
this.isIframe = this.embedModeService.getEmbedMode().isIframe();
this.onUserInfo();
this.onOktaError();
}
onUserInfo() {
this.oktaService.onNewUserInfo()
.pipe(takeUntil(this.onDestroy$))
.subscribe((user) => {
if (user?.email) {
this.userReceived = true;
// emit that all is well, so the screen can already start rendering
this.introDone.emit(true);
// and only hide the okta itself after n ms
timer(1400)
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => {
this.isDone = true;
});
}
});
}
onOktaError() {
this.oktaService.onNewOktaError()
.pipe(takeUntil(this.onDestroy$))
.subscribe((error) => {
this.oktaError = error;
});
}
oktaTryAgain() {
this.oktaService.forceRetry();
}
contactGuard() {
const body = 'Following error was received trying to sign in to ' + this.config?.cleanAppName + ':\r\n\r\n' +
JSON.stringify(this.oktaError);
const targetUrl = `mailto:5939@engie.com?subject=Okta sign-in error for ${this.config?.cleanAppName}&body=${encodeURIComponent(body)}`;
this.windowUtilsService.redirectTo(targetUrl);
}
goToSnow() {
this.windowUtilsService.openWindow('https://gemprod.service-now.com/gem');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: IntroComponent, deps: [{ token: ConfigService }, { token: EmbedModeService }, { token: OktaService }, { token: WindowUtilsService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: IntroComponent, isStandalone: false, selector: "spaas-okta-intro", inputs: { introText: "introText", checkingAccessText: "checkingAccessText", tryAgainButtonTitle: "tryAgainButtonTitle", contactGuardButtonTitle: "contactGuardButtonTitle", goToSnowButtonTitle: "goToSnowButtonTitle", bgImg: "bgImg" }, outputs: { introDone: "introDone" }, usesInheritance: true, ngImport: i0, template: "@if (!isDone) {\r\n <div [class.in-iframe]=\"isIframe\"\r\n class=\"intro\">\r\n @if (!isIframe) {\r\n <div class=\"half-screen flex col center\">\r\n <!-- LOGO -->\r\n <div class=\"half-screen__logo flex center\">\r\n <svg viewBox=\"0 0 512 256\">\r\n <use [attr.xlink:href]=\"'../../assets/images/logo-engie.svg#svg1'\"></use>\r\n </svg>\r\n </div>\r\n @if (oktaError) {\r\n <!-- HAS OKTA ERROR -->\r\n <div class=\"txt-center\">\r\n <div class=\"txt-bold\">Bumped into an error:</div>\r\n <div>{{ oktaError.message }}</div>\r\n <div class=\"flex center pad-big-top column-gap-10\">\r\n <button (click)=\"oktaTryAgain()\" class=\"primary\">\r\n {{ tryAgainButtonTitle }}\r\n </button>\r\n @if ((oktaError.errorCode | lowercase) === 'access_denied') {\r\n <button (click)=\"goToSnow()\" class=\"error\">\r\n {{ goToSnowButtonTitle }}\r\n </button>\r\n } @else {\r\n <button (click)=\"contactGuard()\" class=\"error\">\r\n {{ contactGuardButtonTitle }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- NO OKTA ERROR -->\r\n <div class=\"txt-center pad-big-bottom\">\r\n <div class=\"pad-big-bottom\" data-testid=\"intro-text\">\r\n {{ userReceived ? introText : checkingAccessText }}\r\n </div>\r\n <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n </div>\r\n }\r\n </div>\r\n <spaas-bg [bgImg]=\"bgImg\"></spaas-bg>\r\n } @else {\r\n <div>\r\n loading embedded {{ config.cleanAppName }}\r\n <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", styles: [".intro{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);height:100vh;left:0;position:fixed;top:0;width:100%;z-index:9999}.intro.in-iframe{display:flex;flex-flow:column;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:18px;justify-content:center;text-align:center}.intro.in-iframe>div{margin:auto;width:344px}\n"], dependencies: [{ kind: "component", type: i5.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: BgComponent, selector: "spaas-bg", inputs: ["bgX", "bgY", "bgPortrait", "bgImg", "bgAnimate"] }, { kind: "pipe", type: i1$1.LowerCasePipe, name: "lowercase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: IntroComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-okta-intro', standalone: false, template: "@if (!isDone) {\r\n <div [class.in-iframe]=\"isIframe\"\r\n class=\"intro\">\r\n @if (!isIframe) {\r\n <div class=\"half-screen flex col center\">\r\n <!-- LOGO -->\r\n <div class=\"half-screen__logo flex center\">\r\n <svg viewBox=\"0 0 512 256\">\r\n <use [attr.xlink:href]=\"'../../assets/images/logo-engie.svg#svg1'\"></use>\r\n </svg>\r\n </div>\r\n @if (oktaError) {\r\n <!-- HAS OKTA ERROR -->\r\n <div class=\"txt-center\">\r\n <div class=\"txt-bold\">Bumped into an error:</div>\r\n <div>{{ oktaError.message }}</div>\r\n <div class=\"flex center pad-big-top column-gap-10\">\r\n <button (click)=\"oktaTryAgain()\" class=\"primary\">\r\n {{ tryAgainButtonTitle }}\r\n </button>\r\n @if ((oktaError.errorCode | lowercase) === 'access_denied') {\r\n <button (click)=\"goToSnow()\" class=\"error\">\r\n {{ goToSnowButtonTitle }}\r\n </button>\r\n } @else {\r\n <button (click)=\"contactGuard()\" class=\"error\">\r\n {{ contactGuardButtonTitle }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- NO OKTA ERROR -->\r\n <div class=\"txt-center pad-big-bottom\">\r\n <div class=\"pad-big-bottom\" data-testid=\"intro-text\">\r\n {{ userReceived ? introText : checkingAccessText }}\r\n </div>\r\n <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n </div>\r\n }\r\n </div>\r\n <spaas-bg [bgImg]=\"bgImg\"></spaas-bg>\r\n } @else {\r\n <div>\r\n loading embedded {{ config.cleanAppName }}\r\n <mat-progress-bar [mode]=\"'indeterminate'\"></mat-progress-bar>\r\n </div>\r\n }\r\n </div>\r\n}\r\n", styles: [".intro{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);height:100vh;left:0;position:fixed;top:0;width:100%;z-index:9999}.intro.in-iframe{display:flex;flex-flow:column;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:18px;justify-content:center;text-align:center}.intro.in-iframe>div{margin:auto;width:344px}\n"] }]
}], ctorParameters: () => [{ type: ConfigService }, { type: EmbedModeService }, { type: OktaService }, { type: WindowUtilsService }], propDecorators: { introText: [{
type: Input
}], checkingAccessText: [{
type: Input
}], tryAgainButtonTitle: [{
type: Input
}], contactGuardButtonTitle: [{
type: Input
}], goToSnowButtonTitle: [{
type: Input
}], bgImg: [{
type: Input
}], introDone: [{
type: Output
}] } });
class MaterialModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.5", ngImport: i0, type: MaterialModule, imports: [DragDropModule,
MatBottomSheetModule,
MatIconModule,
MatProgressBarModule,
MatRadioModule,
MatSnackBarModule,
MatTooltipModule,
MatMenuModule], exports: [DragDropModule,
MatBottomSheetModule,
MatIconModule,
MatProgressBarModule,
MatRadioModule,
MatSnackBarModule,
MatTooltipModule,
MatMenuModule] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MaterialModule, providers: [
{
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: {
subscriptSizing: 'dynamic'
}
},
{
provide: MAT_RADIO_DEFAULT_OPTIONS,
useValue: { color: 'primary' },
}
], imports: [DragDropModule,
MatBottomSheetModule,
MatIconModule,
MatProgressBarModule,
MatRadioModule,
MatSnackBarModule,
MatTooltipModule,
MatMenuModule, DragDropModule,
MatBottomSheetModule,
MatIconModule,
MatProgressBarModule,
MatRadioModule,
MatSnackBarModule,
MatTooltipModule,
MatMenuModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MaterialModule, decorators: [{
type: NgModule,
args: [{
exports: [
DragDropModule,
MatBottomSheetModule,
MatIconModule,
MatProgressBarModule,
MatRadioModule,
MatSnackBarModule,
MatTooltipModule,
MatMenuModule
],
imports: [
DragDropModule,
MatBottomSheetModule,
MatIconModule,
MatProgressBarModule,
MatRadioModule,
MatSnackBarModule,
MatTooltipModule,
MatMenuModule
],
providers: [
{
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: {
subscriptSizing: 'dynamic'
}
},
{
provide: MAT_RADIO_DEFAULT_OPTIONS,
useValue: { color: 'primary' },
}
]
}]
}] });
class SlideOutModel {
constructor(objIn = null) {
this.component = objIn?.component || null;
this.data = objIn?.data || null;
this.providers = objIn?.providers || [];
this.type = objIn?.type || '';
this.updateBrowserLocationTo = objIn?.updateBrowserLocationTo || '';
}
}
/*
const SLIDE_OUTS = {
dagResults: 'dag-results',
taskLogs: 'task-logs'
} as const;
export type SlideOutType = typeof SLIDE_OUTS[keyof typeof SLIDE_OUTS];
*/
class SlideOutService {
constructor(location) {
this.location = location;
this.slideOut$ = new BehaviorSubject(new SlideOutModel());
this.prevUpdate = '';
this.getPopStates();
}
getPopStates() {
this.location.subscribe((location) => {
if (location.type === 'popstate') {
// close the active slide-out on back/forward
this.prevUpdate = '';
if (this.getSlideOut()?.type) {
this.newSlideOut(null);
}
}
});
}
updateBrowserLocation(url) {
if (url !== this.prevUpdate) {
this.prevUpdate = url;
this.location.go(url);
}
}
newSlideOut(so) {
const slideOut = new SlideOutModel(so);
if (slideOut.type === this.getSlideOut()?.type) {
slideOut.type = '';
slideOut.component = null;
}
if (slideOut.type || slideOut.updateBrowserLocationTo) {
// update location history so users stay in screen
// when they try to close the slide-out with back
this.updateBrowserLocation(slideOut.updateBrowserLocationTo || this.location.path());
}
this.slideOut$.next(slideOut);
}
onNewSlideOut() {
return this.slideOut$.asObservable();
}
getSlideOut() {
return this.slideOut$.getValue();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SlideOutService, deps: [{ token: i1$1.Location }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SlideOutService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SlideOutService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1$1.Location }] });
class MenuComponent extends BaseComponent {
constructor(embedModeService, slideOutService, themeService) {
super();
this.embedModeService = embedModeService;
this.slideOutService = slideOutService;
this.themeService = themeService;
/** The menu items to render in the DOM. */
this.menuItems = [];
this.mmActive = false;
this.so = '';
this.isIframe = false;
this.isIframe = this.embedModeService.getEmbedMode().isIframe();
if (!this.isIframe) {
this.themeService.setBodyData(DATA__HAS_MENU);
}
this.onSo();
}
// ********************************************************************************************************
// LOAD
// ********************************************************************************************************
onSo() {
this.slideOutService.onNewSlideOut()
.pipe(takeUntil(this.onDestroy$))
.subscribe((so) => {
if (so?.type) {
this.mmActive = false;
}
});
}
// ********************************************************************************************************
// UI
// ********************************************************************************************************
// EVENT LISTENERS
onToggleMenu() {
this.mmActive = !this.mmActive;
if (this.mmActive) {
// menu active: close open slide-outs
this.slideOutService.newSlideOut(null);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuComponent, deps: [{ token: EmbedModeService }, { token: SlideOutService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: MenuComponent, isStandalone: false, selector: "spaas-menu", inputs: { menuItems: "menuItems" }, usesInheritance: true, ngImport: i0, template: "@if (!isIframe) {\r\n <div class=\"mm\">\r\n\r\n <div (click)=\"onToggleMenu()\"\r\n [class.active]=\"mmActive\"\r\n class=\"mm__burger\">\r\n <span></span>\r\n <span></span>\r\n </div>\r\n <div [class.visible]=\"mmActive\"\r\n class=\"mm__slide-out\">\r\n @if (mmActive) {\r\n <div class=\"mm__slide-out__items\">\r\n @for (item of menuItems; track item) {\r\n <div (click)=\"onToggleMenu()\"\r\n [routerLink]=\"item.rtrLink\"\r\n routerLinkActive=\"accent\">\r\n {{ item.label }}\r\n </div>\r\n }\r\n </div>\r\n <div class=\"mm__slide-out__logo\">\r\n <svg viewBox=\"0 0 512 256\">\r\n <use [attr.xlink:href]=\"'assets/images/logo-engie.svg#svg1'\"></use>\r\n </svg>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".mm__burger{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);cursor:pointer;height:44px;left:0;position:fixed;top:2px;transition:background-color .4s;width:44px;z-index:9996}.mm__burger span{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),1);border-radius:9px;display:block;height:3px;opacity:1;position:absolute;right:10px;transform:rotate(0);transition:.25s ease-in-out}.mm__burger span:nth-child(1){top:19px;width:24px}.mm__burger span:nth-child(2){top:24px;width:18px}.mm__burger.active span{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);height:3px}.mm__burger.active span:nth-child(1){top:20px;transform:rotate(45deg);width:24px}.mm__burger.active span:nth-child(2){top:24px;transform:rotate(-45deg);width:24px}.mm__slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;padding:28px 88px;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9995}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.mm__slide-out{padding:28px 44px}}.mm__slide-out.visible{transform:translateZ(0)}.mm__slide-out__items{animation:anim-fade-in .2s .2s forwards;opacity:0}.mm__slide-out__items>div{cursor:pointer;font-size:28px;font-family:BebasNeue,Lato,Arial,sans-serif;padding:7px;transition:transform .2s}.mm__slide-out__items>div:hover{transform:translate(7px)}.mm__slide-out__logo{bottom:14px;color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + -4%),1);height:40vh;position:absolute;right:88px;width:80vh}.mm__slide-out__logo svg{height:100%;width:100%}\n"], dependencies: [{ kind: "directive", type: i3$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3$1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-menu', standalone: false, template: "@if (!isIframe) {\r\n <div class=\"mm\">\r\n\r\n <div (click)=\"onToggleMenu()\"\r\n [class.active]=\"mmActive\"\r\n class=\"mm__burger\">\r\n <span></span>\r\n <span></span>\r\n </div>\r\n <div [class.visible]=\"mmActive\"\r\n class=\"mm__slide-out\">\r\n @if (mmActive) {\r\n <div class=\"mm__slide-out__items\">\r\n @for (item of menuItems; track item) {\r\n <div (click)=\"onToggleMenu()\"\r\n [routerLink]=\"item.rtrLink\"\r\n routerLinkActive=\"accent\">\r\n {{ item.label }}\r\n </div>\r\n }\r\n </div>\r\n <div class=\"mm__slide-out__logo\">\r\n <svg viewBox=\"0 0 512 256\">\r\n <use [attr.xlink:href]=\"'assets/images/logo-engie.svg#svg1'\"></use>\r\n </svg>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".mm__burger{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);cursor:pointer;height:44px;left:0;position:fixed;top:2px;transition:background-color .4s;width:44px;z-index:9996}.mm__burger span{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),1);border-radius:9px;display:block;height:3px;opacity:1;position:absolute;right:10px;transform:rotate(0);transition:.25s ease-in-out}.mm__burger span:nth-child(1){top:19px;width:24px}.mm__burger span:nth-child(2){top:24px;width:18px}.mm__burger.active span{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);height:3px}.mm__burger.active span:nth-child(1){top:20px;transform:rotate(45deg);width:24px}.mm__burger.active span:nth-child(2){top:24px;transform:rotate(-45deg);width:24px}.mm__slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;padding:28px 88px;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9995}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.mm__slide-out{padding:28px 44px}}.mm__slide-out.visible{transform:translateZ(0)}.mm__slide-out__items{animation:anim-fade-in .2s .2s forwards;opacity:0}.mm__slide-out__items>div{cursor:pointer;font-size:28px;font-family:BebasNeue,Lato,Arial,sans-serif;padding:7px;transition:transform .2s}.mm__slide-out__items>div:hover{transform:translate(7px)}.mm__slide-out__logo{bottom:14px;color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + -4%),1);height:40vh;position:absolute;right:88px;width:80vh}.mm__slide-out__logo svg{height:100%;width:100%}\n"] }]
}], ctorParameters: () => [{ type: EmbedModeService }, { type: SlideOutService }, { type: ThemeService }], propDecorators: { menuItems: [{
type: Input
}] } });
class ActiveRouteModel {
constructor(url, queryParams, params) {
this.params = params || {};
this.queryParams = queryParams || {};
this.url = url && url.startsWith('/') ? url.replace(/\//g, ' ') : '';
}
}
class ActiveRouteService {
constructor(configService, titleService) {
this.configService = configService;
this.titleService = titleService;
this.activeRoute = new ActiveRouteModel('', {}, {});
this.activeRoute$ = new ReplaySubject(1);
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newActiveRoute(url, queryParams, params) {
this.activeRoute = new ActiveRouteModel(url, queryParams, params);
this.titleService.setTitle(this.configService.getConfig().cleanAppName + ' - ' + this.activeRoute.url + ' | Engie');
this.activeRoute$.next(this.activeRoute);
}
onNewActiveRoute() {
return this.activeRoute$.asObservable();
}
getActiveRoute() {
return this.activeRoute;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ActiveRouteService, deps: [{ token: ConfigService }, { token: i2$1.Title }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ActiveRouteService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ActiveRouteService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: ConfigService }, { type: i2$1.Title }] });
class MenuSideBarComponent extends BaseComponent {
constructor(activeRouteService, configService, themeService) {
super();
this.activeRouteService = activeRouteService;
this.configService = configService;
this.themeService = themeService;
this.titleText = '';
this.withMinHeight = true;
this.env = '';
this.fullEnv = '';
// enable menu gutter and notify parent that iframe has menu
this.themeService.setBodyData(DATA__HAS_MENU);
this.setEnv();
}
ngOnInit() {
if (!this.titleText) {
this.titleText = this.activeRouteService.getActiveRoute()?.url;
}
}
setEnv() {
const config = this.configService.getConfig();
if (config.environment &&
!config.environment.startsWith('local') &&
!config.environment.startsWith('prod')) {
this.env = config.environment.slice(0, 3);
this.fullEnv = config.environment;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarComponent, deps: [{ token: ActiveRouteService }, { token: ConfigService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: MenuSideBarComponent, isStandalone: false, selector: "spaas-menu-side-bar", inputs: { titleText: "titleText", withMinHeight: "withMinHeight" }, usesInheritance: true, ngImport: i0, template: "<div class=\"mm-side-bar pad-small-top\">\r\n\r\n <ng-content select=\"spaas-user-info\"></ng-content>\r\n\r\n @if (env) {\r\n <div class=\"mm-side-bar__env {{env}}\"\r\n matTooltipPosition=\"right\"\r\n matTooltipClass=\"bg-error\"\r\n matTooltip=\"you are on the {{fullEnv | uppercase}} environment\">\r\n {{ env }}\r\n </div>\r\n }\r\n\r\n <div class=\"mm-side-bar__title\"\r\n [class.with-min-height]=\"withMinHeight\">\r\n {{ titleText }}\r\n </div>\r\n\r\n <ng-content select=\"spaas-menu-side-bar-icon\"></ng-content>\r\n\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"], dependencies: [{ kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i1$1.UpperCasePipe, name: "uppercase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-menu-side-bar', standalone: false, template: "<div class=\"mm-side-bar pad-small-top\">\r\n\r\n <ng-content select=\"spaas-user-info\"></ng-content>\r\n\r\n @if (env) {\r\n <div class=\"mm-side-bar__env {{env}}\"\r\n matTooltipPosition=\"right\"\r\n matTooltipClass=\"bg-error\"\r\n matTooltip=\"you are on the {{fullEnv | uppercase}} environment\">\r\n {{ env }}\r\n </div>\r\n }\r\n\r\n <div class=\"mm-side-bar__title\"\r\n [class.with-min-height]=\"withMinHeight\">\r\n {{ titleText }}\r\n </div>\r\n\r\n <ng-content select=\"spaas-menu-side-bar-icon\"></ng-content>\r\n\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"] }]
}], ctorParameters: () => [{ type: ActiveRouteService }, { type: ConfigService }, { type: ThemeService }], propDecorators: { titleText: [{
type: Input
}], withMinHeight: [{
type: Input
}] } });
class MenuSideBarSubmenuListComponent {
constructor() {
this.submenuItems = false;
}
ngAfterViewInit() {
this.submenuItems = !!this.refSubmenuItems.nativeElement.querySelector('spaas-submenu-side-bar-item');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarSubmenuListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: MenuSideBarSubmenuListComponent, isStandalone: false, selector: "spaas-submenu-side-bar-list", viewQueries: [{ propertyName: "refSubmenuItems", first: true, predicate: ["refSubmenuItems"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"mm-side-bar__icon__submenu-list__wrapper\" #refSubmenuItems>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarSubmenuListComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-submenu-side-bar-list', standalone: false, template: "<div class=\"mm-side-bar__icon__submenu-list__wrapper\" #refSubmenuItems>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"] }]
}], propDecorators: { refSubmenuItems: [{
type: ViewChild,
args: ['refSubmenuItems', { read: ElementRef }]
}] } });
class HoverDirective {
constructor(elementRef, renderer) {
this.elementRef = elementRef;
this.renderer = renderer;
this.spaasHover = '';
}
onMouseHover(event) {
if (event.type === 'mouseenter') {
this.renderer.addClass(this.elementRef.nativeElement, this.spaasHover);
return;
}
this.renderer.removeClass(this.elementRef.nativeElement, this.spaasHover);
}
onClick() {
if (this.elementRef.nativeElement.classList.contains(this.spaasHover)) {
this.renderer.removeClass(this.elementRef.nativeElement, this.spaasHover);
}
else {
this.renderer.addClass(this.elementRef.nativeElement, this.spaasHover);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: HoverDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: HoverDirective, isStandalone: false, selector: "[spaasHover]", inputs: { spaasHover: "spaasHover" }, host: { listeners: { "mouseenter": "onMouseHover($event)", "mouseleave": "onMouseHover($event)", "click": "onClick()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: HoverDirective, decorators: [{
type: Directive,
args: [{
selector: '[spaasHover]',
standalone: false,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { spaasHover: [{
type: Input
}], onMouseHover: [{
type: HostListener,
args: ['mouseenter', ['$event']]
}, {
type: HostListener,
args: ['mouseleave', ['$event']]
}], onClick: [{
type: HostListener,
args: ['click']
}] } });
class MenuSideBarIconComponent extends BaseComponent {
constructor(slideOutService) {
super();
this.slideOutService = slideOutService;
this.tooltipMsg = '';
this.withTopMargin = false;
this.withHover = true;
this.withDivider = false;
this.submenuWidth = 100;
// GENERIC STATE INDICATORS FROM PARENT
this.isDisabled = false;
// SLIDE-OUT TO INDICATE THAT THIS ICON SHOULD ACTIVATE A SLIDE-OUT
this.slideOut = null;
this.isActive = false;
// MOUSE-EVENT EMITTER IF NOT SO-TYPE
this.clicked = new EventEmitter();
this.getSoActive();
}
ngOnInit() {
this.submenuWidth = Math.max(this.submenuWidth, 50);
}
getSoActive() {
this.slideOutService.onNewSlideOut()
.pipe(takeUntil(this.onDestroy$))
.subscribe((so) => {
this.isActive = this.slideOut?.type !== '' && so?.type === this.slideOut?.type;
});
}
onClick(e) {
if (this.slideOut) {
this.slideOutService.newSlideOut(this.slideOut);
}
else if (!this.isDisabled) {
this.clicked.emit(e);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarIconComponent, deps: [{ token: SlideOutService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: MenuSideBarIconComponent, isStandalone: false, selector: "spaas-menu-side-bar-icon", inputs: { tooltipMsg: "tooltipMsg", withTopMargin: "withTopMargin", withHover: "withHover", withDivider: "withDivider", submenuWidth: "submenuWidth", isDisabled: "isDisabled", slideOut: "slideOut", isActive: "isActive" }, outputs: { clicked: "clicked" }, queries: [{ propertyName: "submenusList", first: true, predicate: MenuSideBarSubmenuListComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"mm-side-bar__icon\"\r\n spaasHover=\"show-submenu\"\r\n [style.--margin-top]=\"withTopMargin || withDivider ? '24px' : '0px'\"\r\n [class.active]=\"isActive\"\r\n [class.disabled]=\"isDisabled\"\r\n [class.with-divider]=\"withDivider\"\r\n [class.submenu-with-hover]=\"this.submenusList\"\r\n [class.with-hover]=\"!this.submenusList && withHover\"\r\n (click)=\"onClick($event)\">\r\n <div\r\n [matTooltipPosition]=\"this.submenusList ? 'above' : 'right'\"\r\n [matTooltip]=\"tooltipMsg\">\r\n <ng-content></ng-content>\r\n </div>\r\n <div class=\"mm-side-bar__icon__submenu-list first-submenu flex column\"\r\n [style.--width-submenu]=\"submenuWidth + 'px'\">\r\n <ng-content select=\"spaas-submenu-side-bar-list\"></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"], dependencies: [{ kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: HoverDirective, selector: "[spaasHover]", inputs: ["spaasHover"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarIconComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-menu-side-bar-icon', standalone: false, template: "<div class=\"mm-side-bar__icon\"\r\n spaasHover=\"show-submenu\"\r\n [style.--margin-top]=\"withTopMargin || withDivider ? '24px' : '0px'\"\r\n [class.active]=\"isActive\"\r\n [class.disabled]=\"isDisabled\"\r\n [class.with-divider]=\"withDivider\"\r\n [class.submenu-with-hover]=\"this.submenusList\"\r\n [class.with-hover]=\"!this.submenusList && withHover\"\r\n (click)=\"onClick($event)\">\r\n <div\r\n [matTooltipPosition]=\"this.submenusList ? 'above' : 'right'\"\r\n [matTooltip]=\"tooltipMsg\">\r\n <ng-content></ng-content>\r\n </div>\r\n <div class=\"mm-side-bar__icon__submenu-list first-submenu flex column\"\r\n [style.--width-submenu]=\"submenuWidth + 'px'\">\r\n <ng-content select=\"spaas-submenu-side-bar-list\"></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"] }]
}], ctorParameters: () => [{ type: SlideOutService }], propDecorators: { submenusList: [{
type: ContentChild,
args: [MenuSideBarSubmenuListComponent]
}], tooltipMsg: [{
type: Input
}], withTopMargin: [{
type: Input
}], withHover: [{
type: Input
}], withDivider: [{
type: Input
}], submenuWidth: [{
type: Input
}], isDisabled: [{
type: Input
}], slideOut: [{
type: Input
}], isActive: [{
type: Input
}], clicked: [{
type: Output
}] } });
class OktaAuthInterceptor {
static checkUrlsToIntercept(urlsToIntercept, url) {
for (const curUrl of urlsToIntercept) {
if (url.startsWith(curUrl)) {
return true;
}
}
return false;
}
constructor(spaasConfig, oktaService) {
this.spaasConfig = spaasConfig;
this.oktaService = oktaService;
}
intercept(req, next) {
let headers = req.headers;
if (
// check for undefined also, because the value here comes directly from the injection-token, so not looped through the SpaasConfigModel constructor
req.method !== 'GET' && (this.spaasConfig.oktaConfig.interceptAddContentHeader === undefined || this.spaasConfig.oktaConfig.interceptAddContentHeader)) {
headers = headers.set('Content-type', 'application/json');
}
if (req.url.startsWith(this.spaasConfig.oktaConfig.url) ||
OktaAuthInterceptor.checkUrlsToIntercept(this.spaasConfig.oktaConfig.interceptUrls, req.url)) {
const token = this.oktaService.getCachedAccessToken();
headers = headers.set('Authorization', `Bearer ${token}`);
const authRequest = req.clone({ headers: headers });
return next.handle(authRequest);
}
else {
const authRequest = req.clone();
return next.handle(authRequest);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaAuthInterceptor, deps: [{ token: SpaasConfigModel }, { token: OktaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaAuthInterceptor, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaAuthInterceptor, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: SpaasConfigModel, decorators: [{
type: Inject,
args: [SpaasConfigModel]
}] }, { type: OktaService }] });
class PreloaderService {
constructor() {
this.preloaderMsgs = [];
this.preloaderMsgs$ = new BehaviorSubject([]);
}
// ********************************************************************************************************
// SAVE DATA
// ********************************************************************************************************
/**
* Activates the preloader overlay ("<spaas-preloader>" to be added to your app.component.html).
*
* @param preloaderMsg will be added to the list of messages, to be shown as feedback to the user.
*/
start(preloaderMsg) {
this.preloaderMsgs.push(preloaderMsg);
this.newPreloaderMsg();
}
/**
* Removes the "preloaderMsg" from the list of preloader messages.
*
* @param preloaderMsg message to be removed from the list. If the "preloaderMsg" was the last one on the list,
* the preloader overlay will be hidden.
*/
stop(preloaderMsg) {
this.preloaderMsgs = this.preloaderMsgs.filter((l) => l !== preloaderMsg);
this.newPreloaderMsg();
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newPreloaderMsg() {
this.preloaderMsgs$.next(this.preloaderMsgs);
}
onNewPreloaderMsg() {
return this.preloaderMsgs$.asObservable();
}
getPreloaderMsgs() {
return JSON.parse(JSON.stringify(this.preloaderMsgs$.getValue()));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PreloaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PreloaderService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PreloaderService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
class PreloaderComponent extends BaseComponent {
constructor(preloaderService) {
super();
this.preloaderService = preloaderService;
this.isActive = false;
this.mostRecent = '';
this.preloaderService.onNewPreloaderMsg()
.pipe(takeUntil(this.onDestroy$))
.subscribe((msgs) => {
this.isActive = msgs.length > 0;
this.mostRecent = msgs[msgs.length - 1] || '';
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PreloaderComponent, deps: [{ token: PreloaderService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: PreloaderComponent, isStandalone: false, selector: "spaas-preloader", usesInheritance: true, ngImport: i0, template: "@if (isActive) {\r\n <div class=\"preloader\">\r\n <mat-progress-bar [mode]=\"'indeterminate'\" class=\"preloader__progbar\">\r\n </mat-progress-bar>\r\n <div class=\"preloader__text\">\r\n {{ mostRecent }}\r\n </div>\r\n </div>\r\n}\r\n", styles: [".preloader{animation:anim-visible 0s ease forwards;background:hsla(var(--bg-h),var(--bg-s),var(--bg-l),var(--bg-op-overlay));cursor:wait;height:100%;left:0;opacity:0;visibility:hidden;position:fixed;top:0;width:100vw;z-index:9996}.preloader__text{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);font-family:BebasNeue,Lato,Arial,sans-serif;font-size:24px;margin:14px auto;padding:14px;text-align:center;width:fit-content}.preloader__progbar{left:0;position:fixed;top:0;width:100%}\n"], dependencies: [{ kind: "component", type: i5.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PreloaderComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-preloader', standalone: false, template: "@if (isActive) {\r\n <div class=\"preloader\">\r\n <mat-progress-bar [mode]=\"'indeterminate'\" class=\"preloader__progbar\">\r\n </mat-progress-bar>\r\n <div class=\"preloader__text\">\r\n {{ mostRecent }}\r\n </div>\r\n </div>\r\n}\r\n", styles: [".preloader{animation:anim-visible 0s ease forwards;background:hsla(var(--bg-h),var(--bg-s),var(--bg-l),var(--bg-op-overlay));cursor:wait;height:100%;left:0;opacity:0;visibility:hidden;position:fixed;top:0;width:100vw;z-index:9996}.preloader__text{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);color:hsla(var(--color-h),var(--color-s),var(--color-l),1);font-family:BebasNeue,Lato,Arial,sans-serif;font-size:24px;margin:14px auto;padding:14px;text-align:center;width:fit-content}.preloader__progbar{left:0;position:fixed;top:0;width:100%}\n"] }]
}], ctorParameters: () => [{ type: PreloaderService }] });
class ResizableComponent {
constructor(localStorageService, sessionStorageService) {
this.localStorageService = localStorageService;
this.sessionStorageService = sessionStorageService;
this.initSizePx = 324;
this.minSizePx = 144;
this.maxSizePx = 9999;
this.resizeAxis = 'y';
this.storage = 'local';
this.storageId = '';
this.sizePxChange = new EventEmitter();
this.sizePx = 324;
}
ngOnInit() {
if (Number.isNaN(Number(this.initSizePx))) {
throw new Error('the value you provided for initial size is not a number');
}
this.initSize();
}
initSize() {
let heightFromStorage = 0, initHeight = this.initSizePx;
if (this.storageId) {
if (this.storage === 'local') {
heightFromStorage = this.localStorageService.getItem(this.storageId);
}
else {
heightFromStorage = this.sessionStorageService.getItem(this.storageId);
}
if (Number.isNaN(Number(heightFromStorage))) {
heightFromStorage = 0;
}
}
// value stored gets priority (user has already changed the height)
this.sizePx = heightFromStorage || initHeight;
}
onDragResizeEnd(e) {
e.source.reset();
const inc = this.resizeAxis === 'y' ? e.distance.y : e.distance.x;
this.sizePx += inc;
this.sizePx = Math.min(Math.max(this.sizePx, this.minSizePx), this.maxSizePx);
this.sizePxChange.emit(this.sizePx);
if (this.storageId) {
if (this.storage === 'local') {
this.localStorageService.setItem(this.storageId, this.sizePx);
}
else {
this.sessionStorageService.setItem(this.storageId, this.sizePx);
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ResizableComponent, deps: [{ token: LocalStorageService }, { token: SessionStorageService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: ResizableComponent, isStandalone: false, selector: "spaas-resizable", inputs: { initSizePx: "initSizePx", minSizePx: "minSizePx", maxSizePx: "maxSizePx", resizeAxis: "resizeAxis", storage: "storage", storageId: "storageId" }, outputs: { sizePxChange: "sizePxChange" }, ngImport: i0, template: "<div class=\"resizable pos-relative\"\r\n [class.horizontal]=\"resizeAxis === 'x'\"\r\n [style.--resizable-size]=\"sizePx + 'px'\">\r\n <ng-content></ng-content>\r\n <div (cdkDragEnded)=\"onDragResizeEnd($event)\"\r\n [cdkDragLockAxis]=\"resizeAxis\"\r\n cdkDrag\r\n class=\"resizable__handle\">\r\n </div>\r\n</div>\r\n", styles: [".resizable{height:var(--resizable-size);padding-bottom:10px;width:100%}.resizable__handle{bottom:0;cursor:ns-resize;height:8px;left:0;position:absolute;transition:background-color .4s;width:100%;z-index:9000}.resizable__handle:before{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);border-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1);border-style:solid;border-width:1px 0 1px 0;content:\"\";height:2px;left:calc(50% - 22px);position:absolute;top:2px;width:44px}.resizable__handle:hover,.resizable__handle.cdk-drag-dragging{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),.2)}.resizable.horizontal{height:100%;padding-bottom:0;padding-right:10px;width:var(--resizable-size)}.resizable.horizontal .resizable__handle{cursor:ew-resize;height:100%;left:auto;right:0;width:8px}.resizable.horizontal .resizable__handle:before{border-width:0 1px 0 1px;width:2px;height:44px;left:2px;top:calc(50% - 22px)}\n"], dependencies: [{ kind: "directive", type: i3$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ResizableComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-resizable', standalone: false, template: "<div class=\"resizable pos-relative\"\r\n [class.horizontal]=\"resizeAxis === 'x'\"\r\n [style.--resizable-size]=\"sizePx + 'px'\">\r\n <ng-content></ng-content>\r\n <div (cdkDragEnded)=\"onDragResizeEnd($event)\"\r\n [cdkDragLockAxis]=\"resizeAxis\"\r\n cdkDrag\r\n class=\"resizable__handle\">\r\n </div>\r\n</div>\r\n", styles: [".resizable{height:var(--resizable-size);padding-bottom:10px;width:100%}.resizable__handle{bottom:0;cursor:ns-resize;height:8px;left:0;position:absolute;transition:background-color .4s;width:100%;z-index:9000}.resizable__handle:before{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1);border-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1);border-style:solid;border-width:1px 0 1px 0;content:\"\";height:2px;left:calc(50% - 22px);position:absolute;top:2px;width:44px}.resizable__handle:hover,.resizable__handle.cdk-drag-dragging{background-color:hsla(var(--color-h),var(--color-s),var(--color-l),.2)}.resizable.horizontal{height:100%;padding-bottom:0;padding-right:10px;width:var(--resizable-size)}.resizable.horizontal .resizable__handle{cursor:ew-resize;height:100%;left:auto;right:0;width:8px}.resizable.horizontal .resizable__handle:before{border-width:0 1px 0 1px;width:2px;height:44px;left:2px;top:calc(50% - 22px)}\n"] }]
}], ctorParameters: () => [{ type: LocalStorageService }, { type: SessionStorageService }], propDecorators: { initSizePx: [{
type: Input
}], minSizePx: [{
type: Input
}], maxSizePx: [{
type: Input
}], resizeAxis: [{
type: Input
}], storage: [{
type: Input
}], storageId: [{
type: Input
}], sizePxChange: [{
type: Output
}] } });
/**
* The toggle component provides a custom toggle-look for checkboxes,
* in line with the Fluid UI theming.
*/
class ToggleComponent extends BaseComponent {
constructor() {
super();
/** The boolean form control to bind to the toggle (checkbox) */
this.ctrl = new FormControl(false, { nonNullable: true });
/**
* The unique id to reference the input with (necessary for label binding). If you have multiple
* toggles, like in each row of a table, you'd typically use the for-index for this
*/
this.id = '';
/** The label to display next to the toggle (clickable) */
this.label = '';
/** The label position, to the left or right of the toggle */
this.labelPosition = 'right';
/** Smaller subtext for underneath the label, usually to provide a more detailed description */
this.subText = '';
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: ToggleComponent, isStandalone: false, selector: "spaas-toggle", inputs: { ctrl: "ctrl", id: "id", label: "label", labelPosition: "labelPosition", subText: "subText" }, usesInheritance: true, ngImport: i0, template: "<div class=\"flex column-gap-7 width-fit-content\"\r\n [ngClass]=\"labelPosition === 'right' ? 'row' : 'row-reverse txt-right'\">\r\n\r\n <input type=\"checkbox\"\r\n class=\"tgl tgl-flat\"\r\n [formControl]=\"ctrl\"\r\n [id]=\"'toggle_' + id\">\r\n <label [for]=\"'toggle_' + id\" class=\"tgl-btn\"></label>\r\n\r\n @if (label) {\r\n <label [for]=\"'toggle_' + id\">\r\n {{ label }}\r\n @if (subText) {\r\n <div class=\"tgl-subtxt\">\r\n {{ subText }}\r\n </div>\r\n }\r\n </label>\r\n }\r\n\r\n</div>\r\n", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ToggleComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-toggle', standalone: false, template: "<div class=\"flex column-gap-7 width-fit-content\"\r\n [ngClass]=\"labelPosition === 'right' ? 'row' : 'row-reverse txt-right'\">\r\n\r\n <input type=\"checkbox\"\r\n class=\"tgl tgl-flat\"\r\n [formControl]=\"ctrl\"\r\n [id]=\"'toggle_' + id\">\r\n <label [for]=\"'toggle_' + id\" class=\"tgl-btn\"></label>\r\n\r\n @if (label) {\r\n <label [for]=\"'toggle_' + id\">\r\n {{ label }}\r\n @if (subText) {\r\n <div class=\"tgl-subtxt\">\r\n {{ subText }}\r\n </div>\r\n }\r\n </label>\r\n }\r\n\r\n</div>\r\n" }]
}], ctorParameters: () => [], propDecorators: { ctrl: [{
type: Input,
args: [{ required: true }]
}], id: [{
type: Input,
args: [{ required: true }]
}], label: [{
type: Input
}], labelPosition: [{
type: Input
}], subText: [{
type: Input
}] } });
class SettingsFormModel {
constructor(settings) {
this.dark = new FormControl(settings.dark, { nonNullable: true });
this.decimalSeparator = new FormControl(settings.decimalSeparator, { nonNullable: true });
this.exportExtension = new FormControl(settings.exportExtension, { nonNullable: true });
}
}
/**
* Settings component that you can simply inject in an otherwise empty 'settings' screen.
* To let the user choose some basic preferences like dark or light theme.
* The component uses content projection to allow you to add any app-specific settings you want to persist.
*/
class SettingsComponent extends BaseComponent {
constructor(oktaService, settingsService, themeService) {
super();
this.oktaService = oktaService;
this.settingsService = settingsService;
this.themeService = themeService;
this.settingTitle = 'These are your settings';
this.darkModeButtonTitle = 'dark mode';
this.darkModeHintText = ' rest your eyes a bit, switch to dark mode';
this.exportDescriptionText = 'When downloading data, save as';
this.excelExportRadioText = 'Excel Workbook (.xlsx)';
this.csvExportRadioText = 'CSV file (.csv)';
this.decimalSeparatorText = 'Your decimal separator in Excel';
this.dotRadioText = 'dot';
this.commaRadioText = 'comma';
this.user = new OktaUserModel({});
this.onNewUser();
this.settings = this.settingsService.getSettings();
this.settingsForm = new FormGroup(new SettingsFormModel(this.settings));
}
onNewUser() {
this.oktaService.onNewUserInfo()
.pipe(takeUntil(this.onDestroy$))
.subscribe((user) => {
this.user = user;
});
}
onToggleTheme() {
this.updateSettings();
this.themeService.toggleTheme();
}
updateSettings() {
// update settings with the form values. Leave extraData untouched, not handled by this component
this.settings.dark = this.settingsForm.controls.dark.value;
this.settings.decimalSeparator = this.settingsForm.controls.decimalSeparator.value;
this.settings.exportExtension = this.settingsForm.controls.exportExtension.value;
// broadcast the new settings
this.settingsService.newSettings(this.settings);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SettingsComponent, deps: [{ token: OktaService }, { token: SettingsService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: SettingsComponent, isStandalone: false, selector: "spaas-settings", inputs: { settingTitle: "settingTitle", darkModeButtonTitle: "darkModeButtonTitle", darkModeHintText: "darkModeHintText", exportDescriptionText: "exportDescriptionText", excelExportRadioText: "excelExportRadioText", csvExportRadioText: "csvExportRadioText", decimalSeparatorText: "decimalSeparatorText", dotRadioText: "dotRadioText", commaRadioText: "commaRadioText" }, usesInheritance: true, ngImport: i0, template: "<div class=\"settings\">\r\n\r\n <div class=\"half-screen\"\r\n [formGroup]=\"settingsForm\">\r\n\r\n <h3>{{ settingTitle }}{{ user.firstName ? ', ' + (user.firstName | titlecase) : '' }}</h3>\r\n\r\n <!-- dark mode -->\r\n <div>\r\n <spaas-toggle id=\"dark\"\r\n [ctrl]=\"settingsForm.controls.dark\"\r\n [label]=\"darkModeButtonTitle\"\r\n [subText]=\"darkModeHintText\"\r\n (change)=\"onToggleTheme()\">\r\n </spaas-toggle>\r\n </div>\r\n\r\n <!-- export type -->\r\n <div>\r\n {{ exportDescriptionText }}\r\n <mat-radio-group aria-label=\"select an export type\"\r\n class=\"flex col\"\r\n [formControl]=\"settingsForm.controls.exportExtension\"\r\n (change)=\"updateSettings()\">\r\n <mat-radio-button value=\"xlsx\">{{ excelExportRadioText }}</mat-radio-button>\r\n <mat-radio-button value=\"csv\">{{ csvExportRadioText }}</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- decimal separator -->\r\n <div>\r\n {{ decimalSeparatorText }}\r\n <mat-radio-group aria-label=\"select a decimal separator\"\r\n class=\"flex col\"\r\n [formControl]=\"settingsForm.controls.decimalSeparator\"\r\n (change)=\"updateSettings()\">\r\n <mat-radio-button value=\"dot\">{{ dotRadioText }}</mat-radio-button>\r\n <mat-radio-button value=\"comma\">{{ commaRadioText }}</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- projected content -->\r\n <div>\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n </div>\r\n\r\n <spaas-bg bgImg=\"employee_solar\"></spaas-bg>\r\n\r\n</div>\r\n", styles: [".settings{animation:anim-fade-in 1s ease;position:relative}\n"], dependencies: [{ kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i5$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "directive", type: i4$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i4$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: BgComponent, selector: "spaas-bg", inputs: ["bgX", "bgY", "bgPortrait", "bgImg", "bgAnimate"] }, { kind: "component", type: ToggleComponent, selector: "spaas-toggle", inputs: ["ctrl", "id", "label", "labelPosition", "subText"] }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SettingsComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-settings', standalone: false, template: "<div class=\"settings\">\r\n\r\n <div class=\"half-screen\"\r\n [formGroup]=\"settingsForm\">\r\n\r\n <h3>{{ settingTitle }}{{ user.firstName ? ', ' + (user.firstName | titlecase) : '' }}</h3>\r\n\r\n <!-- dark mode -->\r\n <div>\r\n <spaas-toggle id=\"dark\"\r\n [ctrl]=\"settingsForm.controls.dark\"\r\n [label]=\"darkModeButtonTitle\"\r\n [subText]=\"darkModeHintText\"\r\n (change)=\"onToggleTheme()\">\r\n </spaas-toggle>\r\n </div>\r\n\r\n <!-- export type -->\r\n <div>\r\n {{ exportDescriptionText }}\r\n <mat-radio-group aria-label=\"select an export type\"\r\n class=\"flex col\"\r\n [formControl]=\"settingsForm.controls.exportExtension\"\r\n (change)=\"updateSettings()\">\r\n <mat-radio-button value=\"xlsx\">{{ excelExportRadioText }}</mat-radio-button>\r\n <mat-radio-button value=\"csv\">{{ csvExportRadioText }}</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- decimal separator -->\r\n <div>\r\n {{ decimalSeparatorText }}\r\n <mat-radio-group aria-label=\"select a decimal separator\"\r\n class=\"flex col\"\r\n [formControl]=\"settingsForm.controls.decimalSeparator\"\r\n (change)=\"updateSettings()\">\r\n <mat-radio-button value=\"dot\">{{ dotRadioText }}</mat-radio-button>\r\n <mat-radio-button value=\"comma\">{{ commaRadioText }}</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- projected content -->\r\n <div>\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n </div>\r\n\r\n <spaas-bg bgImg=\"employee_solar\"></spaas-bg>\r\n\r\n</div>\r\n", styles: [".settings{animation:anim-fade-in 1s ease;position:relative}\n"] }]
}], ctorParameters: () => [{ type: OktaService }, { type: SettingsService }, { type: ThemeService }], propDecorators: { settingTitle: [{
type: Input
}], darkModeButtonTitle: [{
type: Input
}], darkModeHintText: [{
type: Input
}], exportDescriptionText: [{
type: Input
}], excelExportRadioText: [{
type: Input
}], csvExportRadioText: [{
type: Input
}], decimalSeparatorText: [{
type: Input
}], dotRadioText: [{
type: Input
}], commaRadioText: [{
type: Input
}] } });
class SyncScrollModel {
constructor() {
this.absX = 0;
this.ratioVisible = 0;
this.relX = 0;
}
}
class SyncScrollService {
constructor() {
this.scrollX$ = new BehaviorSubject({ absX: 0, relX: 0, ratioVisible: 1 });
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newScrollX(x) {
// console.log(x);
this.scrollX$.next(x);
}
onNewScrollX() {
return this.scrollX$.asObservable();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SyncScrollService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SyncScrollService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SyncScrollService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}] });
class SyncScrollDirective {
constructor(el, syncScrollService) {
this.el = el;
this.syncScrollService = syncScrollService;
this.curSync = new SyncScrollModel();
this.onDestroy$ = new Subject();
this.syncScrollService.onNewScrollX()
.pipe(takeUntil(this.onDestroy$))
// .pipe(debounceTime(40)) // TODO: evaluate whether to debounce or not
.subscribe((x) => {
this.curSync = x;
this.el.nativeElement.scrollLeft = x.absX;
});
}
onScroll(e) {
// only broadcast event if different scroll (to prevent slave components from also firing an update)
if (e.target.scrollLeft !== this.curSync?.absX) {
this.syncScrollService.newScrollX({
absX: e.target.scrollLeft,
relX: e.target.scrollLeft / e.target.scrollWidth,
ratioVisible: e.target.clientWidth / e.target.scrollWidth,
});
}
}
ngOnDestroy() {
this.onDestroy$.next();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SyncScrollDirective, deps: [{ token: i0.ElementRef }, { token: SyncScrollService }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.1.5", type: SyncScrollDirective, isStandalone: false, selector: "[spaasSyncScroll]", host: { listeners: { "scroll": "onScroll($event)" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SyncScrollDirective, decorators: [{
type: Directive,
args: [{
selector: '[spaasSyncScroll]',
standalone: false
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: SyncScrollService }], propDecorators: { onScroll: [{
type: HostListener,
args: ['scroll', ['$event']]
}] } });
class SlideOutComponent extends BaseComponent {
constructor(slideOutService) {
super();
this.slideOutService = slideOutService;
this.slideOut = new SlideOutModel(null);
this.providersInjector = undefined;
this.getSlideOut();
}
ngOnDestroy() {
this.slideOutService.newSlideOut(null);
super.ngOnDestroy();
}
// ********************************************************************************************************
// LOAD DATA
// ********************************************************************************************************
getSlideOut() {
this.slideOutService.onNewSlideOut()
.pipe(takeUntil(this.onDestroy$))
.subscribe((so) => {
this.slideOut = so;
if (this.slideOut?.providers?.length) {
this.providersInjector = Injector.create({
providers: this.slideOut.providers,
});
}
});
}
// ********************************************************************************************************
// UI
// ********************************************************************************************************
onClose() {
this.slideOutService.newSlideOut(null);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SlideOutComponent, deps: [{ token: SlideOutService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: SlideOutComponent, isStandalone: false, selector: "spaas-slide-out", usesInheritance: true, ngImport: i0, template: "<div class=\"slide-out\"\r\n [class.visible]=\"slideOut.type\">\r\n\r\n <div class=\"slide-out__close\">\r\n <mat-icon (click)=\"onClose()\">clear</mat-icon>\r\n </div>\r\n\r\n <div class=\"slide-out__content\">\r\n <ng-container *ngComponentOutlet=\"slideOut.component; inputs: slideOut.data; injector: providersInjector\">\r\n </ng-container>\r\n </div>\r\n</div>\r\n\r\n", styles: [".slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9004}.slide-out.visible{transform:translateZ(0)}.slide-out.visible .slide-out__close{animation:rotate .6s;opacity:1}.slide-out__close{color:hsla(var(--error-h),var(--error-s),var(--error-l),1);opacity:0;position:fixed;right:54px;top:20px;z-index:9999}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__close{right:10px}}.slide-out__close .mat-icon{font-size:28px!important;height:28px!important;line-height:28px!important;width:28px!important}.slide-out__content{height:calc(100vh - 28px);margin-left:88px;overflow-y:auto;overscroll-behavior:contain;position:fixed;margin-top:14px;width:calc(100% - 176px);z-index:9005}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__content{margin-left:58px;width:calc(100% - 116px)}}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(90deg)}}\n"], dependencies: [{ kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: i3$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SlideOutComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-slide-out', standalone: false, template: "<div class=\"slide-out\"\r\n [class.visible]=\"slideOut.type\">\r\n\r\n <div class=\"slide-out__close\">\r\n <mat-icon (click)=\"onClose()\">clear</mat-icon>\r\n </div>\r\n\r\n <div class=\"slide-out__content\">\r\n <ng-container *ngComponentOutlet=\"slideOut.component; inputs: slideOut.data; injector: providersInjector\">\r\n </ng-container>\r\n </div>\r\n</div>\r\n\r\n", styles: [".slide-out{background-color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),.94);height:100vh;position:fixed;left:0;top:0;transform:translate3d(-100%,0,0);transition:transform .2s;width:100%;z-index:9004}.slide-out.visible{transform:translateZ(0)}.slide-out.visible .slide-out__close{animation:rotate .6s;opacity:1}.slide-out__close{color:hsla(var(--error-h),var(--error-s),var(--error-l),1);opacity:0;position:fixed;right:54px;top:20px;z-index:9999}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__close{right:10px}}.slide-out__close .mat-icon{font-size:28px!important;height:28px!important;line-height:28px!important;width:28px!important}.slide-out__content{height:calc(100vh - 28px);margin-left:88px;overflow-y:auto;overscroll-behavior:contain;position:fixed;margin-top:14px;width:calc(100% - 176px);z-index:9005}@media screen and (min-width: 768px) and (max-width: 1024px) and (max-height: 1024px) and (orientation: portrait),screen and (max-width: 767px) and (orientation: portrait),screen and (max-height: 420px) and (orientation: landscape){.slide-out__content{margin-left:58px;width:calc(100% - 116px)}}@keyframes rotate{0%{transform:rotate(0)}to{transform:rotate(90deg)}}\n"] }]
}], ctorParameters: () => [{ type: SlideOutService }] });
class MenuSideBarSubmenuItemComponent {
constructor(changeDetectionRef) {
this.changeDetectionRef = changeDetectionRef;
this.clicked = new EventEmitter();
this.isThereSubmenus = false;
}
ngAfterViewInit() {
this.isThereSubmenus = this.submenuList?.submenuItems;
this.changeDetectionRef.detectChanges();
}
onClick(event) {
// we block the trickling up of the click event if it has children
// (items with children should not close the entire submenu)
if (this.isThereSubmenus) {
event.stopPropagation();
}
this.clicked.emit(event);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarSubmenuItemComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.1.5", type: MenuSideBarSubmenuItemComponent, isStandalone: false, selector: "spaas-submenu-side-bar-item", outputs: { clicked: "clicked" }, queries: [{ propertyName: "submenuList", first: true, predicate: MenuSideBarSubmenuListComponent, descendants: true }], ngImport: i0, template: "<div spaasHover=\"show-submenu\"\r\n class=\"mm-side-bar__icon__submenu-list__submenu_item flex align-center space-between\"\r\n (click)=\"onClick($event)\">\r\n <div class=\"flex space-between align-center full-width\">\r\n <ng-content></ng-content>\r\n\r\n @if (isThereSubmenus) {\r\n <mat-icon class=\"submenu-arrow\" fontIcon=\"arrow_forward_ios\"></mat-icon>\r\n }\r\n </div>\r\n <div class=\"mm-side-bar__icon__submenu-list subsequent-submenu flex column\">\r\n <ng-content select=\"spaas-submenu-side-bar-list\"></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"], dependencies: [{ kind: "component", type: i3$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: HoverDirective, selector: "[spaasHover]", inputs: ["spaasHover"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: MenuSideBarSubmenuItemComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-submenu-side-bar-item', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div spaasHover=\"show-submenu\"\r\n class=\"mm-side-bar__icon__submenu-list__submenu_item flex align-center space-between\"\r\n (click)=\"onClick($event)\">\r\n <div class=\"flex space-between align-center full-width\">\r\n <ng-content></ng-content>\r\n\r\n @if (isThereSubmenus) {\r\n <mat-icon class=\"submenu-arrow\" fontIcon=\"arrow_forward_ios\"></mat-icon>\r\n }\r\n </div>\r\n <div class=\"mm-side-bar__icon__submenu-list subsequent-submenu flex column\">\r\n <ng-content select=\"spaas-submenu-side-bar-list\"></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".mm-side-bar{animation:anim-fade-in .4s .2s ease forwards;height:calc(100vh - 88px);left:0;opacity:0;position:fixed;top:44px;width:44px;z-index:9994}.mm-side-bar__title,.mm-side-bar__env{font-family:BebasNeue,Lato,Arial,sans-serif;font-size:28px;text-align:right;text-orientation:sideways;transform:rotate(180deg);-webkit-user-select:none;user-select:none;width:44px;writing-mode:vertical-lr;margin-top:5px}.mm-side-bar__title{max-height:50vh;padding:44px 0 7px 2px}.mm-side-bar__title.with-min-height{min-height:174px}@media screen and (max-height: 544px){.mm-side-bar__title{display:none}}.mm-side-bar__env{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);color:#fff;margin-bottom:7px;padding:14px 0 14px 2px}.mm-side-bar__env.acc,.mm-side-bar__env.hom{background-color:orange}.mm-side-bar__icon{cursor:pointer;font-family:BebasNeue,Lato,Arial,sans-serif;font-size:84%;height:34px;line-height:26px;padding:4px;position:relative;text-align:center;transition:color .4s;width:44px}.mm-side-bar__icon.submenu-with-hover:hover{background-color:hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--bg-accent)),1)}.mm-side-bar__icon.with-hover:hover{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.with-divider{border-top:1px solid hsla(var(--bg-h),var(--bg-s),calc(var(--bg-l) + var(--table-even)),1);height:calc(34px + var(--margin-top) * .5);margin-top:calc(var(--margin-top) * .5);padding-top:calc(4px + var(--margin-top) * .5)}.mm-side-bar__icon:not(.with-divider){margin-top:var(--margin-top)}.mm-side-bar__icon.active{color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1)}.mm-side-bar__icon.active:before,.mm-side-bar__icon.active:after{background-color:hsla(var(--error-h),var(--error-s),var(--error-l),1);content:\"\";height:2px;position:absolute;right:2px;top:7px;width:10px;z-index:900}.mm-side-bar__icon.active:before{transform:rotate(45deg)}.mm-side-bar__icon.active:after{transform:rotate(-45deg)}.mm-side-bar__icon.disabled:before,.mm-side-bar__icon.disabled:after{background-color:hsla(var(--disabled-h),var(--disabled-s),var(--disabled-l),1)}.mm-side-bar__icon__submenu-list{display:none;position:absolute;top:0;transition-duration:.3s;width:var(--width-submenu)}.mm-side-bar__icon__submenu-list__wrapper{background-color:var(--mat-menu-container-color, var(--mat-sys-surface-container))}.mm-side-bar__icon__submenu-list *{-webkit-user-select:none;user-select:none}.mm-side-bar__icon__submenu-list.first-submenu{left:44px}.mm-side-bar__icon__submenu-list.subsequent-submenu{left:var(--width-submenu)}.mm-side-bar__icon__submenu-list__submenu_item{font-family:Lato,Arial,sans-serif;font-weight:bolder;height:40px;padding:2px 0 2px 6px;position:relative;text-align:left;transition-duration:.3s}.mm-side-bar__icon__submenu-list__submenu_item .submenu-arrow{font-size:10pt!important}.mm-side-bar__icon__submenu-list__submenu_item:hover{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),var(--primary-op-min));padding-left:8px}.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>span.label,.mm-side-bar__icon__submenu-list__submenu_item:hover>div>div>.submenu-arrow{color:hsla(var(--bg-h),var(--bg-s),var(--bg-l),1)}.show-submenu>.mm-side-bar__icon__submenu-list{display:flex}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { submenuList: [{
type: ContentChild,
args: [MenuSideBarSubmenuListComponent]
}], clicked: [{
type: Output
}] } });
class UserInfoComponent {
constructor(oktaService) {
this.oktaService = oktaService;
this.currentUser = null;
this.userInitials = '';
}
ngOnInit() {
this.oktaService.onNewUserInfo()
.subscribe((userInfo) => {
this.currentUser = userInfo;
if (this.currentUser) {
this.userInitials = this.getUserInitials(this.currentUser);
}
});
}
getUserInitials(userInfo) {
const { firstName, lastName } = userInfo;
return `${firstName.charAt(0).toUpperCase()}${lastName.charAt(0).toUpperCase()}`;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UserInfoComponent, deps: [{ token: OktaService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.1.5", type: UserInfoComponent, isStandalone: false, selector: "spaas-user-info", ngImport: i0, template: "<div class=\"flex center\"\r\n [matMenuTriggerFor]=\"menu\">\r\n <mat-icon>account_circle</mat-icon>\r\n</div>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"user-menu-panel\">\r\n <div class=\"flex row pad-big space-between\">\r\n\r\n <div class=\"menu-bubble flex align-center center txt-bold\">\r\n {{ userInitials }}\r\n </div>\r\n\r\n <div class=\"flex column pad-small-top pad-big-right pad-big-left\">\r\n <h3>{{ currentUser?.firstName }} {{ currentUser?.lastName | titlecase }}</h3>\r\n <p>\r\n {{ currentUser?.userId }}<br>\r\n {{ currentUser?.email }}\r\n </p>\r\n <!--@if (currentUser?.groups) {\r\n <!–user groups–>\r\n <div class=\"flex row column-gap-10\">\r\n @for (item of currentUser?.groups; track $index) {\r\n <div class=\"group-item\">{{ item }}</div>\r\n }\r\n </div>\r\n }-->\r\n <!-- placeholder for content projection -->\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n </div>\r\n</mat-menu>\r\n", styles: [".menu-bubble{background:#d6d6d6;border-radius:50%;flex:0 0 auto;font-size:16px;height:40px;text-align:center;width:40px}.group-item{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1);padding:8px;border-radius:16px;color:#fff}\n"], dependencies: [{ kind: "component", type: i3$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i3$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: UserInfoComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-user-info', standalone: false, template: "<div class=\"flex center\"\r\n [matMenuTriggerFor]=\"menu\">\r\n <mat-icon>account_circle</mat-icon>\r\n</div>\r\n\r\n<mat-menu #menu=\"matMenu\" class=\"user-menu-panel\">\r\n <div class=\"flex row pad-big space-between\">\r\n\r\n <div class=\"menu-bubble flex align-center center txt-bold\">\r\n {{ userInitials }}\r\n </div>\r\n\r\n <div class=\"flex column pad-small-top pad-big-right pad-big-left\">\r\n <h3>{{ currentUser?.firstName }} {{ currentUser?.lastName | titlecase }}</h3>\r\n <p>\r\n {{ currentUser?.userId }}<br>\r\n {{ currentUser?.email }}\r\n </p>\r\n <!--@if (currentUser?.groups) {\r\n <!–user groups–>\r\n <div class=\"flex row column-gap-10\">\r\n @for (item of currentUser?.groups; track $index) {\r\n <div class=\"group-item\">{{ item }}</div>\r\n }\r\n </div>\r\n }-->\r\n <!-- placeholder for content projection -->\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n </div>\r\n</mat-menu>\r\n", styles: [".menu-bubble{background:#d6d6d6;border-radius:50%;flex:0 0 auto;font-size:16px;height:40px;text-align:center;width:40px}.group-item{background-color:hsla(var(--primary-h),var(--primary-s),var(--primary-l),1);padding:8px;border-radius:16px;color:#fff}\n"] }]
}], ctorParameters: () => [{ type: OktaService }] });
/**
* The SpaasModule offers all building blocks needed for a bespoke SPaaS SPA.
*
* <spaas-okta-intro> to display an intro for okta handling
* <spaas-preloader> to add a preloader to your app
* OktaAuthGuard to protect your routing
* OktaAuthInterceptor to automatically include the token in your http requests
*/
class SpaasModule {
static forRoot(config) {
return {
ngModule: SpaasModule,
providers: [{ provide: SpaasConfigModel, useValue: config }]
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SpaasModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.5", ngImport: i0, type: SpaasModule, declarations: [BaseComponent,
BgComponent,
EmbedComponent,
HoverDirective,
IntroComponent,
MenuComponent,
MenuSideBarComponent,
MenuSideBarIconComponent,
MenuSideBarSubmenuItemComponent,
MenuSideBarSubmenuListComponent,
NewVersionComponent,
PreloaderComponent,
PwaInstallComponent,
ResizableComponent,
SettingsComponent,
SlideOutComponent,
SyncScrollDirective,
ToggleComponent,
UserInfoComponent], imports: [CommonModule,
FormsModule,
MaterialModule,
ReactiveFormsModule,
RouterModule, i2.ServiceWorkerModule], exports: [BaseComponent,
BgComponent,
EmbedComponent,
HoverDirective,
IntroComponent,
MenuComponent,
MenuSideBarComponent,
MenuSideBarIconComponent,
MenuSideBarSubmenuItemComponent,
MenuSideBarSubmenuListComponent,
PreloaderComponent,
ResizableComponent,
SettingsComponent,
SlideOutComponent,
SyncScrollDirective,
ToggleComponent,
UserInfoComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SpaasModule, providers: [
provideAppInitializer(() => {
const initializerFn = ((appInitService) => () => {
return appInitService.initApp();
})(inject(AppInitService));
return initializerFn();
}),
{ provide: HTTP_INTERCEPTORS, useClass: OktaAuthInterceptor, multi: true },
provideHttpClient(withInterceptorsFromDi()),
], imports: [CommonModule,
FormsModule,
MaterialModule,
ReactiveFormsModule,
RouterModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: !window.location.host.includes('localhost') })] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SpaasModule, decorators: [{
type: NgModule,
args: [{
declarations: [
BaseComponent,
BgComponent,
EmbedComponent,
HoverDirective,
IntroComponent,
MenuComponent,
MenuSideBarComponent,
MenuSideBarIconComponent,
MenuSideBarSubmenuItemComponent,
MenuSideBarSubmenuListComponent,
NewVersionComponent,
PreloaderComponent,
PwaInstallComponent,
ResizableComponent,
SettingsComponent,
SlideOutComponent,
SyncScrollDirective,
ToggleComponent,
UserInfoComponent
],
exports: [
BaseComponent,
BgComponent,
EmbedComponent,
HoverDirective,
IntroComponent,
MenuComponent,
MenuSideBarComponent,
MenuSideBarIconComponent,
MenuSideBarSubmenuItemComponent,
MenuSideBarSubmenuListComponent,
PreloaderComponent,
ResizableComponent,
SettingsComponent,
SlideOutComponent,
SyncScrollDirective,
ToggleComponent,
UserInfoComponent
],
imports: [
CommonModule,
FormsModule,
MaterialModule,
ReactiveFormsModule,
RouterModule,
ServiceWorkerModule.register('ngsw-worker.js', { enabled: !window.location.host.includes('localhost') }),
],
providers: [
provideAppInitializer(() => {
const initializerFn = ((appInitService) => () => {
return appInitService.initApp();
})(inject(AppInitService));
return initializerFn();
}),
{ provide: HTTP_INTERCEPTORS, useClass: OktaAuthInterceptor, multi: true },
provideHttpClient(withInterceptorsFromDi()),
]
}]
}] });
class EmbeddedOnlyGuard {
constructor(embedModeService, router) {
this.embedModeService = embedModeService;
this.router = router;
}
isIframe() {
const isIframe = this.embedModeService.getEmbedMode().isIframe();
if (!isIframe) {
// set default url to "home". If "home" does not exist, router will fall back to redirect config
return this.router.parseUrl('/home');
}
return isIframe;
}
// CAN LOAD: FOR FEATURE MODULES SECURITY
canLoad(route) {
return this.isIframe();
}
// CAN ACTIVATE: FOR ROUTES SECURITY
canActivate(route, state) {
return this.isIframe();
}
canActivateChild(route, state) {
return this.canActivate(route, state);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbeddedOnlyGuard, deps: [{ token: EmbedModeService }, { token: i3$1.Router }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbeddedOnlyGuard, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: EmbeddedOnlyGuard, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: EmbedModeService }, { type: i3$1.Router }] });
class OktaAuthGuard {
constructor(activeRouteService, oktaService) {
this.activeRouteService = activeRouteService;
this.oktaService = oktaService;
}
// CAN LOAD: FOR FEATURE MODULES SECURITY
canLoad(route) {
return !!this.oktaService.getCachedAccessToken();
}
// CAN ACTIVATE: FOR ROUTES SECURITY
canActivate(route, state) {
this.activeRouteService.newActiveRoute(state.url, route.queryParams, route.params);
return !!this.oktaService.getCachedAccessToken();
}
canActivateChild(route, state) {
return this.canActivate(route, state);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaAuthGuard, deps: [{ token: ActiveRouteService }, { token: OktaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaAuthGuard, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: OktaAuthGuard, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: ActiveRouteService }, { type: OktaService }] });
/**
* Model used to replace <any>.
* Contains keys of type T.
*/
/**
* Enum used as msgType in the PostMessageModel. Will be used to know how to respond to a certain message.
*/
var PostMessageEnum;
(function (PostMessageEnum) {
PostMessageEnum["getTheme"] = "1_getTheme";
PostMessageEnum["setTheme"] = "2_setTheme";
})(PostMessageEnum || (PostMessageEnum = {}));
/**
* Model used to post messages from and to an iframe child app.
*
* @property {PostMessageEnum} msgType the type defined by PostMessageEnum. Will be used to know how
* to respond to a certain message
* @property {any} msgData any data you want to include in the PostMessage
*/
class PostMessageModel {
constructor(type, data = '') {
this.msgType = type;
this.msgData = data;
}
}
const REGEX_DEC = '^-?(0|[1-9]\\d*)(\\.\\d+)?$';
const REGEX_DEC_OR_HASH = '^[#]{1}$|^-?(0|[1-9]\\d*)(\\.\\d+)?$';
const REGEX_INT = '^[-]?\\d*$'; // only integers, also negative
const REGEX_INT_OR_1DEC = '^-?\\d+([.]\\d)?$';
const REGEX_POSITIVE_INT = '^\\d+$';
class PostMessageService {
constructor(embedModeService, settingsService, themeService) {
this.embedModeService = embedModeService;
this.settingsService = settingsService;
this.themeService = themeService;
this.onEmbedMode();
this.startListening();
}
onEmbedMode() {
this.embedModeService.onNewEmbedMode()
.subscribe((mode) => {
if (mode?.isIframe()) {
// ask for theme from parent
this.postMessage(window.parent, new PostMessageModel(PostMessageEnum.getTheme));
}
});
}
startListening() {
this.listenToPostMessages()
.subscribe((msg) => {
// **************************************
// MESSAGES TO BE PROCESSED BY PARENT
// request for theme
if (msg.msgType === PostMessageEnum.getTheme) {
console.log('parent received request for theme');
this.postMessage(this.embedModeService.embeddedWindow, new PostMessageModel(PostMessageEnum.setTheme, this.themeService.getActiveTheme().name));
}
// **************************************
// MESSAGES TO BE PROCESSED BY CHILD
// set theme received from parent
if (msg.msgType === PostMessageEnum.setTheme) {
console.log('child received theme from parent: ' + msg.msgData);
const settings = this.settingsService.getSettings();
settings.dark = msg.msgData === 'dark';
this.settingsService.newSettings(settings);
this.themeService.setActiveTheme(msg.msgData);
}
});
}
/**
* When you've embedded a SPaaS app using an iframe, you can use this method to listen to
* the messages it will post. Some messages are automatically processed, check the doc.
*/
listenToPostMessages() {
return fromEvent(window, 'message')
.pipe(map((m) => new PostMessageModel(m?.data?.msgType || '', m?.data?.msgData || '')));
}
/**
* When you've embedded a SPaaS app in an iframe and want to reply to some messages it will post,
* you can use this method to do so.
*
* @param source the MessageEventSource of the iframe. You can retrieve its source by using
* '@ViewChild('your_iframe_div') iframeDiv: ElementRef;' and then get 'this.iframeDiv.nativeElement.contentWindow'
* @param msg the actual message to send to the child app in the iframe
*/
postMessage(source, msg) {
if (source) {
source.postMessage(msg, { targetOrigin: '*' });
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PostMessageService, deps: [{ token: EmbedModeService }, { token: SettingsService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PostMessageService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: PostMessageService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: EmbedModeService }, { type: SettingsService }, { type: ThemeService }] });
class SnackbarService {
static getConfirmId(type) {
return type + '_' + performance.now();
}
constructor(snackbar, zone) {
this.snackbar = snackbar;
this.zone = zone;
this.DEF_DURATION = 6000;
this.duration = this.DEF_DURATION;
this.confirm$ = new BehaviorSubject('');
this.sbConfig = new MatSnackBarConfig();
}
/**
* Shows a Material snackbar.
*
* @param message the message to show in the snackbar
* @param action (optional) the message to show in the snackbar action button. When no action is provided, the button
* will not show
* @param append (optional, default true) specifies whether to append the new snackbar message to the previous one
* if a previous snackbar is still active
* @param duration (optional) set a one-time specific duration in milliseconds, just for this snackbar instance
*/
message(message, action = '', append = true, duration = this.duration) {
this.open(message, action, append, duration, false);
}
/**
* Shows a Material snackbar as an error (red background).
*
* @param message the message to show in the snackbar
* @param action (optional) the message to show in the snackbar action button. When no action is provided, the button
* will not show
* @param append (optional, default true) specifies whether to append the new snackbar message to the previous one
* if a previous snackbar is still active
* @param duration (optional) set a one-time specific duration in milliseconds, just for this snackbar instance
*/
error(message, action = '', append = true, duration = this.duration) {
this.open(message, action, append, duration, true);
}
open(message, action, append, duration, isError) {
this.zone.run(() => {
if (append && this.snackbar._openedSnackBarRef?.instance?.data?.message) {
message = this.snackbar._openedSnackBarRef.instance.data.message + '\n------\n' + message;
}
// reset panelClass in case the previous snackbar was an error
this.sbConfig.panelClass = isError ? 'bg-error' : '';
this.sbConfig.duration = duration;
this.snackbar.open(message, action, this.sbConfig);
});
}
/**
* Shows a Material snackbar which awaits confirmation.
*
* @param message the message to show in the snackbar
* @param action the message to show in the snackbar action button. When no action is provided, the button
* will show "Got it"
* @param confirmId a unique identifier by which you can recognise the confirmation response
* that you get when listening to "onNewConfirm". Use static method "SnackbarService.getConfirmId" to get a unique id.
* @param duration (optional) set a one-time specific duration in milliseconds, just for this snackbar instance
*/
confirm(message, action = 'Got it', confirmId, duration = this.duration) {
this.zone.run(() => {
// reset panelClass in case the previous snackbar was an error
this.sbConfig.panelClass = '';
this.sbConfig.duration = duration;
const snack = this.snackbar.open(message, action, this.sbConfig);
snack.onAction()
.subscribe(() => {
this.newConfirm(confirmId);
});
});
}
/**
* Set the global duration for all snackbars
*
* @param ms duration in milliseconds
*/
setDuration(ms) {
this.duration = ms;
}
/**
* Reset the global duration for all snackbars to default (6000)
*/
resetDuration() {
this.duration = this.DEF_DURATION;
}
// ********************************************************************************************************
// BROADCAST DATA
// ********************************************************************************************************
newConfirm(newConfirm) {
this.confirm$.next(newConfirm);
}
onNewConfirm() {
return this.confirm$.asObservable();
}
close() {
this.zone.run(() => {
this.snackbar.dismiss();
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SnackbarService, deps: [{ token: i1$2.MatSnackBar }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SnackbarService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: SnackbarService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: i1$2.MatSnackBar }, { type: i0.NgZone }] });
class ConnectionErrorInterceptor {
constructor(snackbarService) {
this.snackbarService = snackbarService;
}
intercept(req, next) {
return next.handle(req).pipe(catchError((errorResponse) => {
if (errorResponse.error instanceof ProgressEvent) {
const s = errorResponse.error;
let message = '';
if (!s.lengthComputable && s.loaded === 0) {
message = 'Unable to make a connection to the server, are you sure you are connected to the VPN ?';
}
else {
message = 'Unable to reach ' + errorResponse.url + '\nThis is usually a network related issue';
}
this.snackbarService.error(message, '', true, 60000);
}
return throwError(() => errorResponse);
}));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ConnectionErrorInterceptor, deps: [{ token: SnackbarService }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ConnectionErrorInterceptor, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: ConnectionErrorInterceptor, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: () => [{ type: SnackbarService }] });
// MODULE
/**
* Generated bundle index. Do not edit.
*/
export { ActiveRouteService, BaseComponent, BgComponent, ConfigService, ConnectionErrorInterceptor, DATA__HAS_MENU, DATA__THEME_DARK, DATA__THEME_LIGHT, EmbedComponent, EmbeddedOnlyGuard, FONT_FAMILY, HoverDirective, IntroComponent, LocalStorageService, MenuComponent, MenuSideBarComponent, MenuSideBarIconComponent, MenuSideBarSubmenuItemComponent, MenuSideBarSubmenuListComponent, NewVersionConfigModel, NewVersionService, OktaAuthGuard, OktaConfigModel, OktaService, OktaUserModel, PostMessageEnum, PostMessageModel, PostMessageService, PreloaderComponent, PreloaderService, REGEX_DEC, REGEX_DEC_OR_HASH, REGEX_INT, REGEX_INT_OR_1DEC, REGEX_POSITIVE_INT, ResizableComponent, SessionStorageService, SettingsComponent, SettingsModel, SettingsService, SlideOutComponent, SlideOutModel, SlideOutService, SnackbarService, SpaasConfigModel, SpaasExtConfigModel, SpaasModule, SyncScrollDirective, SyncScrollService, ThemeModel, ThemeService, ToggleComponent, UserInfoComponent, UtilsService, WINDOW, WindowUtilsService, dark, light };
//# sourceMappingURL=engie-group-ngx-gem-spaas.mjs.map