@yuuvis/client-shell 2.1.3 → 2.1.5

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,115 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, Component } from '@angular/core';
3
+ import { toSignal } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@yuuvis/client-core';
5
+ import { UserService, ConfigService, TranslateService, TranslateModule } from '@yuuvis/client-core';
6
+ import { DOCUMENT, CommonModule } from '@angular/common';
7
+ import { HttpClient } from '@angular/common/http';
8
+ import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
9
+ import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
10
+ import * as i2 from '@angular/material/expansion';
11
+ import { MatExpansionModule } from '@angular/material/expansion';
12
+ import { MatSelectModule } from '@angular/material/select';
13
+ import * as i3 from '@angular/material/table';
14
+ import { MatTableModule } from '@angular/material/table';
15
+ import { ShellService } from '@yuuvis/client-shell-core';
16
+ import { map } from 'rxjs';
17
+ import { LayoutSettingsService } from '@yuuvis/client-framework/common';
18
+
19
+ class SettingsPageComponent {
20
+ constructor() {
21
+ this.userService = inject(UserService);
22
+ this.config = inject(ConfigService);
23
+ this.translate = inject(TranslateService);
24
+ this.shell = inject(ShellService);
25
+ this.document = inject(DOCUMENT);
26
+ this.#layoutSettingsService = inject(LayoutSettingsService);
27
+ this.#http = inject(HttpClient);
28
+ this.#fb = inject(FormBuilder);
29
+ this.clientLocales = signal([]);
30
+ this.clientVersion = signal(undefined);
31
+ this.clientAboutData = signal(undefined);
32
+ this.currentMode = this.#layoutSettingsService.mode;
33
+ this.user = toSignal(this.userService.user$);
34
+ this.appSettingForms$ = this.shell.appSettings$.pipe(map((settings) => settings.map((e) => {
35
+ const x = {};
36
+ const fcn = e.properties.map((p) => ({
37
+ label: this.translate.instant(p.label) || p.label,
38
+ name: p.name,
39
+ type: p.type
40
+ }));
41
+ e.properties.forEach((p) => {
42
+ x[p.name] = [p.value];
43
+ });
44
+ return {
45
+ appID: e.appID,
46
+ label: e.label,
47
+ formControls: fcn,
48
+ form: this.#fb.group(x)
49
+ };
50
+ })));
51
+ }
52
+ #layoutSettingsService;
53
+ #http;
54
+ #fb;
55
+ saveAppSettings(appID, form) {
56
+ this.userService
57
+ .saveUserSettings({
58
+ clientAppSettings: {
59
+ [appID]: form.value
60
+ }
61
+ })
62
+ .subscribe({
63
+ next: () => {
64
+ form.markAsPristine();
65
+ },
66
+ error: (err) => {
67
+ console.error('Error saving app settings', err);
68
+ }
69
+ });
70
+ }
71
+ changeClientLocale(iso) {
72
+ this.userService.changeClientLocale(iso);
73
+ }
74
+ changeMode(mode) {
75
+ if (mode && mode !== this.currentMode) {
76
+ this.#layoutSettingsService.setMode(mode);
77
+ this.#layoutSettingsService.applyLayoutMode(mode);
78
+ }
79
+ }
80
+ toggleDarkMode() {
81
+ const root = document.getElementsByTagName('body')[0];
82
+ root.classList.toggle('dark');
83
+ }
84
+ ngOnInit() {
85
+ this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');
86
+ this.clientLocales.set(this.config.getClientLocales());
87
+ this.getAboutData();
88
+ }
89
+ getAboutData() {
90
+ this.#http
91
+ .get('assets/about.data.json')
92
+ .pipe(map((response) => ({
93
+ ...response,
94
+ libraries: response.libraries
95
+ ? response.libraries.map((lib) => ({
96
+ ...lib,
97
+ ...(lib.license !== 'SEE LICENSE IN LICENSE' ? { link: `https://opensource.org/license/${lib.license}` } : {})
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: "19.2.12", ngImport: i0, type: SettingsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
107
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.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\"> {{ 'yuv.shell.settings.user.email' | translate }}: </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\"> {{ 'yuv.shell.settings.tenant' | translate }}: </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 <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]=\"currentMode\"\n (valueChange)=\"changeMode($event)\"\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 </section>\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\" class=\"mat-elevation-z8\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>{{ 'yuv.shell.settings.dependency-info.package' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.version' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.license' | translate }}</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 <!-- app settings -->\n <!-- TODO: activate one feature is refined -->\n <!-- @for (c of appSettingForms$ | async; track $index) {\n <section>\n {{ c.label }}\n <form [formGroup]=\"c.form\" (ngSubmit)=\"saveAppSettings(c.appID, c.form)\">\n @for (n of c.formControls; track $index) {\n <label\n >{{ n.label }}\n\n @switch (n.type) {\n @case ('string') {\n <input type=\"text\" [formControlName]=\"n.name\" />\n }\n @case ('number') {\n <input type=\"number\" [formControlName]=\"n.name\" />\n }\n }\n </label>\n }\n <button [ngClass]=\"{ hideen: c.form.untouched }\" [disabled]=\"c.form.invalid\">Save</button>\n </form>\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 .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: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { 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"] }] }); }
108
+ }
109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.12", ngImport: i0, type: SettingsPageComponent, decorators: [{
110
+ type: Component,
111
+ args: [{ selector: 'yuv-settings', standalone: true, imports: [CommonModule, TranslateModule, MatSelectModule, ReactiveFormsModule, MatButtonToggleGroup, MatButtonToggle, MatExpansionModule, MatTableModule], 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\"> {{ 'yuv.shell.settings.user.email' | translate }}: </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\"> {{ 'yuv.shell.settings.tenant' | translate }}: </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 <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]=\"currentMode\"\n (valueChange)=\"changeMode($event)\"\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 </section>\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\" class=\"mat-elevation-z8\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>{{ 'yuv.shell.settings.dependency-info.package' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.version' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.license' | translate }}</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 <!-- app settings -->\n <!-- TODO: activate one feature is refined -->\n <!-- @for (c of appSettingForms$ | async; track $index) {\n <section>\n {{ c.label }}\n <form [formGroup]=\"c.form\" (ngSubmit)=\"saveAppSettings(c.appID, c.form)\">\n @for (n of c.formControls; track $index) {\n <label\n >{{ n.label }}\n\n @switch (n.type) {\n @case ('string') {\n <input type=\"text\" [formControlName]=\"n.name\" />\n }\n @case ('number') {\n <input type=\"number\" [formControlName]=\"n.name\" />\n }\n }\n </label>\n }\n <button [ngClass]=\"{ hideen: c.form.untouched }\" [disabled]=\"c.form.invalid\">Save</button>\n </form>\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 .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"] }]
112
+ }] });
113
+
114
+ export { SettingsPageComponent };
115
+ //# sourceMappingURL=yuuvis-client-shell-settings.component-CRIAEk3A.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yuuvis-client-shell-settings.component-CRIAEk3A.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 { Component, inject, OnInit, Signal, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { AppCacheService, ConfigService, TranslateModule, TranslateService, UserService, YuvConfigLanguages, YuvUser } from '@yuuvis/client-core';\n\nimport { CommonModule, DOCUMENT } from '@angular/common';\nimport { HttpClient } from '@angular/common/http';\nimport { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { MatButtonToggle, 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 { ShellAppSettingProperty, ShellAppSettings, ShellService } from '@yuuvis/client-shell-core';\nimport { map, Observable } from 'rxjs';\nimport { AboutData } from './settings.model';\nimport { LayoutMode, LayoutSettingsService } from '@yuuvis/client-framework/common';\n\n@Component({\n selector: 'yuv-settings',\n standalone: true,\n imports: [CommonModule, TranslateModule, MatSelectModule, ReactiveFormsModule, MatButtonToggleGroup, MatButtonToggle, MatExpansionModule, MatTableModule],\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 #layoutSettingsService = inject(LayoutSettingsService);\n #http = inject(HttpClient);\n\n #fb = inject(FormBuilder);\n\n clientLocales = signal<YuvConfigLanguages[]>([]);\n clientVersion = signal<string | undefined>(undefined);\n clientAboutData = signal<AboutData | undefined>(undefined);\n currentMode = this.#layoutSettingsService.mode;\n\n user: Signal<YuvUser | undefined> = toSignal(this.userService.user$);\n appSettingForms$: Observable<\n {\n appID: string;\n label: string;\n formControls: ShellAppSettingProperty[];\n form: FormGroup;\n }[]\n > = this.shell.appSettings$.pipe(\n map((settings: ShellAppSettings[]) =>\n settings.map((e) => {\n const x: any = {};\n const fcn: ShellAppSettingProperty[] = e.properties.map((p) => ({\n label: this.translate.instant(p.label) || p.label,\n name: p.name,\n type: p.type\n }));\n e.properties.forEach((p) => {\n x[p.name] = [p.value];\n });\n return {\n appID: e.appID,\n label: e.label,\n formControls: fcn,\n form: this.#fb.group(x)\n };\n })\n )\n );\n\n saveAppSettings(appID: string, form: FormGroup) {\n this.userService\n .saveUserSettings({\n clientAppSettings: {\n [appID]: form.value\n }\n })\n .subscribe({\n next: () => {\n form.markAsPristine();\n },\n error: (err) => {\n console.error('Error saving app settings', err);\n }\n });\n }\n\n changeClientLocale(iso: string) {\n this.userService.changeClientLocale(iso);\n }\n\n changeMode(mode: LayoutMode) {\n if (mode && mode !== this.currentMode) {\n this.#layoutSettingsService.setMode(mode);\n this.#layoutSettingsService.applyLayoutMode(mode);\n }\n }\n\n toggleDarkMode() {\n const root = document.getElementsByTagName('body')[0];\n root.classList.toggle('dark');\n }\n\n ngOnInit(): void {\n this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');\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' ? { link: `https://opensource.org/license/${lib.license}` } : {})\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\"> {{ 'yuv.shell.settings.user.email' | translate }}: </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\"> {{ 'yuv.shell.settings.tenant' | translate }}: </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 <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]=\"currentMode\"\n (valueChange)=\"changeMode($event)\"\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 </section>\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\" class=\"mat-elevation-z8\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>{{ 'yuv.shell.settings.dependency-info.package' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.version' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.license' | translate }}</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 <!-- app settings -->\n <!-- TODO: activate one feature is refined -->\n <!-- @for (c of appSettingForms$ | async; track $index) {\n <section>\n {{ c.label }}\n <form [formGroup]=\"c.form\" (ngSubmit)=\"saveAppSettings(c.appID, c.form)\">\n @for (n of c.formControls; track $index) {\n <label\n >{{ n.label }}\n\n @switch (n.type) {\n @case ('string') {\n <input type=\"text\" [formControlName]=\"n.name\" />\n }\n @case ('number') {\n <input type=\"number\" [formControlName]=\"n.name\" />\n }\n }\n </label>\n }\n <button [ngClass]=\"{ hideen: c.form.untouched }\" [disabled]=\"c.form.invalid\">Save</button>\n </form>\n </section>\n } -->\n </div>\n</main>\n"],"names":[],"mappings":"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"}
@@ -335,7 +335,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.12", ngImpo
335
335
  const clientShellRoutes = [
336
336
  { path: 'dashboard', loadComponent: () => import('./yuuvis-client-shell-dashboard.component-akNayAfe.mjs').then((comp) => comp.DashboardPageComponent) },
337
337
  { path: 'notifications', component: NotificationsPageComponent, outlet: 'aside' },
338
- { path: 'settings', loadComponent: () => import('./yuuvis-client-shell-settings.component-ANbgn9LN.mjs').then((comp) => comp.SettingsPageComponent) },
338
+ { path: 'settings', loadComponent: () => import('./yuuvis-client-shell-settings.component-CRIAEk3A.mjs').then((comp) => comp.SettingsPageComponent) },
339
339
  // default route
340
340
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
341
341
  // redirecting route
@@ -653,5 +653,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.12", ngImpo
653
653
  * Generated bundle index. Do not edit.
654
654
  */
655
655
 
656
- export { ClientShellComponent, InertDirective, ManageFlavorsAction, ShellLogoComponent, ShellWidgetsService, YuvAppHeaderSlotDirective, YuvClientShellModule, clientShellRoutes };
656
+ export { ClientShellComponent, ClientShellService, InertDirective, ManageFlavorsAction, ShellLogoComponent, ShellWidgetsService, YuvAppHeaderSlotDirective, YuvClientShellModule, clientShellRoutes };
657
657
  //# sourceMappingURL=yuuvis-client-shell.mjs.map
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './lib/actions/manage-flavors/manage-flavors.action';
2
2
  export * from './lib/client-shell.component';
3
+ export * from './lib/services/client-shell/client-shell.service';
3
4
  export * from './lib/client-shell.module';
4
5
  export * from './lib/components/app-header/app-header-slot.directive';
5
6
  export * from './lib/components/shell-logo/shell-logo.component';
@@ -23,7 +23,10 @@
23
23
  "yuv.shell.settings.dependency-info.title": "Lizenzhinweise",
24
24
  "yuv.shell.settings.dependency-info.version": "Version",
25
25
  "yuv.shell.settings.language": "Sprache",
26
- "yuv.shell.settings.mode": "",
26
+ "yuv.shell.settings.mode": "Modus",
27
+ "yuv.shell.settings.mode.dark": "Dunkel",
28
+ "yuv.shell.settings.mode.light": "Hell",
29
+ "yuv.shell.settings.mode.system": "System",
27
30
  "yuv.shell.settings.tenant": "Mandant",
28
31
  "yuv.shell.settings.title": "Einstellungen",
29
32
  "yuv.shell.settings.user.email": "E-Mail"
@@ -23,7 +23,10 @@
23
23
  "yuv.shell.settings.dependency-info.title": "Licensing notes",
24
24
  "yuv.shell.settings.dependency-info.version": "Version",
25
25
  "yuv.shell.settings.language": "Language",
26
- "yuv.shell.settings.mode": "",
26
+ "yuv.shell.settings.mode": "Mode",
27
+ "yuv.shell.settings.mode.dark": "Dark",
28
+ "yuv.shell.settings.mode.light": "Light",
29
+ "yuv.shell.settings.mode.system": "System",
27
30
  "yuv.shell.settings.tenant": "Tenant",
28
31
  "yuv.shell.settings.title": "Settings",
29
32
  "yuv.shell.settings.user.email": "E-mail"
@@ -4,6 +4,7 @@ import { FormGroup } from '@angular/forms';
4
4
  import { ShellAppSettingProperty } from '@yuuvis/client-shell-core';
5
5
  import { Observable } from 'rxjs';
6
6
  import { AboutData } from './settings.model';
7
+ import { LayoutMode } from '@yuuvis/client-framework/common';
7
8
  import * as i0 from "@angular/core";
8
9
  export declare class SettingsPageComponent implements OnInit {
9
10
  #private;
@@ -15,6 +16,7 @@ export declare class SettingsPageComponent implements OnInit {
15
16
  clientLocales: import("@angular/core").WritableSignal<YuvConfigLanguages[]>;
16
17
  clientVersion: import("@angular/core").WritableSignal<string | undefined>;
17
18
  clientAboutData: import("@angular/core").WritableSignal<AboutData | undefined>;
19
+ currentMode: LayoutMode;
18
20
  user: Signal<YuvUser | undefined>;
19
21
  appSettingForms$: Observable<{
20
22
  appID: string;
@@ -24,6 +26,7 @@ export declare class SettingsPageComponent implements OnInit {
24
26
  }[]>;
25
27
  saveAppSettings(appID: string, form: FormGroup): void;
26
28
  changeClientLocale(iso: string): void;
29
+ changeMode(mode: LayoutMode): void;
27
30
  toggleDarkMode(): void;
28
31
  ngOnInit(): void;
29
32
  getAboutData(): void;
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@yuuvis/client-shell",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
4
4
  "author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
7
7
  "@angular/common": "^19.2.1",
8
8
  "@angular/core": "^19.2.1",
9
9
  "@angular/service-worker": "^19.2.1",
10
- "@yuuvis/client-core": "^2.1.3",
11
- "@yuuvis/client-shell-core": "^2.1.3",
12
- "@yuuvis/client-framework": "^2.1.3"
10
+ "@yuuvis/client-core": "^2.1.5",
11
+ "@yuuvis/client-shell-core": "^2.1.5",
12
+ "@yuuvis/client-framework": "^2.1.5"
13
13
  },
14
14
  "dependencies": {
15
15
  "tslib": "^2.3.0"
@@ -1,107 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { inject, signal, Component } from '@angular/core';
3
- import { toSignal } from '@angular/core/rxjs-interop';
4
- import * as i1 from '@yuuvis/client-core';
5
- import { UserService, ConfigService, TranslateService, AppCacheService, TranslateModule } from '@yuuvis/client-core';
6
- import { DOCUMENT, CommonModule } from '@angular/common';
7
- import { HttpClient } from '@angular/common/http';
8
- import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
9
- import { MatButtonToggleGroup, MatButtonToggle } from '@angular/material/button-toggle';
10
- import * as i2 from '@angular/material/expansion';
11
- import { MatExpansionModule } from '@angular/material/expansion';
12
- import { MatSelectModule } from '@angular/material/select';
13
- import * as i3 from '@angular/material/table';
14
- import { MatTableModule } from '@angular/material/table';
15
- import { ShellService } from '@yuuvis/client-shell-core';
16
- import { map } from 'rxjs';
17
-
18
- class SettingsPageComponent {
19
- constructor() {
20
- this.userService = inject(UserService);
21
- this.config = inject(ConfigService);
22
- this.translate = inject(TranslateService);
23
- this.shell = inject(ShellService);
24
- this.document = inject(DOCUMENT);
25
- this.#appCache = inject(AppCacheService);
26
- this.#http = inject(HttpClient);
27
- this.#fb = inject(FormBuilder);
28
- this.clientLocales = signal([]);
29
- this.clientVersion = signal(undefined);
30
- this.clientAboutData = signal(undefined);
31
- this.user = toSignal(this.userService.user$);
32
- this.appSettingForms$ = this.shell.appSettings$.pipe(map((settings) => settings.map((e) => {
33
- const x = {};
34
- const fcn = e.properties.map((p) => ({
35
- label: this.translate.instant(p.label) || p.label,
36
- name: p.name,
37
- type: p.type
38
- }));
39
- e.properties.forEach((p) => {
40
- x[p.name] = [p.value];
41
- });
42
- return {
43
- appID: e.appID,
44
- label: e.label,
45
- formControls: fcn,
46
- form: this.#fb.group(x)
47
- };
48
- })));
49
- }
50
- #appCache;
51
- #http;
52
- #fb;
53
- saveAppSettings(appID, form) {
54
- this.userService
55
- .saveUserSettings({
56
- clientAppSettings: {
57
- [appID]: form.value
58
- }
59
- })
60
- .subscribe({
61
- next: () => {
62
- form.markAsPristine();
63
- },
64
- error: (err) => {
65
- console.error('Error saving app settings', err);
66
- }
67
- });
68
- }
69
- changeClientLocale(iso) {
70
- this.userService.changeClientLocale(iso);
71
- }
72
- toggleDarkMode() {
73
- const root = document.getElementsByTagName('body')[0];
74
- root.classList.toggle('dark');
75
- }
76
- ngOnInit() {
77
- this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');
78
- this.clientLocales.set(this.config.getClientLocales());
79
- this.getAboutData();
80
- }
81
- getAboutData() {
82
- this.#http
83
- .get('assets/about.data.json')
84
- .pipe(map((response) => ({
85
- ...response,
86
- libraries: response.libraries
87
- ? response.libraries.map((lib) => ({
88
- ...lib,
89
- ...(lib.license !== 'SEE LICENSE IN LICENSE' ? { link: `https://opensource.org/license/${lib.license}` } : {})
90
- }))
91
- : undefined
92
- })))
93
- .subscribe({
94
- next: (response) => this.clientAboutData.set(response),
95
- error: (error) => console.log({ error })
96
- });
97
- }
98
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.12", ngImport: i0, type: SettingsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
99
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.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\"> {{ 'yuv.shell.settings.user.email' | translate }}: </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\"> {{ 'yuv.shell.settings.tenant' | translate }}: </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 <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]=\"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\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\" class=\"mat-elevation-z8\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>{{ 'yuv.shell.settings.dependency-info.package' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.version' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.license' | translate }}</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 <!-- app settings -->\n <!-- TODO: activate one feature is refined -->\n <!-- @for (c of appSettingForms$ | async; track $index) {\n <section>\n {{ c.label }}\n <form [formGroup]=\"c.form\" (ngSubmit)=\"saveAppSettings(c.appID, c.form)\">\n @for (n of c.formControls; track $index) {\n <label\n >{{ n.label }}\n\n @switch (n.type) {\n @case ('string') {\n <input type=\"text\" [formControlName]=\"n.name\" />\n }\n @case ('number') {\n <input type=\"number\" [formControlName]=\"n.name\" />\n }\n }\n </label>\n }\n <button [ngClass]=\"{ hideen: c.form.untouched }\" [disabled]=\"c.form.invalid\">Save</button>\n </form>\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 .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: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { 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"] }] }); }
100
- }
101
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.12", ngImport: i0, type: SettingsPageComponent, decorators: [{
102
- type: Component,
103
- args: [{ selector: 'yuv-settings', standalone: true, imports: [CommonModule, TranslateModule, MatSelectModule, ReactiveFormsModule, MatButtonToggleGroup, MatButtonToggle, MatExpansionModule, MatTableModule], 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\"> {{ 'yuv.shell.settings.user.email' | translate }}: </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\"> {{ 'yuv.shell.settings.tenant' | translate }}: </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 <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]=\"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\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\" class=\"mat-elevation-z8\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>{{ 'yuv.shell.settings.dependency-info.package' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.version' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.license' | translate }}</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 <!-- app settings -->\n <!-- TODO: activate one feature is refined -->\n <!-- @for (c of appSettingForms$ | async; track $index) {\n <section>\n {{ c.label }}\n <form [formGroup]=\"c.form\" (ngSubmit)=\"saveAppSettings(c.appID, c.form)\">\n @for (n of c.formControls; track $index) {\n <label\n >{{ n.label }}\n\n @switch (n.type) {\n @case ('string') {\n <input type=\"text\" [formControlName]=\"n.name\" />\n }\n @case ('number') {\n <input type=\"number\" [formControlName]=\"n.name\" />\n }\n }\n </label>\n }\n <button [ngClass]=\"{ hideen: c.form.untouched }\" [disabled]=\"c.form.invalid\">Save</button>\n </form>\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 .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"] }]
104
- }] });
105
-
106
- export { SettingsPageComponent };
107
- //# sourceMappingURL=yuuvis-client-shell-settings.component-ANbgn9LN.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yuuvis-client-shell-settings.component-ANbgn9LN.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 { Component, inject, OnInit, Signal, signal } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { AppCacheService, ConfigService, TranslateModule, TranslateService, UserService, YuvConfigLanguages, YuvUser } from '@yuuvis/client-core';\n\nimport { CommonModule, DOCUMENT } from '@angular/common';\nimport { HttpClient } from '@angular/common/http';\nimport { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';\nimport { MatButtonToggle, 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 { ShellAppSettingProperty, ShellAppSettings, ShellService } from '@yuuvis/client-shell-core';\nimport { map, Observable } from 'rxjs';\nimport { AboutData } from './settings.model';\n\n@Component({\n selector: 'yuv-settings',\n standalone: true,\n imports: [CommonModule, TranslateModule, MatSelectModule, ReactiveFormsModule, MatButtonToggleGroup, MatButtonToggle, MatExpansionModule, MatTableModule],\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 #appCache = inject(AppCacheService);\n #http = inject(HttpClient);\n\n #fb = inject(FormBuilder);\n\n clientLocales = signal<YuvConfigLanguages[]>([]);\n clientVersion = signal<string | undefined>(undefined);\n clientAboutData = signal<AboutData | undefined>(undefined);\n\n user: Signal<YuvUser | undefined> = toSignal(this.userService.user$);\n appSettingForms$: Observable<\n {\n appID: string;\n label: string;\n formControls: ShellAppSettingProperty[];\n form: FormGroup;\n }[]\n > = this.shell.appSettings$.pipe(\n map((settings: ShellAppSettings[]) =>\n settings.map((e) => {\n const x: any = {};\n const fcn: ShellAppSettingProperty[] = e.properties.map((p) => ({\n label: this.translate.instant(p.label) || p.label,\n name: p.name,\n type: p.type\n }));\n e.properties.forEach((p) => {\n x[p.name] = [p.value];\n });\n return {\n appID: e.appID,\n label: e.label,\n formControls: fcn,\n form: this.#fb.group(x)\n };\n })\n )\n );\n\n saveAppSettings(appID: string, form: FormGroup) {\n this.userService\n .saveUserSettings({\n clientAppSettings: {\n [appID]: form.value\n }\n })\n .subscribe({\n next: () => {\n form.markAsPristine();\n },\n error: (err) => {\n console.error('Error saving app settings', err);\n }\n });\n }\n\n changeClientLocale(iso: string) {\n this.userService.changeClientLocale(iso);\n }\n\n toggleDarkMode() {\n const root = document.getElementsByTagName('body')[0];\n root.classList.toggle('dark');\n }\n\n ngOnInit(): void {\n this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');\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' ? { link: `https://opensource.org/license/${lib.license}` } : {})\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\"> {{ 'yuv.shell.settings.user.email' | translate }}: </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\"> {{ 'yuv.shell.settings.tenant' | translate }}: </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 <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]=\"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\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\" class=\"mat-elevation-z8\">\n <!-- Name Column -->\n <ng-container matColumnDef=\"name\">\n <th mat-header-cell *matHeaderCellDef>{{ 'yuv.shell.settings.dependency-info.package' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.version' | translate }}</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>{{ 'yuv.shell.settings.dependency-info.license' | translate }}</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 <!-- app settings -->\n <!-- TODO: activate one feature is refined -->\n <!-- @for (c of appSettingForms$ | async; track $index) {\n <section>\n {{ c.label }}\n <form [formGroup]=\"c.form\" (ngSubmit)=\"saveAppSettings(c.appID, c.form)\">\n @for (n of c.formControls; track $index) {\n <label\n >{{ n.label }}\n\n @switch (n.type) {\n @case ('string') {\n <input type=\"text\" [formControlName]=\"n.name\" />\n }\n @case ('number') {\n <input type=\"number\" [formControlName]=\"n.name\" />\n }\n }\n </label>\n }\n <button [ngClass]=\"{ hideen: c.form.untouched }\" [disabled]=\"c.form.invalid\">Save</button>\n </form>\n </section>\n } -->\n </div>\n</main>\n"],"names":[],"mappings":"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"}