@yuuvis/client-shell 3.8.3 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,125 @@
1
+ import * as i1 from '@angular/common';
2
+ import { CommonModule } from '@angular/common';
3
+ import { HttpClient } from '@angular/common/http';
4
+ import * as i0 from '@angular/core';
5
+ import { inject, DOCUMENT, computed, signal, effect, Component } from '@angular/core';
6
+ import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
+ import { ReactiveFormsModule } from '@angular/forms';
8
+ import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
9
+ import * as i2 from '@angular/material/expansion';
10
+ import { MatExpansionModule } from '@angular/material/expansion';
11
+ import { MatSelectModule } from '@angular/material/select';
12
+ import * as i3 from '@angular/material/table';
13
+ import { MatTableModule } from '@angular/material/table';
14
+ import { MatTooltip } from '@angular/material/tooltip';
15
+ import { UserService, ConfigService, TranslateService, TranslatePipe } from '@yuuvis/client-core';
16
+ import { ThemeService, DEFAULT_THEME_KEY, HIGH_CONTRAST_THEME_KEY, DEFAULT_THEME } from '@yuuvis/client-framework/common';
17
+ import { ShellService } from '@yuuvis/client-shell-core';
18
+ import { map } from 'rxjs';
19
+
20
+ class SettingsPageComponent {
21
+ #themeService;
22
+ #http;
23
+ #appSettings;
24
+ #appSettingsEffect;
25
+ constructor() {
26
+ this.userService = inject(UserService);
27
+ this.config = inject(ConfigService);
28
+ this.translate = inject(TranslateService);
29
+ this.shell = inject(ShellService);
30
+ this.document = inject(DOCUMENT);
31
+ this.#themeService = inject(ThemeService);
32
+ this.#http = inject(HttpClient);
33
+ this.DEFAULT_THEME_KEY = DEFAULT_THEME_KEY;
34
+ this.HIGH_CONTRAST_THEME_KEY = HIGH_CONTRAST_THEME_KEY;
35
+ this.DEFAULT_THEME = DEFAULT_THEME;
36
+ this.disableMode = this.#themeService.disableMode;
37
+ this.customThemes = this.#themeService.customThemes;
38
+ this.currentTheme = computed(() => {
39
+ const ct = this.#themeService.customTheme();
40
+ return ct ? ct.key : undefined;
41
+ }, ...(ngDevMode ? [{ debugName: "currentTheme" }] : /* istanbul ignore next */ []));
42
+ this.clientLocales = signal([], ...(ngDevMode ? [{ debugName: "clientLocales" }] : /* istanbul ignore next */ []));
43
+ this.clientVersion = signal(undefined, ...(ngDevMode ? [{ debugName: "clientVersion" }] : /* istanbul ignore next */ []));
44
+ this.clientAboutData = signal(undefined, ...(ngDevMode ? [{ debugName: "clientAboutData" }] : /* istanbul ignore next */ []));
45
+ this.currentMode = this.#themeService.mode;
46
+ this.user = toSignal(this.userService.user$);
47
+ this.appSettings = signal([], ...(ngDevMode ? [{ debugName: "appSettings" }] : /* istanbul ignore next */ []));
48
+ this.#appSettings = this.shell.appSettings;
49
+ this.#appSettingsEffect = effect(() => {
50
+ const as = this.#appSettings();
51
+ this.#mapAppSettings(as);
52
+ }, ...(ngDevMode ? [{ debugName: "#appSettingsEffect" }] : /* istanbul ignore next */ []));
53
+ this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe(() => {
54
+ this.#mapAppSettings(this.appSettings());
55
+ });
56
+ }
57
+ #mapAppSettings(as) {
58
+ this.appSettings.set(as.map((appSetting) => {
59
+ const translatedLabel = this.translate.instant(appSetting.label);
60
+ const label = translatedLabel && !translatedLabel.startsWith('!missing') ? translatedLabel : appSetting.label;
61
+ return {
62
+ ...appSetting,
63
+ _label: label
64
+ };
65
+ }));
66
+ }
67
+ changeClientLocale(iso) {
68
+ this.userService.changeClientLocale(iso);
69
+ }
70
+ changeMode({ value }) {
71
+ if (value && value !== this.currentMode()) {
72
+ this.#themeService.toggleTheme(value);
73
+ }
74
+ }
75
+ toggleDarkMode() {
76
+ const root = document.getElementsByTagName('body')[0];
77
+ root.classList.toggle('dark');
78
+ }
79
+ changeCustomTheme({ value }) {
80
+ this.#themeService.setCustomTheme(value);
81
+ }
82
+ ngOnInit() {
83
+ this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');
84
+ this.clientLocales.set(this.config.getClientLocales());
85
+ this.getAboutData();
86
+ }
87
+ getAboutData() {
88
+ this.#http
89
+ .get('assets/about.data.json')
90
+ .pipe(map((response) => ({
91
+ ...response,
92
+ libraries: response.libraries
93
+ ? response.libraries.map((lib) => ({
94
+ ...lib,
95
+ ...(lib.license !== 'SEE LICENSE IN LICENSE'
96
+ ? { link: `https://opensource.org/license/${lib.license}` }
97
+ : {})
98
+ }))
99
+ : undefined
100
+ })))
101
+ .subscribe({
102
+ next: (response) => this.clientAboutData.set(response),
103
+ error: (error) => console.log({ error })
104
+ });
105
+ }
106
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SettingsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
107
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: SettingsPageComponent, isStandalone: true, selector: "yuv-settings", ngImport: i0, template: "<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <span class=\"subhead\">{{ 'yuv.shell.settings.client.version' | translate }}: {{ clientVersion() }}</span>\n</header>\n\n<main>\n <div class=\"content-container\">\n <!-- User Info -->\n @let user = this.user();\n @if (user) {\n <section class=\"section user\">\n <h2 class=\"section__title\">{{ user.title }}</h2>\n <div class=\"section__body user__data grid\">\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.user.email' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.email }}\n </span>\n </div>\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.tenant' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.tenant }}\n </span>\n </div>\n\n <!--<div class=\"user__data\">{{ 'yuv.shell.settings.user.name' | translate }}: {{ user.username }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.user.email' | translate }}: {{ user.email }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user.tenant }}</div>-->\n </div>\n </section>\n }\n <!-- Language Settings -->\n <section yuvOfflineDisabled class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.language' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"language\"\n [value]=\"translate.currentLang\"\n (valueChange)=\"changeClientLocale($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.language' | translate\"\n >\n @for (locale of clientLocales(); track locale.iso) {\n <mat-button-toggle [value]=\"locale.iso\">{{ locale.label }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- Mode -->\n @let currentThemeMode = currentMode();\n <section class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.mode' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"mode\"\n [value]=\"currentThemeMode\"\n (change)=\"changeMode($event)\"\n [disabled]=\"disableMode()\"\n [attr.aria-label]=\"'yuv.shell.settings.mode' | translate\"\n >\n <mat-button-toggle value=\"light\">{{ 'yuv.shell.settings.mode.light' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"dark\">{{ 'yuv.shell.settings.mode.dark' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"system\">{{ 'yuv.shell.settings.mode.system' | translate }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <p></p>\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.custom.theme' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"custom-theme\"\n [value]=\"currentTheme()\"\n (change)=\"changeCustomTheme($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.custom.theme' | translate\"\n >\n <mat-button-toggle [value]=\"DEFAULT_THEME.key\" [matTooltip]=\"DEFAULT_THEME.description | translate\">\n {{ DEFAULT_THEME.label | translate }}\n </mat-button-toggle>\n @for (theme of customThemes(); track theme.key) {\n <mat-button-toggle [value]=\"theme.key\">{{ theme.label | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- app settings -->\n @for (c of appSettings(); track $index) {\n <section class=\"section\">\n <h2 class=\"section__title\">{{ c._label }}</h2>\n <div class=\"section__body\">\n <ng-container *ngComponentOutlet=\"c.component\" />\n </div>\n </section>\n }\n\n <!-- About Info -->\n @let libraries = this.clientAboutData()?.libraries;\n @if (libraries) {\n <section class=\"section about\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.about.title' | translate }}</h2>\n <mat-expansion-panel class=\"about__panel\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{ 'yuv.shell.settings.dependency-info.title' | translate }}</mat-panel-title>\n <!-- <mat-panel-description>{{ '' | translate }}</mat-panel-description>-->\n </mat-expansion-panel-header>\n\n <ng-template matExpansionPanelContent>\n <div class=\"about__panel-content\">\n <table mat-table [dataSource]=\"libraries\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.package' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.name }}</td>\n </ng-container>\n\n <!-- Version Column -->\n <ng-container matColumnDef=\"version\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.version' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.version }}</td>\n </ng-container>\n\n <!-- License Column -->\n <ng-container matColumnDef=\"license\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.license' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (element.link) {\n <a href=\"{{ element.link }}\" target=\"_blank\">{{ element.license }}</a>\n } @else {\n {{ element.license }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"['name', 'version', 'license']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['name', 'version', 'license']\"></tr>\n </table>\n </div>\n </ng-template>\n </mat-expansion-panel>\n </section>\n }\n </div>\n</main>\n", styles: [":host{display:grid;grid-template-columns:1fr auto;grid-template-rows:auto 1fr;grid-template-areas:\"header\" \"settings\";height:100%;overflow:hidden;overflow-y:auto}:host header{grid-area:header;padding:var(--ymt-spacing-3xl)}:host header h1{margin:0}:host header .subhead{font:var(--ymt-font-subhead);color:var(--ymt-text-color-subtle)}:host main{grid-area:settings;padding:var(--ymt-spacing-m);padding-right:0;overflow-y:auto;scrollbar-gutter:stable}:host main .content-container{max-width:900px}:host main section{display:flex;flex-flow:column;padding:var(--ymt-spacing-m);margin-bottom:var(--ymt-spacing-l)}:host main .about__panel-content{overflow-x:auto}:host main .about__panel-content table{background-color:transparent}:host main .grid-row{display:grid;grid-template-columns:minmax(10ch,1fr) 11fr;grid-gap:var(--ymt-spacing-s);grid-template-areas:\"key value\";align-items:baseline}:host main .grid-col-key{font-weight:700;grid-area:key}:host main .grid-col-value{grid-area:value;word-break:break-all}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i2.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2.MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
108
+ }
109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SettingsPageComponent, decorators: [{
110
+ type: Component,
111
+ args: [{ selector: 'yuv-settings', standalone: true, imports: [
112
+ CommonModule,
113
+ TranslatePipe,
114
+ MatTooltip,
115
+ MatSelectModule,
116
+ ReactiveFormsModule,
117
+ MatButtonToggleGroup,
118
+ MatButtonToggle,
119
+ MatExpansionModule,
120
+ MatTableModule
121
+ ], template: "<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <span class=\"subhead\">{{ 'yuv.shell.settings.client.version' | translate }}: {{ clientVersion() }}</span>\n</header>\n\n<main>\n <div class=\"content-container\">\n <!-- User Info -->\n @let user = this.user();\n @if (user) {\n <section class=\"section user\">\n <h2 class=\"section__title\">{{ user.title }}</h2>\n <div class=\"section__body user__data grid\">\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.user.email' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.email }}\n </span>\n </div>\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.tenant' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.tenant }}\n </span>\n </div>\n\n <!--<div class=\"user__data\">{{ 'yuv.shell.settings.user.name' | translate }}: {{ user.username }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.user.email' | translate }}: {{ user.email }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user.tenant }}</div>-->\n </div>\n </section>\n }\n <!-- Language Settings -->\n <section yuvOfflineDisabled class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.language' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"language\"\n [value]=\"translate.currentLang\"\n (valueChange)=\"changeClientLocale($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.language' | translate\"\n >\n @for (locale of clientLocales(); track locale.iso) {\n <mat-button-toggle [value]=\"locale.iso\">{{ locale.label }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- Mode -->\n @let currentThemeMode = currentMode();\n <section class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.mode' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"mode\"\n [value]=\"currentThemeMode\"\n (change)=\"changeMode($event)\"\n [disabled]=\"disableMode()\"\n [attr.aria-label]=\"'yuv.shell.settings.mode' | translate\"\n >\n <mat-button-toggle value=\"light\">{{ 'yuv.shell.settings.mode.light' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"dark\">{{ 'yuv.shell.settings.mode.dark' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"system\">{{ 'yuv.shell.settings.mode.system' | translate }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <p></p>\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.custom.theme' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"custom-theme\"\n [value]=\"currentTheme()\"\n (change)=\"changeCustomTheme($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.custom.theme' | translate\"\n >\n <mat-button-toggle [value]=\"DEFAULT_THEME.key\" [matTooltip]=\"DEFAULT_THEME.description | translate\">\n {{ DEFAULT_THEME.label | translate }}\n </mat-button-toggle>\n @for (theme of customThemes(); track theme.key) {\n <mat-button-toggle [value]=\"theme.key\">{{ theme.label | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- app settings -->\n @for (c of appSettings(); track $index) {\n <section class=\"section\">\n <h2 class=\"section__title\">{{ c._label }}</h2>\n <div class=\"section__body\">\n <ng-container *ngComponentOutlet=\"c.component\" />\n </div>\n </section>\n }\n\n <!-- About Info -->\n @let libraries = this.clientAboutData()?.libraries;\n @if (libraries) {\n <section class=\"section about\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.about.title' | translate }}</h2>\n <mat-expansion-panel class=\"about__panel\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{ 'yuv.shell.settings.dependency-info.title' | translate }}</mat-panel-title>\n <!-- <mat-panel-description>{{ '' | translate }}</mat-panel-description>-->\n </mat-expansion-panel-header>\n\n <ng-template matExpansionPanelContent>\n <div class=\"about__panel-content\">\n <table mat-table [dataSource]=\"libraries\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.package' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.name }}</td>\n </ng-container>\n\n <!-- Version Column -->\n <ng-container matColumnDef=\"version\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.version' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.version }}</td>\n </ng-container>\n\n <!-- License Column -->\n <ng-container matColumnDef=\"license\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.license' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (element.link) {\n <a href=\"{{ element.link }}\" target=\"_blank\">{{ element.license }}</a>\n } @else {\n {{ element.license }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"['name', 'version', 'license']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['name', 'version', 'license']\"></tr>\n </table>\n </div>\n </ng-template>\n </mat-expansion-panel>\n </section>\n }\n </div>\n</main>\n", styles: [":host{display:grid;grid-template-columns:1fr auto;grid-template-rows:auto 1fr;grid-template-areas:\"header\" \"settings\";height:100%;overflow:hidden;overflow-y:auto}:host header{grid-area:header;padding:var(--ymt-spacing-3xl)}:host header h1{margin:0}:host header .subhead{font:var(--ymt-font-subhead);color:var(--ymt-text-color-subtle)}:host main{grid-area:settings;padding:var(--ymt-spacing-m);padding-right:0;overflow-y:auto;scrollbar-gutter:stable}:host main .content-container{max-width:900px}:host main section{display:flex;flex-flow:column;padding:var(--ymt-spacing-m);margin-bottom:var(--ymt-spacing-l)}:host main .about__panel-content{overflow-x:auto}:host main .about__panel-content table{background-color:transparent}:host main .grid-row{display:grid;grid-template-columns:minmax(10ch,1fr) 11fr;grid-gap:var(--ymt-spacing-s);grid-template-areas:\"key value\";align-items:baseline}:host main .grid-col-key{font-weight:700;grid-area:key}:host main .grid-col-value{grid-area:value;word-break:break-all}\n"] }]
122
+ }], ctorParameters: () => [] });
123
+
124
+ export { SettingsPageComponent };
125
+ //# sourceMappingURL=yuuvis-client-shell-settings.component-DBAxwdjk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yuuvis-client-shell-settings.component-DBAxwdjk.mjs","sources":["../../../../../libs/yuuvis/client-shell/src/lib/pages/settings/settings.component.ts","../../../../../libs/yuuvis/client-shell/src/lib/pages/settings/settings.component.html"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { HttpClient } from '@angular/common/http';\nimport { Component, computed, DOCUMENT, effect, inject, OnInit, Signal, signal } from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { MatButtonToggle, MatButtonToggleChange, MatButtonToggleGroup } from '@angular/material/button-toggle';\nimport { MatExpansionModule } from '@angular/material/expansion';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatTableModule } from '@angular/material/table';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport {\n ConfigService,\n TranslatePipe,\n TranslateService,\n UserService,\n YuvConfigLanguages,\n YuvUser\n} from '@yuuvis/client-core';\nimport {\n DEFAULT_THEME,\n DEFAULT_THEME_KEY,\n HIGH_CONTRAST_THEME_KEY,\n ThemeService\n} from '@yuuvis/client-framework/common';\nimport { ShellAppSettings, ShellService } from '@yuuvis/client-shell-core';\nimport { map } from 'rxjs';\nimport { AboutData } from './settings.model';\n\n@Component({\n selector: 'yuv-settings',\n standalone: true,\n imports: [\n CommonModule,\n TranslatePipe,\n MatTooltip,\n MatSelectModule,\n ReactiveFormsModule,\n MatButtonToggleGroup,\n MatButtonToggle,\n MatExpansionModule,\n MatTableModule\n ],\n templateUrl: './settings.component.html',\n styleUrls: ['./settings.component.scss']\n})\nexport class SettingsPageComponent implements OnInit {\n private userService = inject(UserService);\n private config = inject(ConfigService);\n public translate = inject(TranslateService);\n private shell = inject(ShellService);\n readonly document = inject(DOCUMENT);\n readonly #themeService = inject(ThemeService);\n readonly #http = inject(HttpClient);\n\n protected readonly DEFAULT_THEME_KEY = DEFAULT_THEME_KEY;\n protected readonly HIGH_CONTRAST_THEME_KEY = HIGH_CONTRAST_THEME_KEY;\n protected readonly DEFAULT_THEME = DEFAULT_THEME;\n disableMode = this.#themeService.disableMode;\n customThemes = this.#themeService.customThemes;\n currentTheme = computed(() => {\n const ct = this.#themeService.customTheme();\n return ct ? ct.key : undefined;\n });\n\n clientLocales = signal<YuvConfigLanguages[]>([]);\n clientVersion = signal<string | undefined>(undefined);\n clientAboutData = signal<AboutData | undefined>(undefined);\n currentMode = this.#themeService.mode;\n\n user: Signal<YuvUser | undefined> = toSignal(this.userService.user$);\n appSettings = signal<(ShellAppSettings & { _label: string })[]>([]);\n #appSettings = this.shell.appSettings;\n #appSettingsEffect = effect(() => {\n const as = this.#appSettings();\n this.#mapAppSettings(as);\n });\n\n constructor() {\n this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe(() => {\n this.#mapAppSettings(this.appSettings());\n });\n }\n\n #mapAppSettings(as: ShellAppSettings[]) {\n this.appSettings.set(\n as.map((appSetting) => {\n const translatedLabel = this.translate.instant(appSetting.label);\n const label = translatedLabel && !translatedLabel.startsWith('!missing') ? translatedLabel : appSetting.label;\n return {\n ...appSetting,\n _label: label\n };\n })\n );\n }\n\n changeClientLocale(iso: string) {\n this.userService.changeClientLocale(iso);\n }\n\n changeMode({ value }: MatButtonToggleChange) {\n if (value && value !== this.currentMode()) {\n this.#themeService.toggleTheme(value);\n }\n }\n\n toggleDarkMode() {\n const root = document.getElementsByTagName('body')[0];\n root.classList.toggle('dark');\n }\n\n changeCustomTheme({ value }: MatButtonToggleChange) {\n this.#themeService.setCustomTheme(value);\n }\n\n ngOnInit(): void {\n this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');\n\n this.clientLocales.set(this.config.getClientLocales());\n this.getAboutData();\n }\n\n getAboutData() {\n this.#http\n .get('assets/about.data.json')\n .pipe(\n map((response: AboutData) => ({\n ...response,\n libraries: response.libraries\n ? response.libraries.map((lib) => ({\n ...lib,\n ...(lib.license !== 'SEE LICENSE IN LICENSE'\n ? { link: `https://opensource.org/license/${lib.license}` }\n : {})\n }))\n : undefined\n }))\n )\n .subscribe({\n next: (response: AboutData) => this.clientAboutData.set(response),\n error: (error) => console.log({ error })\n });\n }\n}\n","<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <span class=\"subhead\">{{ 'yuv.shell.settings.client.version' | translate }}: {{ clientVersion() }}</span>\n</header>\n\n<main>\n <div class=\"content-container\">\n <!-- User Info -->\n @let user = this.user();\n @if (user) {\n <section class=\"section user\">\n <h2 class=\"section__title\">{{ user.title }}</h2>\n <div class=\"section__body user__data grid\">\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.user.email' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.email }}\n </span>\n </div>\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.tenant' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.tenant }}\n </span>\n </div>\n\n <!--<div class=\"user__data\">{{ 'yuv.shell.settings.user.name' | translate }}: {{ user.username }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.user.email' | translate }}: {{ user.email }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user.tenant }}</div>-->\n </div>\n </section>\n }\n <!-- Language Settings -->\n <section yuvOfflineDisabled class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.language' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"language\"\n [value]=\"translate.currentLang\"\n (valueChange)=\"changeClientLocale($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.language' | translate\"\n >\n @for (locale of clientLocales(); track locale.iso) {\n <mat-button-toggle [value]=\"locale.iso\">{{ locale.label }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- Mode -->\n @let currentThemeMode = currentMode();\n <section class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.mode' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"mode\"\n [value]=\"currentThemeMode\"\n (change)=\"changeMode($event)\"\n [disabled]=\"disableMode()\"\n [attr.aria-label]=\"'yuv.shell.settings.mode' | translate\"\n >\n <mat-button-toggle value=\"light\">{{ 'yuv.shell.settings.mode.light' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"dark\">{{ 'yuv.shell.settings.mode.dark' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"system\">{{ 'yuv.shell.settings.mode.system' | translate }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <p></p>\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.custom.theme' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"custom-theme\"\n [value]=\"currentTheme()\"\n (change)=\"changeCustomTheme($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.custom.theme' | translate\"\n >\n <mat-button-toggle [value]=\"DEFAULT_THEME.key\" [matTooltip]=\"DEFAULT_THEME.description | translate\">\n {{ DEFAULT_THEME.label | translate }}\n </mat-button-toggle>\n @for (theme of customThemes(); track theme.key) {\n <mat-button-toggle [value]=\"theme.key\">{{ theme.label | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- app settings -->\n @for (c of appSettings(); track $index) {\n <section class=\"section\">\n <h2 class=\"section__title\">{{ c._label }}</h2>\n <div class=\"section__body\">\n <ng-container *ngComponentOutlet=\"c.component\" />\n </div>\n </section>\n }\n\n <!-- About Info -->\n @let libraries = this.clientAboutData()?.libraries;\n @if (libraries) {\n <section class=\"section about\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.about.title' | translate }}</h2>\n <mat-expansion-panel class=\"about__panel\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{ 'yuv.shell.settings.dependency-info.title' | translate }}</mat-panel-title>\n <!-- <mat-panel-description>{{ '' | translate }}</mat-panel-description>-->\n </mat-expansion-panel-header>\n\n <ng-template matExpansionPanelContent>\n <div class=\"about__panel-content\">\n <table mat-table [dataSource]=\"libraries\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.package' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.name }}</td>\n </ng-container>\n\n <!-- Version Column -->\n <ng-container matColumnDef=\"version\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.version' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.version }}</td>\n </ng-container>\n\n <!-- License Column -->\n <ng-container matColumnDef=\"license\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.license' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (element.link) {\n <a href=\"{{ element.link }}\" target=\"_blank\">{{ element.license }}</a>\n } @else {\n {{ element.license }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"['name', 'version', 'license']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['name', 'version', 'license']\"></tr>\n </table>\n </div>\n </ng-template>\n </mat-expansion-panel>\n </section>\n }\n </div>\n</main>\n"],"names":[],"mappings":"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"}
@@ -537,7 +537,7 @@ const clientShellRoutes = [
537
537
  { path: 'notifications', component: NotificationsPageComponent, outlet: 'aside' },
538
538
  // tracking outlet for dialogs
539
539
  { path: 'dialogs/:id', component: DialogTrackingComponent, outlet: 'dt', canDeactivate: [closeDialogGuard] },
540
- { path: 'settings', loadComponent: () => import('./yuuvis-client-shell-settings.component-BqBDoPC9.mjs').then((comp) => comp.SettingsPageComponent) },
540
+ { path: 'settings', loadComponent: () => import('./yuuvis-client-shell-settings.component-DBAxwdjk.mjs').then((comp) => comp.SettingsPageComponent) },
541
541
  // default route
542
542
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
543
543
  // redirecting route
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@yuuvis/client-shell",
3
- "version": "3.8.3",
3
+ "version": "3.10.0",
4
4
  "author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
7
7
  "@angular/common": "^21.2.9",
8
8
  "@angular/core": "^21.2.9",
9
9
  "@angular/service-worker": "^21.2.9",
10
- "@yuuvis/client-core": "^3.8.3",
11
- "@yuuvis/client-shell-core": "^3.8.3",
12
- "@yuuvis/client-framework": "^3.8.3"
10
+ "@yuuvis/client-core": "^3.10.0",
11
+ "@yuuvis/client-shell-core": "^3.10.0",
12
+ "@yuuvis/client-framework": "^3.10.0"
13
13
  },
14
14
  "dependencies": {
15
15
  "tslib": "^2.3.0"
@@ -1,125 +0,0 @@
1
- import * as i1 from '@angular/common';
2
- import { CommonModule } from '@angular/common';
3
- import { HttpClient } from '@angular/common/http';
4
- import * as i0 from '@angular/core';
5
- import { inject, DOCUMENT, computed, signal, effect, Component } from '@angular/core';
6
- import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
- import { ReactiveFormsModule } from '@angular/forms';
8
- import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
9
- import * as i2 from '@angular/material/expansion';
10
- import { MatExpansionModule } from '@angular/material/expansion';
11
- import { MatSelectModule } from '@angular/material/select';
12
- import * as i3 from '@angular/material/table';
13
- import { MatTableModule } from '@angular/material/table';
14
- import { MatTooltip } from '@angular/material/tooltip';
15
- import { UserService, ConfigService, TranslateService, TranslatePipe } from '@yuuvis/client-core';
16
- import { ThemeService, DEFAULT_THEME_KEY, HIGH_CONTRAST_THEME_KEY, DEFAULT_THEME } from '@yuuvis/client-framework/common';
17
- import { ShellService } from '@yuuvis/client-shell-core';
18
- import { map } from 'rxjs';
19
-
20
- class SettingsPageComponent {
21
- #themeService;
22
- #http;
23
- #appSettings;
24
- #appSettingsEffect;
25
- constructor() {
26
- this.userService = inject(UserService);
27
- this.config = inject(ConfigService);
28
- this.translate = inject(TranslateService);
29
- this.shell = inject(ShellService);
30
- this.document = inject(DOCUMENT);
31
- this.#themeService = inject(ThemeService);
32
- this.#http = inject(HttpClient);
33
- this.DEFAULT_THEME_KEY = DEFAULT_THEME_KEY;
34
- this.HIGH_CONTRAST_THEME_KEY = HIGH_CONTRAST_THEME_KEY;
35
- this.DEFAULT_THEME = DEFAULT_THEME;
36
- this.disableMode = this.#themeService.disableMode;
37
- this.customThemes = this.#themeService.customThemes;
38
- this.currentTheme = computed(() => {
39
- const ct = this.#themeService.customTheme();
40
- return ct ? ct.key : undefined;
41
- }, ...(ngDevMode ? [{ debugName: "currentTheme" }] : /* istanbul ignore next */ []));
42
- this.clientLocales = signal([], ...(ngDevMode ? [{ debugName: "clientLocales" }] : /* istanbul ignore next */ []));
43
- this.clientVersion = signal(undefined, ...(ngDevMode ? [{ debugName: "clientVersion" }] : /* istanbul ignore next */ []));
44
- this.clientAboutData = signal(undefined, ...(ngDevMode ? [{ debugName: "clientAboutData" }] : /* istanbul ignore next */ []));
45
- this.currentMode = this.#themeService.mode;
46
- this.user = toSignal(this.userService.user$);
47
- this.appSettings = signal([], ...(ngDevMode ? [{ debugName: "appSettings" }] : /* istanbul ignore next */ []));
48
- this.#appSettings = this.shell.appSettings;
49
- this.#appSettingsEffect = effect(() => {
50
- const as = this.#appSettings();
51
- this.#mapAppSettings(as);
52
- }, ...(ngDevMode ? [{ debugName: "#appSettingsEffect" }] : /* istanbul ignore next */ []));
53
- this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe(() => {
54
- this.#mapAppSettings(this.appSettings());
55
- });
56
- }
57
- #mapAppSettings(as) {
58
- this.appSettings.set(as.map((appSetting) => {
59
- const translatedLabel = this.translate.instant(appSetting.label);
60
- const label = translatedLabel && !translatedLabel.startsWith('!missing') ? translatedLabel : appSetting.label;
61
- return {
62
- ...appSetting,
63
- _label: label
64
- };
65
- }));
66
- }
67
- changeClientLocale(iso) {
68
- this.userService.changeClientLocale(iso);
69
- }
70
- changeMode({ value }) {
71
- if (value && value !== this.currentMode()) {
72
- this.#themeService.toggleTheme(value);
73
- }
74
- }
75
- toggleDarkMode() {
76
- const root = document.getElementsByTagName('body')[0];
77
- root.classList.toggle('dark');
78
- }
79
- changeCustomTheme({ value }) {
80
- this.#themeService.setCustomTheme(value);
81
- }
82
- ngOnInit() {
83
- this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');
84
- this.clientLocales.set(this.config.getClientLocales());
85
- this.getAboutData();
86
- }
87
- getAboutData() {
88
- this.#http
89
- .get('assets/about.data.json')
90
- .pipe(map((response) => ({
91
- ...response,
92
- libraries: response.libraries
93
- ? response.libraries.map((lib) => ({
94
- ...lib,
95
- ...(lib.license !== 'SEE LICENSE IN LICENSE'
96
- ? { link: `https://opensource.org/license/${lib.license}` }
97
- : {})
98
- }))
99
- : undefined
100
- })))
101
- .subscribe({
102
- next: (response) => this.clientAboutData.set(response),
103
- error: (error) => console.log({ error })
104
- });
105
- }
106
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SettingsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
107
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: SettingsPageComponent, isStandalone: true, selector: "yuv-settings", ngImport: i0, template: "<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <span class=\"subhead\">{{ 'yuv.shell.settings.client.version' | translate }}: {{ clientVersion() }}</span>\n</header>\n\n<main>\n <div class=\"content-container\">\n <!-- User Info -->\n @let user = this.user();\n @if (user) {\n <section class=\"section user\">\n <h2 class=\"section__title\">{{ user.title }}</h2>\n <div class=\"section__body user__data grid\">\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.user.email' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.email }}\n </span>\n </div>\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.tenant' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.tenant }}\n </span>\n </div>\n\n <!--<div class=\"user__data\">{{ 'yuv.shell.settings.user.name' | translate }}: {{ user.username }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.user.email' | translate }}: {{ user.email }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user.tenant }}</div>-->\n </div>\n </section>\n }\n <!-- Language Settings -->\n <section yuvOfflineDisabled class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.language' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"language\"\n [value]=\"translate.currentLang\"\n (valueChange)=\"changeClientLocale($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.language' | translate\"\n >\n @for (locale of clientLocales(); track locale.iso) {\n <mat-button-toggle value=\"{{ locale.iso }}\">{{ locale.label }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- Mode -->\n @let currentThemeMode = currentMode();\n <section class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.mode' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"mode\"\n [value]=\"currentThemeMode\"\n (change)=\"changeMode($event)\"\n [disabled]=\"disableMode()\"\n [attr.aria-label]=\"'yuv.shell.settings.mode' | translate\"\n >\n <mat-button-toggle value=\"light\">{{ 'yuv.shell.settings.mode.light' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"dark\">{{ 'yuv.shell.settings.mode.dark' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"system\">{{ 'yuv.shell.settings.mode.system' | translate }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <p></p>\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.custom.theme' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"custom-theme\"\n [value]=\"currentTheme()\"\n (change)=\"changeCustomTheme($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.custom.theme' | translate\"\n >\n <mat-button-toggle [value]=\"DEFAULT_THEME.key\" [matTooltip]=\"DEFAULT_THEME.description | translate\">\n {{ DEFAULT_THEME.label | translate }}\n </mat-button-toggle>\n @for (theme of customThemes(); track theme.key) {\n <mat-button-toggle [value]=\"theme.key\">{{ theme.label | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- app settings -->\n @for (c of appSettings(); track $index) {\n <section class=\"section\">\n <h2 class=\"section__title\">{{ c._label }}</h2>\n <div class=\"section__body\">\n <ng-container *ngComponentOutlet=\"c.component\"></ng-container>\n </div>\n </section>\n }\n\n <!-- About Info -->\n @let libraries = this.clientAboutData()?.libraries;\n @if (libraries) {\n <section class=\"section about\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.about.title' | translate }}</h2>\n <mat-expansion-panel class=\"about__panel\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{ 'yuv.shell.settings.dependency-info.title' | translate }}</mat-panel-title>\n <!-- <mat-panel-description>{{ '' | translate }}</mat-panel-description>-->\n </mat-expansion-panel-header>\n\n <ng-template matExpansionPanelContent>\n <div class=\"about__panel-content\">\n <table mat-table [dataSource]=\"libraries\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.package' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.name }}</td>\n </ng-container>\n\n <!-- Version Column -->\n <ng-container matColumnDef=\"version\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.version' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.version }}</td>\n </ng-container>\n\n <!-- License Column -->\n <ng-container matColumnDef=\"license\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.license' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (element.link) {\n <a href=\"{{ element.link }}\" target=\"_blank\">{{ element.license }}</a>\n } @else {\n {{ element.license }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"['name', 'version', 'license']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['name', 'version', 'license']\"></tr>\n </table>\n </div>\n </ng-template>\n </mat-expansion-panel>\n </section>\n }\n </div>\n</main>\n", styles: [":host{display:grid;grid-template-columns:1fr auto;grid-template-rows:auto 1fr;grid-template-areas:\"header\" \"settings\";height:100%;overflow:hidden;overflow-y:auto}:host header{grid-area:header;padding:var(--ymt-spacing-3xl)}:host header h1{margin:0}:host header .subhead{font:var(--ymt-font-subhead);color:var(--ymt-text-color-subtle)}:host main{grid-area:settings;padding:var(--ymt-spacing-m);padding-right:0;overflow-y:auto;scrollbar-gutter:stable}:host main .content-container{max-width:900px}:host main section{display:flex;flex-flow:column;padding:var(--ymt-spacing-m);margin-bottom:var(--ymt-spacing-l)}:host main .about__panel-content{overflow-x:auto}:host main .about__panel-content table{background-color:transparent}:host main .grid-row{display:grid;grid-template-columns:minmax(10ch,1fr) 11fr;grid-gap:var(--ymt-spacing-s);grid-template-areas:\"key value\";align-items:baseline}:host main .grid-col-key{font-weight:700;grid-area:key}:host main .grid-col-value{grid-area:value;word-break:break-all}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i2.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2.MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i3.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
108
- }
109
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SettingsPageComponent, decorators: [{
110
- type: Component,
111
- args: [{ selector: 'yuv-settings', standalone: true, imports: [
112
- CommonModule,
113
- TranslatePipe,
114
- MatTooltip,
115
- MatSelectModule,
116
- ReactiveFormsModule,
117
- MatButtonToggleGroup,
118
- MatButtonToggle,
119
- MatExpansionModule,
120
- MatTableModule
121
- ], template: "<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <span class=\"subhead\">{{ 'yuv.shell.settings.client.version' | translate }}: {{ clientVersion() }}</span>\n</header>\n\n<main>\n <div class=\"content-container\">\n <!-- User Info -->\n @let user = this.user();\n @if (user) {\n <section class=\"section user\">\n <h2 class=\"section__title\">{{ user.title }}</h2>\n <div class=\"section__body user__data grid\">\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.user.email' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.email }}\n </span>\n </div>\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.tenant' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.tenant }}\n </span>\n </div>\n\n <!--<div class=\"user__data\">{{ 'yuv.shell.settings.user.name' | translate }}: {{ user.username }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.user.email' | translate }}: {{ user.email }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user.tenant }}</div>-->\n </div>\n </section>\n }\n <!-- Language Settings -->\n <section yuvOfflineDisabled class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.language' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"language\"\n [value]=\"translate.currentLang\"\n (valueChange)=\"changeClientLocale($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.language' | translate\"\n >\n @for (locale of clientLocales(); track locale.iso) {\n <mat-button-toggle value=\"{{ locale.iso }}\">{{ locale.label }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- Mode -->\n @let currentThemeMode = currentMode();\n <section class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.mode' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"mode\"\n [value]=\"currentThemeMode\"\n (change)=\"changeMode($event)\"\n [disabled]=\"disableMode()\"\n [attr.aria-label]=\"'yuv.shell.settings.mode' | translate\"\n >\n <mat-button-toggle value=\"light\">{{ 'yuv.shell.settings.mode.light' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"dark\">{{ 'yuv.shell.settings.mode.dark' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"system\">{{ 'yuv.shell.settings.mode.system' | translate }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <p></p>\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.custom.theme' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"custom-theme\"\n [value]=\"currentTheme()\"\n (change)=\"changeCustomTheme($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.custom.theme' | translate\"\n >\n <mat-button-toggle [value]=\"DEFAULT_THEME.key\" [matTooltip]=\"DEFAULT_THEME.description | translate\">\n {{ DEFAULT_THEME.label | translate }}\n </mat-button-toggle>\n @for (theme of customThemes(); track theme.key) {\n <mat-button-toggle [value]=\"theme.key\">{{ theme.label | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- app settings -->\n @for (c of appSettings(); track $index) {\n <section class=\"section\">\n <h2 class=\"section__title\">{{ c._label }}</h2>\n <div class=\"section__body\">\n <ng-container *ngComponentOutlet=\"c.component\"></ng-container>\n </div>\n </section>\n }\n\n <!-- About Info -->\n @let libraries = this.clientAboutData()?.libraries;\n @if (libraries) {\n <section class=\"section about\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.about.title' | translate }}</h2>\n <mat-expansion-panel class=\"about__panel\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{ 'yuv.shell.settings.dependency-info.title' | translate }}</mat-panel-title>\n <!-- <mat-panel-description>{{ '' | translate }}</mat-panel-description>-->\n </mat-expansion-panel-header>\n\n <ng-template matExpansionPanelContent>\n <div class=\"about__panel-content\">\n <table mat-table [dataSource]=\"libraries\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.package' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.name }}</td>\n </ng-container>\n\n <!-- Version Column -->\n <ng-container matColumnDef=\"version\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.version' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.version }}</td>\n </ng-container>\n\n <!-- License Column -->\n <ng-container matColumnDef=\"license\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.license' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (element.link) {\n <a href=\"{{ element.link }}\" target=\"_blank\">{{ element.license }}</a>\n } @else {\n {{ element.license }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"['name', 'version', 'license']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['name', 'version', 'license']\"></tr>\n </table>\n </div>\n </ng-template>\n </mat-expansion-panel>\n </section>\n }\n </div>\n</main>\n", styles: [":host{display:grid;grid-template-columns:1fr auto;grid-template-rows:auto 1fr;grid-template-areas:\"header\" \"settings\";height:100%;overflow:hidden;overflow-y:auto}:host header{grid-area:header;padding:var(--ymt-spacing-3xl)}:host header h1{margin:0}:host header .subhead{font:var(--ymt-font-subhead);color:var(--ymt-text-color-subtle)}:host main{grid-area:settings;padding:var(--ymt-spacing-m);padding-right:0;overflow-y:auto;scrollbar-gutter:stable}:host main .content-container{max-width:900px}:host main section{display:flex;flex-flow:column;padding:var(--ymt-spacing-m);margin-bottom:var(--ymt-spacing-l)}:host main .about__panel-content{overflow-x:auto}:host main .about__panel-content table{background-color:transparent}:host main .grid-row{display:grid;grid-template-columns:minmax(10ch,1fr) 11fr;grid-gap:var(--ymt-spacing-s);grid-template-areas:\"key value\";align-items:baseline}:host main .grid-col-key{font-weight:700;grid-area:key}:host main .grid-col-value{grid-area:value;word-break:break-all}\n"] }]
122
- }], ctorParameters: () => [] });
123
-
124
- export { SettingsPageComponent };
125
- //# sourceMappingURL=yuuvis-client-shell-settings.component-BqBDoPC9.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yuuvis-client-shell-settings.component-BqBDoPC9.mjs","sources":["../../../../../libs/yuuvis/client-shell/src/lib/pages/settings/settings.component.ts","../../../../../libs/yuuvis/client-shell/src/lib/pages/settings/settings.component.html"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { HttpClient } from '@angular/common/http';\nimport { Component, computed, DOCUMENT, effect, inject, OnInit, Signal, signal } from '@angular/core';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { MatButtonToggle, MatButtonToggleChange, MatButtonToggleGroup } from '@angular/material/button-toggle';\nimport { MatExpansionModule } from '@angular/material/expansion';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatTableModule } from '@angular/material/table';\nimport { MatTooltip } from '@angular/material/tooltip';\nimport {\n ConfigService,\n TranslatePipe,\n TranslateService,\n UserService,\n YuvConfigLanguages,\n YuvUser\n} from '@yuuvis/client-core';\nimport {\n DEFAULT_THEME,\n DEFAULT_THEME_KEY,\n HIGH_CONTRAST_THEME_KEY,\n ThemeService\n} from '@yuuvis/client-framework/common';\nimport { ShellAppSettings, ShellService } from '@yuuvis/client-shell-core';\nimport { map } from 'rxjs';\nimport { AboutData } from './settings.model';\n\n@Component({\n selector: 'yuv-settings',\n standalone: true,\n imports: [\n CommonModule,\n TranslatePipe,\n MatTooltip,\n MatSelectModule,\n ReactiveFormsModule,\n MatButtonToggleGroup,\n MatButtonToggle,\n MatExpansionModule,\n MatTableModule\n ],\n templateUrl: './settings.component.html',\n styleUrls: ['./settings.component.scss']\n})\nexport class SettingsPageComponent implements OnInit {\n private userService = inject(UserService);\n private config = inject(ConfigService);\n public translate = inject(TranslateService);\n private shell = inject(ShellService);\n readonly document = inject(DOCUMENT);\n readonly #themeService = inject(ThemeService);\n readonly #http = inject(HttpClient);\n\n protected readonly DEFAULT_THEME_KEY = DEFAULT_THEME_KEY;\n protected readonly HIGH_CONTRAST_THEME_KEY = HIGH_CONTRAST_THEME_KEY;\n protected readonly DEFAULT_THEME = DEFAULT_THEME;\n disableMode = this.#themeService.disableMode;\n customThemes = this.#themeService.customThemes;\n currentTheme = computed(() => {\n const ct = this.#themeService.customTheme();\n return ct ? ct.key : undefined;\n });\n\n clientLocales = signal<YuvConfigLanguages[]>([]);\n clientVersion = signal<string | undefined>(undefined);\n clientAboutData = signal<AboutData | undefined>(undefined);\n currentMode = this.#themeService.mode;\n\n user: Signal<YuvUser | undefined> = toSignal(this.userService.user$);\n appSettings = signal<(ShellAppSettings & { _label: string })[]>([]);\n #appSettings = this.shell.appSettings;\n #appSettingsEffect = effect(() => {\n const as = this.#appSettings();\n this.#mapAppSettings(as);\n });\n\n constructor() {\n this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe(() => {\n this.#mapAppSettings(this.appSettings());\n });\n }\n\n #mapAppSettings(as: ShellAppSettings[]) {\n this.appSettings.set(\n as.map((appSetting) => {\n const translatedLabel = this.translate.instant(appSetting.label);\n const label = translatedLabel && !translatedLabel.startsWith('!missing') ? translatedLabel : appSetting.label;\n return {\n ...appSetting,\n _label: label\n };\n })\n );\n }\n\n changeClientLocale(iso: string) {\n this.userService.changeClientLocale(iso);\n }\n\n changeMode({ value }: MatButtonToggleChange) {\n if (value && value !== this.currentMode()) {\n this.#themeService.toggleTheme(value);\n }\n }\n\n toggleDarkMode() {\n const root = document.getElementsByTagName('body')[0];\n root.classList.toggle('dark');\n }\n\n changeCustomTheme({ value }: MatButtonToggleChange) {\n this.#themeService.setCustomTheme(value);\n }\n\n ngOnInit(): void {\n this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');\n\n this.clientLocales.set(this.config.getClientLocales());\n this.getAboutData();\n }\n\n getAboutData() {\n this.#http\n .get('assets/about.data.json')\n .pipe(\n map((response: AboutData) => ({\n ...response,\n libraries: response.libraries\n ? response.libraries.map((lib) => ({\n ...lib,\n ...(lib.license !== 'SEE LICENSE IN LICENSE'\n ? { link: `https://opensource.org/license/${lib.license}` }\n : {})\n }))\n : undefined\n }))\n )\n .subscribe({\n next: (response: AboutData) => this.clientAboutData.set(response),\n error: (error) => console.log({ error })\n });\n }\n}\n","<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <span class=\"subhead\">{{ 'yuv.shell.settings.client.version' | translate }}: {{ clientVersion() }}</span>\n</header>\n\n<main>\n <div class=\"content-container\">\n <!-- User Info -->\n @let user = this.user();\n @if (user) {\n <section class=\"section user\">\n <h2 class=\"section__title\">{{ user.title }}</h2>\n <div class=\"section__body user__data grid\">\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.user.email' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.email }}\n </span>\n </div>\n <div class=\"user__data-entry grid-row\">\n <span class=\"user__data-entry-key grid-col grid-col-key\">\n {{ 'yuv.shell.settings.tenant' | translate }}:\n </span>\n <span class=\"user__data-entry-value grid-col grid-col-value\">\n {{ user.tenant }}\n </span>\n </div>\n\n <!--<div class=\"user__data\">{{ 'yuv.shell.settings.user.name' | translate }}: {{ user.username }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.user.email' | translate }}: {{ user.email }}</div>\n <div class=\"user__data-entry\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user.tenant }}</div>-->\n </div>\n </section>\n }\n <!-- Language Settings -->\n <section yuvOfflineDisabled class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.language' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"language\"\n [value]=\"translate.currentLang\"\n (valueChange)=\"changeClientLocale($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.language' | translate\"\n >\n @for (locale of clientLocales(); track locale.iso) {\n <mat-button-toggle value=\"{{ locale.iso }}\">{{ locale.label }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- Mode -->\n @let currentThemeMode = currentMode();\n <section class=\"section\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.mode' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"mode\"\n [value]=\"currentThemeMode\"\n (change)=\"changeMode($event)\"\n [disabled]=\"disableMode()\"\n [attr.aria-label]=\"'yuv.shell.settings.mode' | translate\"\n >\n <mat-button-toggle value=\"light\">{{ 'yuv.shell.settings.mode.light' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"dark\">{{ 'yuv.shell.settings.mode.dark' | translate }}</mat-button-toggle>\n <mat-button-toggle value=\"system\">{{ 'yuv.shell.settings.mode.system' | translate }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n\n <p></p>\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.custom.theme' | translate }}</h2>\n <div class=\"section__body\">\n <mat-button-toggle-group\n name=\"custom-theme\"\n [value]=\"currentTheme()\"\n (change)=\"changeCustomTheme($event)\"\n [attr.aria-label]=\"'yuv.shell.settings.custom.theme' | translate\"\n >\n <mat-button-toggle [value]=\"DEFAULT_THEME.key\" [matTooltip]=\"DEFAULT_THEME.description | translate\">\n {{ DEFAULT_THEME.label | translate }}\n </mat-button-toggle>\n @for (theme of customThemes(); track theme.key) {\n <mat-button-toggle [value]=\"theme.key\">{{ theme.label | translate }}</mat-button-toggle>\n }\n </mat-button-toggle-group>\n </div>\n </section>\n\n <!-- app settings -->\n @for (c of appSettings(); track $index) {\n <section class=\"section\">\n <h2 class=\"section__title\">{{ c._label }}</h2>\n <div class=\"section__body\">\n <ng-container *ngComponentOutlet=\"c.component\"></ng-container>\n </div>\n </section>\n }\n\n <!-- About Info -->\n @let libraries = this.clientAboutData()?.libraries;\n @if (libraries) {\n <section class=\"section about\">\n <h2 class=\"section__title\">{{ 'yuv.shell.settings.about.title' | translate }}</h2>\n <mat-expansion-panel class=\"about__panel\">\n <mat-expansion-panel-header>\n <mat-panel-title>{{ 'yuv.shell.settings.dependency-info.title' | translate }}</mat-panel-title>\n <!-- <mat-panel-description>{{ '' | translate }}</mat-panel-description>-->\n </mat-expansion-panel-header>\n\n <ng-template matExpansionPanelContent>\n <div class=\"about__panel-content\">\n <table mat-table [dataSource]=\"libraries\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.package' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.name }}</td>\n </ng-container>\n\n <!-- Version Column -->\n <ng-container matColumnDef=\"version\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.version' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">{{ element.version }}</td>\n </ng-container>\n\n <!-- License Column -->\n <ng-container matColumnDef=\"license\">\n <th mat-header-cell *matHeaderCellDef>\n {{ 'yuv.shell.settings.dependency-info.license' | translate }}\n </th>\n <td mat-cell *matCellDef=\"let element\">\n @if (element.link) {\n <a href=\"{{ element.link }}\" target=\"_blank\">{{ element.license }}</a>\n } @else {\n {{ element.license }}\n }\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"['name', 'version', 'license']\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: ['name', 'version', 'license']\"></tr>\n </table>\n </div>\n </ng-template>\n </mat-expansion-panel>\n </section>\n }\n </div>\n</main>\n"],"names":[],"mappings":"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"}