@yuuvis/client-shell 0.6.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.
- package/README.md +94 -0
- package/esm2022/index.mjs +6 -0
- package/esm2022/lib/actions/manage-flavors/manage-flavors.action.mjs +39 -0
- package/esm2022/lib/actions/manage-flavors/manage-flavors.component.mjs +69 -0
- package/esm2022/lib/client-shell.component.mjs +191 -0
- package/esm2022/lib/components/app-logo/app-logo.component.mjs +18 -0
- package/esm2022/lib/directives/inert.directive.mjs +26 -0
- package/esm2022/lib/lib.routes.mjs +15 -0
- package/esm2022/lib/pages/dashboard/dashboard.component.mjs +11 -0
- package/esm2022/lib/pages/notifications/notifications.component.mjs +82 -0
- package/esm2022/lib/pages/settings/settings.component.mjs +71 -0
- package/esm2022/lib/pages/web-share-target/web-share-target.component.mjs +18 -0
- package/esm2022/widget-dashboard/index.mjs +3 -0
- package/esm2022/widget-dashboard/lib/widget-dashboard.component.mjs +46 -0
- package/esm2022/widget-dashboard/lib/widget-dashboard.config.mjs +3 -0
- package/esm2022/widget-dashboard/lib/widget-dashboard.module.mjs +49 -0
- package/esm2022/widget-dashboard/yuuvis-client-shell-widget-dashboard.mjs +5 -0
- package/esm2022/yuuvis-client-shell.mjs +5 -0
- package/fesm2022/yuuvis-client-shell-widget-dashboard.mjs +98 -0
- package/fesm2022/yuuvis-client-shell-widget-dashboard.mjs.map +1 -0
- package/fesm2022/yuuvis-client-shell.mjs +496 -0
- package/fesm2022/yuuvis-client-shell.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/actions/manage-flavors/manage-flavors.action.d.ts +17 -0
- package/lib/actions/manage-flavors/manage-flavors.component.d.ts +17 -0
- package/lib/assets/i18n/de.json +30 -0
- package/lib/assets/i18n/en.json +30 -0
- package/lib/client-shell.component.d.ts +42 -0
- package/lib/components/app-logo/app-logo.component.d.ts +7 -0
- package/lib/directives/inert.directive.d.ts +8 -0
- package/lib/lib.routes.d.ts +2 -0
- package/lib/pages/dashboard/dashboard.component.d.ts +5 -0
- package/lib/pages/notifications/notifications.component.d.ts +29 -0
- package/lib/pages/settings/settings.component.d.ts +28 -0
- package/lib/pages/web-share-target/web-share-target.component.d.ts +6 -0
- package/package.json +40 -0
- package/widget-dashboard/README.md +19 -0
- package/widget-dashboard/index.d.ts +2 -0
- package/widget-dashboard/lib/widget-dashboard.component.d.ts +16 -0
- package/widget-dashboard/lib/widget-dashboard.config.d.ts +7 -0
- package/widget-dashboard/lib/widget-dashboard.module.d.ts +13 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, input, effect, Directive, Component, signal, HostListener } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/common';
|
|
4
|
+
import { DOCUMENT, CommonModule, NgIf, AsyncPipe } from '@angular/common';
|
|
5
|
+
import { toSignal } from '@angular/core/rxjs-interop';
|
|
6
|
+
import * as i2$2 from '@angular/router';
|
|
7
|
+
import { Router, NavigationEnd, RouterModule } from '@angular/router';
|
|
8
|
+
import { SwPush } from '@angular/service-worker';
|
|
9
|
+
import * as i2 from '@yuuvis/client-core';
|
|
10
|
+
import { UserService, ConfigService, TranslateService, TranslateModule, Utils, LocaleDatePipe, AuthService, DeviceService, UserRoles, DmsService } from '@yuuvis/client-core';
|
|
11
|
+
import { MetadataDefaultTemplatesComponent } from '@yuuvis/client-framework/metadata-form';
|
|
12
|
+
import { ShellService, ShellNotificationsService, CommandPaletteService } from '@yuuvis/client-shell-core';
|
|
13
|
+
import * as i2$1 from '@yuuvis/components/icon';
|
|
14
|
+
import { ICONS, YvcIconModule } from '@yuuvis/components/icon';
|
|
15
|
+
import { map, of, tap as tap$1 } from 'rxjs';
|
|
16
|
+
import { tap, map as map$1, filter, catchError, switchMap } from 'rxjs/operators';
|
|
17
|
+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
18
|
+
import { CdkTrapFocus } from '@angular/cdk/a11y';
|
|
19
|
+
import { LightDismissDirective, BusyOverlayDirective } from '@yuuvis/client-framework/common';
|
|
20
|
+
import { YUV_ICONS } from '@yuuvis/client-framework/icons';
|
|
21
|
+
import { ListComponent, ListItemDirective } from '@yuuvis/client-framework/list';
|
|
22
|
+
import { AbstractContextAction, ACTION_ICON, SelectionRange } from '@yuuvis/client-framework/actions';
|
|
23
|
+
import { YvcOverlayRef, YvcOverlayService } from '@yuuvis/components/overlay';
|
|
24
|
+
import { FlavorChipComponent } from '@yuuvis/client-framework/object-flavor';
|
|
25
|
+
|
|
26
|
+
class InertDirective {
|
|
27
|
+
constructor() {
|
|
28
|
+
this.elRef = inject(ElementRef);
|
|
29
|
+
this.inert = input(false);
|
|
30
|
+
effect(() => {
|
|
31
|
+
const el = this.elRef.nativeElement;
|
|
32
|
+
if (this.inert())
|
|
33
|
+
el.setAttribute('inert', 'true');
|
|
34
|
+
else
|
|
35
|
+
el.removeAttribute('inert');
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InertDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
39
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.13", type: InertDirective, isStandalone: true, selector: "[inert]", inputs: { inert: { classPropertyName: "inert", publicName: "inert", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 }); }
|
|
40
|
+
}
|
|
41
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InertDirective, decorators: [{
|
|
42
|
+
type: Directive,
|
|
43
|
+
args: [{
|
|
44
|
+
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
45
|
+
selector: '[inert]',
|
|
46
|
+
standalone: true
|
|
47
|
+
}]
|
|
48
|
+
}], ctorParameters: () => [] });
|
|
49
|
+
|
|
50
|
+
class DashboardPageComponent {
|
|
51
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DashboardPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
52
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DashboardPageComponent, selector: "yuv-dashboard", ngImport: i0, template: "yuuvis Momentum\n", styles: [":host{display:grid;align-items:center;justify-content:center;height:100%;overflow:hidden;color:var(--text-color-hint);font-size:var(--font-display)}\n"] }); }
|
|
53
|
+
}
|
|
54
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DashboardPageComponent, decorators: [{
|
|
55
|
+
type: Component,
|
|
56
|
+
args: [{ selector: 'yuv-dashboard', template: "yuuvis Momentum\n", styles: [":host{display:grid;align-items:center;justify-content:center;height:100%;overflow:hidden;color:var(--text-color-hint);font-size:var(--font-display)}\n"] }]
|
|
57
|
+
}] });
|
|
58
|
+
|
|
59
|
+
class SettingsPageComponent {
|
|
60
|
+
constructor() {
|
|
61
|
+
this.userService = inject(UserService);
|
|
62
|
+
this.config = inject(ConfigService);
|
|
63
|
+
this.translate = inject(TranslateService);
|
|
64
|
+
this.shell = inject(ShellService);
|
|
65
|
+
this.document = inject(DOCUMENT);
|
|
66
|
+
this.#fb = inject(FormBuilder);
|
|
67
|
+
this.clientLocales = signal([]);
|
|
68
|
+
this.clientVersion = signal(undefined);
|
|
69
|
+
this.user = toSignal(this.userService.user$);
|
|
70
|
+
this.appSettingForms$ = this.shell.appSettings$.pipe(map((settings) => settings.map((e) => {
|
|
71
|
+
const x = {};
|
|
72
|
+
const fcn = e.properties.map((p) => ({
|
|
73
|
+
label: this.translate.instant(p.label) || p.label,
|
|
74
|
+
name: p.name,
|
|
75
|
+
type: p.type
|
|
76
|
+
}));
|
|
77
|
+
e.properties.forEach((p) => {
|
|
78
|
+
x[p.name] = [p.value];
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
appID: e.appID,
|
|
82
|
+
label: e.label,
|
|
83
|
+
formControls: fcn,
|
|
84
|
+
form: this.#fb.group(x)
|
|
85
|
+
};
|
|
86
|
+
})));
|
|
87
|
+
}
|
|
88
|
+
#fb;
|
|
89
|
+
saveAppSettings(appID, form) {
|
|
90
|
+
this.userService
|
|
91
|
+
.saveUserSettings({
|
|
92
|
+
clientAppSettings: {
|
|
93
|
+
[appID]: form.value
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
.subscribe({
|
|
97
|
+
next: () => {
|
|
98
|
+
form.markAsPristine();
|
|
99
|
+
},
|
|
100
|
+
error: (err) => {
|
|
101
|
+
console.error('Error saving app settings', err);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
changeClientLocale(iso) {
|
|
106
|
+
this.userService.changeClientLocale(iso);
|
|
107
|
+
}
|
|
108
|
+
ngOnInit() {
|
|
109
|
+
this.clientVersion.set(this.document.body.getAttribute('data-version') ?? 'dev');
|
|
110
|
+
this.clientLocales.set(this.config.getClientLocales());
|
|
111
|
+
}
|
|
112
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SettingsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
113
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: SettingsPageComponent, isStandalone: true, selector: "yuv-settings", ngImport: i0, template: "<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <h4>{{ 'yuc.shell.settings.client.version' | translate }}: {{ clientVersion() }}</h4>\n</header>\n\n\n<main>@if (user()) {\n <section class=\"user\">\n <!-- <yuv-user-avatar class=\"background\" [user]=\"user()\"></yuv-user-avatar> -->\n <div class=\"user\">\n <div class=\"meta uname\">{{ user()!.username }}</div>\n <h2>{{ user()!.title }}</h2>\n <div class=\"meta uemail\">{{ user()!.email }}</div>\n <div class=\"meta utenant\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user()!.tenant }}</div>\n </div>\n </section>\n}\n <!-- language -->\n <section yuvOfflineDisabled>\n <div class=\"label\" translate>yuv.shell.settings.language</div>\n <div class=\"value buttons\">\n @for (locale of clientLocales(); track locale.iso) {\n <button class=\"toggle secondary\" (click)=\"changeClientLocale(locale.iso)\" [ngClass]=\"{ active: translate.currentLang === locale.iso }\">\n {{ locale.label }}\n </button>\n }\n </div>\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</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:calc(var(--app-pane-padding) * 2)}:host header h1,:host header h4{margin:0}:host header h1{font-size:var(--font-display);font-weight:400}:host header h4{font-size:var(--font-cation);font-weight:400;font-style:italic;color:var(--text-color-caption)}:host main{grid-area:settings;padding:var(--app-pane-padding);overflow-y:auto}:host main section{display:flex;flex-flow:column;padding:var(--app-pane-padding)}:host main section .label{margin-block-end:1em}:host main section .value{display:flex;flex-flow:row wrap;gap:calc(var(--app-pane-padding) / 4)}:host main section.user h2{margin:0 0 1rem;font-weight:400}:host button.active{background-color:var(--color-accent);color:var(--color-accent-tone);pointer-events:none}:host button.color.clear{padding:2px 8px}:host button.color.accent.active{outline:2px solid #fff;outline-offset:-2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "directive", type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); }
|
|
114
|
+
}
|
|
115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SettingsPageComponent, decorators: [{
|
|
116
|
+
type: Component,
|
|
117
|
+
args: [{ selector: 'yuv-settings', standalone: true, imports: [CommonModule, TranslateModule, ReactiveFormsModule], template: "<header>\n <h1>{{ 'yuv.shell.settings.title' | translate }}</h1>\n <h4>{{ 'yuc.shell.settings.client.version' | translate }}: {{ clientVersion() }}</h4>\n</header>\n\n\n<main>@if (user()) {\n <section class=\"user\">\n <!-- <yuv-user-avatar class=\"background\" [user]=\"user()\"></yuv-user-avatar> -->\n <div class=\"user\">\n <div class=\"meta uname\">{{ user()!.username }}</div>\n <h2>{{ user()!.title }}</h2>\n <div class=\"meta uemail\">{{ user()!.email }}</div>\n <div class=\"meta utenant\">{{ 'yuv.shell.settings.tenant' | translate }}: {{ user()!.tenant }}</div>\n </div>\n </section>\n}\n <!-- language -->\n <section yuvOfflineDisabled>\n <div class=\"label\" translate>yuv.shell.settings.language</div>\n <div class=\"value buttons\">\n @for (locale of clientLocales(); track locale.iso) {\n <button class=\"toggle secondary\" (click)=\"changeClientLocale(locale.iso)\" [ngClass]=\"{ active: translate.currentLang === locale.iso }\">\n {{ locale.label }}\n </button>\n }\n </div>\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</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:calc(var(--app-pane-padding) * 2)}:host header h1,:host header h4{margin:0}:host header h1{font-size:var(--font-display);font-weight:400}:host header h4{font-size:var(--font-cation);font-weight:400;font-style:italic;color:var(--text-color-caption)}:host main{grid-area:settings;padding:var(--app-pane-padding);overflow-y:auto}:host main section{display:flex;flex-flow:column;padding:var(--app-pane-padding)}:host main section .label{margin-block-end:1em}:host main section .value{display:flex;flex-flow:row wrap;gap:calc(var(--app-pane-padding) / 4)}:host main section.user h2{margin:0 0 1rem;font-weight:400}:host button.active{background-color:var(--color-accent);color:var(--color-accent-tone);pointer-events:none}:host button.color.clear{padding:2px 8px}:host button.color.accent.active{outline:2px solid #fff;outline-offset:-2px}\n"] }]
|
|
118
|
+
}] });
|
|
119
|
+
|
|
120
|
+
class NotificationsPageComponent {
|
|
121
|
+
constructor() {
|
|
122
|
+
this.router = inject(Router);
|
|
123
|
+
this.shellNotifications = inject(ShellNotificationsService);
|
|
124
|
+
this.elRef = inject(ElementRef);
|
|
125
|
+
this._focusedIndex = -1;
|
|
126
|
+
this._notificationIDs = [];
|
|
127
|
+
this.notifications = toSignal(this.shellNotifications.shellNotifications$);
|
|
128
|
+
this.notificationsIdEffect = effect(() => (this._notificationIDs = (this.notifications() || []).map((n) => n.id)));
|
|
129
|
+
this.icons = {
|
|
130
|
+
close: ICONS.clear,
|
|
131
|
+
trash: YUV_ICONS.trash,
|
|
132
|
+
note: YUV_ICONS.notification
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
onKeydown(event) {
|
|
136
|
+
switch (event.code) {
|
|
137
|
+
case 'Delete': {
|
|
138
|
+
if (this._focusedIndex >= 0)
|
|
139
|
+
this.remove(this._notificationIDs[this._focusedIndex]);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async itemSelected(idx) {
|
|
145
|
+
const n = this.shellNotifications.getNotificationById(this._notificationIDs[idx[0]]);
|
|
146
|
+
if (n?.targetRoute) {
|
|
147
|
+
await this.close();
|
|
148
|
+
this.router.navigateByUrl(n.targetRoute, { replaceUrl: true });
|
|
149
|
+
if (n.removeOnTargetRouteNavigated)
|
|
150
|
+
this.remove(n.id);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
itemFocused(index) {
|
|
154
|
+
this._focusedIndex = index;
|
|
155
|
+
}
|
|
156
|
+
remove(id) {
|
|
157
|
+
if (id)
|
|
158
|
+
this.shellNotifications.remove(id);
|
|
159
|
+
}
|
|
160
|
+
removeAll() {
|
|
161
|
+
this.shellNotifications.removeAll();
|
|
162
|
+
}
|
|
163
|
+
close() {
|
|
164
|
+
return this.router.navigate([{ outlets: { aside: null } }], {
|
|
165
|
+
replaceUrl: true
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
ngOnInit() {
|
|
169
|
+
this.shellNotifications.markAllAsSeen();
|
|
170
|
+
setTimeout(() => {
|
|
171
|
+
const fc = Utils.getFocusableChildren(this.elRef.nativeElement);
|
|
172
|
+
if (fc.length)
|
|
173
|
+
fc[0].focus();
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
177
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: NotificationsPageComponent, isStandalone: true, selector: "yuv-notifications", host: { listeners: { "keydown": "onKeydown($event)" } }, ngImport: i0, template: "<div class=\"notifications\" (yuvLightDismiss)=\"close()\" cdkTrapFocus>\n <h2>{{ 'yuv.shell.notifications.title' | translate }}</h2>\n\n @if (notifications()?.length) {\n <yuv-list (itemSelect)=\"itemSelected($event)\" (itemFocus)=\"itemFocused($event)\">\n @for (n of notifications(); track n.id) {\n <div class=\"note {{ n.level }}\" [ngClass]=\"{ withRoute: n.targetRoute }\" yuvListItem>\n <div class=\"icon\"><yvc-icon [svg]=\"n.icon || icons.note\"></yvc-icon></div>\n <div class=\"received\">{{ n.timestamp | localeDate }}</div>\n <div class=\"title\">{{ n.title }}</div>\n <div class=\"description\">{{ n.description }}</div>\n <div class=\"meta\"></div>\n\n <div class=\"actions\">\n <button (click)=\"remove(n.id)\">\n <yvc-icon [svg]=\"icons.trash\"></yvc-icon>\n </button>\n </div>\n </div>\n }\n </yuv-list>\n\n <div class=\"actions\">\n <button [hidden]=\"!notifications()?.length\" class=\"icon secondary\" (click)=\"removeAll()\">\n {{ 'yuv.shell.notifications.button.remove.all' | translate }}<yvc-icon [svg]=\"icons.trash\"></yvc-icon>\n </button>\n </div>\n } @else {\n <div class=\"empty\">\n <p>{{ 'yuv.shell.notifications.empty' | translate }}</p>\n </div>\n }\n\n <button class=\"icon close\" (click)=\"close()\">\n <yvc-icon [svg]=\"icons.close\"></yvc-icon>\n </button>\n</div>\n", styles: [":host{height:100%;display:flex}:host .notifications{background-color:var(--panel-background-lightgrey);border-inline-end:1px solid var(--panel-divider-color);height:100%;overflow:hidden;box-sizing:border-box;padding:var(--app-pane-padding);display:grid;grid-template-rows:auto auto 1fr;grid-template-columns:1fr auto;grid-template-areas:\"title close\" \"actions actions\" \"list list\";gap:var(--app-pane-padding);max-width:30vw;min-width:300px;box-shadow:8px 0 8px #0000001a;animation:dialogAppear .2s ease-in-out}:host .notifications h2{color:var(--text-color-caption);grid-area:title;margin:0;padding:0;align-self:center;font-size:var(--font-title);font-weight:400;text-overflow:ellipsis;overflow:hidden}:host .notifications .actions{grid-area:actions;display:flex;justify-content:end;--icon-size: 18px}:host .notifications .actions button{border-radius:.4em}:host .notifications .close{grid-area:close;--icon-size: 18px}:host .notifications yuv-list,:host .notifications .empty{grid-area:list}:host .notifications .empty{display:grid;align-items:center;justify-content:center;color:var(--text-color-caption)}:host .notifications .note{--level-color: transparent;display:grid;grid-template-rows:auto auto auto auto;grid-template-columns:auto 1fr auto;grid-template-areas:\"icon received actions\" \"icon title title\" \"icon description description\" \"icon meta meta\";row-gap:calc(var(--app-pane-padding) / 4);column-gap:calc(var(--app-pane-padding) / 2);align-items:center;padding:calc(var(--app-pane-padding) / 2);padding-inline-start:var(--app-pane-padding);margin-block-end:calc(var(--app-pane-padding) / 2);background-color:var(--panel-background);outline:1px solid var(--panel-divider-color);outline-offset:-1px;position:relative;cursor:default}:host .notifications .note.withRoute{cursor:pointer}:host .notifications .note:before{content:\"\";width:4px;position:absolute;left:2px;top:2px;bottom:2px;border-radius:2px;background-color:var(--level-color)}:host .notifications .note.alert{--level-color: var(--color-error)}:host .notifications .note.warning{--level-color: var(--color-warning)}:host .notifications .note.success{--level-color: var(--color-success)}:host .notifications .note:hover,:host .notifications .note[aria-current=true]{background-color:var(--item-focus-background-color)}:host .notifications .note:hover button,:host .notifications .note[aria-current=true] button{opacity:1}:host .notifications .note .icon{grid-area:icon;color:var(--text-color-caption)}:host .notifications .note .title{overflow:hidden;text-overflow:ellipsis;font-weight:700;grid-area:title;color:var(--text-color-body)}:host .notifications .note .description{grid-area:description;overflow:hidden;text-overflow:ellipsis}:host .notifications .note .meta{grid-area:meta}:host .notifications .note .received{grid-area:received;color:var(--text-color-caption)}:host .notifications .note button{grid-area:actions;padding:0;opacity:0}:host .notifications .note button yvc-icon{width:18px;height:18px}@keyframes dialogAppear{0%{opacity:0;transform:translate(calc(var(--app-pane-padding) * -1))}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: LightDismissDirective, selector: "[yuvLightDismiss]", outputs: ["yuvLightDismiss"] }, { kind: "pipe", type: LocaleDatePipe, name: "localeDate" }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i2$1.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: ListComponent, selector: "yuv-list", inputs: ["multiselect", "disableSelection"], outputs: ["itemSelect", "itemFocus"] }, { kind: "directive", type: ListItemDirective, selector: "[yuvListItem]", inputs: ["disabled", "active", "selected"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
|
|
178
|
+
}
|
|
179
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NotificationsPageComponent, decorators: [{
|
|
180
|
+
type: Component,
|
|
181
|
+
args: [{ selector: 'yuv-notifications', standalone: true, imports: [CommonModule, LightDismissDirective, LocaleDatePipe, YvcIconModule, CdkTrapFocus, ListComponent, ListItemDirective, TranslateModule], template: "<div class=\"notifications\" (yuvLightDismiss)=\"close()\" cdkTrapFocus>\n <h2>{{ 'yuv.shell.notifications.title' | translate }}</h2>\n\n @if (notifications()?.length) {\n <yuv-list (itemSelect)=\"itemSelected($event)\" (itemFocus)=\"itemFocused($event)\">\n @for (n of notifications(); track n.id) {\n <div class=\"note {{ n.level }}\" [ngClass]=\"{ withRoute: n.targetRoute }\" yuvListItem>\n <div class=\"icon\"><yvc-icon [svg]=\"n.icon || icons.note\"></yvc-icon></div>\n <div class=\"received\">{{ n.timestamp | localeDate }}</div>\n <div class=\"title\">{{ n.title }}</div>\n <div class=\"description\">{{ n.description }}</div>\n <div class=\"meta\"></div>\n\n <div class=\"actions\">\n <button (click)=\"remove(n.id)\">\n <yvc-icon [svg]=\"icons.trash\"></yvc-icon>\n </button>\n </div>\n </div>\n }\n </yuv-list>\n\n <div class=\"actions\">\n <button [hidden]=\"!notifications()?.length\" class=\"icon secondary\" (click)=\"removeAll()\">\n {{ 'yuv.shell.notifications.button.remove.all' | translate }}<yvc-icon [svg]=\"icons.trash\"></yvc-icon>\n </button>\n </div>\n } @else {\n <div class=\"empty\">\n <p>{{ 'yuv.shell.notifications.empty' | translate }}</p>\n </div>\n }\n\n <button class=\"icon close\" (click)=\"close()\">\n <yvc-icon [svg]=\"icons.close\"></yvc-icon>\n </button>\n</div>\n", styles: [":host{height:100%;display:flex}:host .notifications{background-color:var(--panel-background-lightgrey);border-inline-end:1px solid var(--panel-divider-color);height:100%;overflow:hidden;box-sizing:border-box;padding:var(--app-pane-padding);display:grid;grid-template-rows:auto auto 1fr;grid-template-columns:1fr auto;grid-template-areas:\"title close\" \"actions actions\" \"list list\";gap:var(--app-pane-padding);max-width:30vw;min-width:300px;box-shadow:8px 0 8px #0000001a;animation:dialogAppear .2s ease-in-out}:host .notifications h2{color:var(--text-color-caption);grid-area:title;margin:0;padding:0;align-self:center;font-size:var(--font-title);font-weight:400;text-overflow:ellipsis;overflow:hidden}:host .notifications .actions{grid-area:actions;display:flex;justify-content:end;--icon-size: 18px}:host .notifications .actions button{border-radius:.4em}:host .notifications .close{grid-area:close;--icon-size: 18px}:host .notifications yuv-list,:host .notifications .empty{grid-area:list}:host .notifications .empty{display:grid;align-items:center;justify-content:center;color:var(--text-color-caption)}:host .notifications .note{--level-color: transparent;display:grid;grid-template-rows:auto auto auto auto;grid-template-columns:auto 1fr auto;grid-template-areas:\"icon received actions\" \"icon title title\" \"icon description description\" \"icon meta meta\";row-gap:calc(var(--app-pane-padding) / 4);column-gap:calc(var(--app-pane-padding) / 2);align-items:center;padding:calc(var(--app-pane-padding) / 2);padding-inline-start:var(--app-pane-padding);margin-block-end:calc(var(--app-pane-padding) / 2);background-color:var(--panel-background);outline:1px solid var(--panel-divider-color);outline-offset:-1px;position:relative;cursor:default}:host .notifications .note.withRoute{cursor:pointer}:host .notifications .note:before{content:\"\";width:4px;position:absolute;left:2px;top:2px;bottom:2px;border-radius:2px;background-color:var(--level-color)}:host .notifications .note.alert{--level-color: var(--color-error)}:host .notifications .note.warning{--level-color: var(--color-warning)}:host .notifications .note.success{--level-color: var(--color-success)}:host .notifications .note:hover,:host .notifications .note[aria-current=true]{background-color:var(--item-focus-background-color)}:host .notifications .note:hover button,:host .notifications .note[aria-current=true] button{opacity:1}:host .notifications .note .icon{grid-area:icon;color:var(--text-color-caption)}:host .notifications .note .title{overflow:hidden;text-overflow:ellipsis;font-weight:700;grid-area:title;color:var(--text-color-body)}:host .notifications .note .description{grid-area:description;overflow:hidden;text-overflow:ellipsis}:host .notifications .note .meta{grid-area:meta}:host .notifications .note .received{grid-area:received;color:var(--text-color-caption)}:host .notifications .note button{grid-area:actions;padding:0;opacity:0}:host .notifications .note button yvc-icon{width:18px;height:18px}@keyframes dialogAppear{0%{opacity:0;transform:translate(calc(var(--app-pane-padding) * -1))}to{opacity:1;transform:translate(0)}}\n"] }]
|
|
182
|
+
}], propDecorators: { onKeydown: [{
|
|
183
|
+
type: HostListener,
|
|
184
|
+
args: ['keydown', ['$event']]
|
|
185
|
+
}] } });
|
|
186
|
+
|
|
187
|
+
class WebShareTargetPageComponent {
|
|
188
|
+
constructor() {
|
|
189
|
+
navigator.serviceWorker.onmessage = (e) => {
|
|
190
|
+
const file = e.data.file;
|
|
191
|
+
console.log(file);
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WebShareTargetPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
195
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: WebShareTargetPageComponent, isStandalone: true, selector: "yuv-web-share-target", ngImport: i0, template: "<p>web-share-target works!</p>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
|
|
196
|
+
}
|
|
197
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WebShareTargetPageComponent, decorators: [{
|
|
198
|
+
type: Component,
|
|
199
|
+
args: [{ selector: 'yuv-web-share-target', standalone: true, imports: [CommonModule], template: "<p>web-share-target works!</p>\n" }]
|
|
200
|
+
}], ctorParameters: () => [] });
|
|
201
|
+
|
|
202
|
+
const clientShellRoutes = [
|
|
203
|
+
{ path: 'dashboard', component: DashboardPageComponent },
|
|
204
|
+
{ path: 'notifications', component: NotificationsPageComponent, outlet: 'aside' },
|
|
205
|
+
{ path: 'settings', component: SettingsPageComponent },
|
|
206
|
+
{ path: 'web-share-target', component: WebShareTargetPageComponent },
|
|
207
|
+
// default route
|
|
208
|
+
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
|
|
209
|
+
// redirecting route
|
|
210
|
+
{ path: '**', redirectTo: '/' }
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
class ClientShellComponent {
|
|
214
|
+
#shell;
|
|
215
|
+
#device;
|
|
216
|
+
#swPush;
|
|
217
|
+
onFocusChange(event) {
|
|
218
|
+
// console.log('focused: ', document.activeElement);
|
|
219
|
+
}
|
|
220
|
+
onDragOver(event) {
|
|
221
|
+
event.stopPropagation();
|
|
222
|
+
event.preventDefault();
|
|
223
|
+
this.showUploadOverlay = !!this._dragContainsFiles(event);
|
|
224
|
+
}
|
|
225
|
+
#appsEffect;
|
|
226
|
+
#shellConfigEffect;
|
|
227
|
+
constructor() {
|
|
228
|
+
this.router = inject(Router);
|
|
229
|
+
this.auth = inject(AuthService);
|
|
230
|
+
this.userService = inject(UserService);
|
|
231
|
+
this.#shell = inject(ShellService);
|
|
232
|
+
this.shellNotifications = inject(ShellNotificationsService);
|
|
233
|
+
this.translate = inject(TranslateService);
|
|
234
|
+
this.commandPalette = inject(CommandPaletteService);
|
|
235
|
+
this.#device = inject(DeviceService);
|
|
236
|
+
this.#swPush = inject(SwPush);
|
|
237
|
+
this.APP_LOGOUT_EVENT_KEY = 'yuv.app.event.logout';
|
|
238
|
+
this._levels = {
|
|
239
|
+
info: 0,
|
|
240
|
+
success: 1,
|
|
241
|
+
warning: 2,
|
|
242
|
+
alert: 3
|
|
243
|
+
};
|
|
244
|
+
this.showUploadOverlay = false;
|
|
245
|
+
this.busy$ = this.#shell.isBusy$;
|
|
246
|
+
this.showNotifications = signal(false);
|
|
247
|
+
this.newNotifications = toSignal(this.shellNotifications.shellNotifications$.pipe(tap((n) => this.showNotifications.set(n.length > 0)), map$1((notifications) => {
|
|
248
|
+
let maxLevel = 'info';
|
|
249
|
+
const count = notifications.filter((n) => !n.seen).length;
|
|
250
|
+
notifications.forEach((n) => (maxLevel = n.level && this._levels[n.level] > this._levels[maxLevel] ? n.level : maxLevel));
|
|
251
|
+
return count > 0 ? { maxLevel, count } : undefined;
|
|
252
|
+
})));
|
|
253
|
+
this.apps = input.required();
|
|
254
|
+
this.#appsEffect = effect(() => this.#shell.setAppBaseRoutes(this.apps()));
|
|
255
|
+
this.checkedForInitialRoute = false;
|
|
256
|
+
this.enableTenantSwitch = false;
|
|
257
|
+
this.config = input();
|
|
258
|
+
this.#shellConfigEffect = effect(() => {
|
|
259
|
+
const cfg = this.config();
|
|
260
|
+
if (cfg) {
|
|
261
|
+
this.#shell.setShellConfig(cfg);
|
|
262
|
+
}
|
|
263
|
+
}, {
|
|
264
|
+
allowSignalWrites: true
|
|
265
|
+
});
|
|
266
|
+
this.shellConfig = this.#shell.shellConfig;
|
|
267
|
+
this.translate.onLangChange.subscribe(() => this._setCommands(true));
|
|
268
|
+
// this.router.events.pipe(
|
|
269
|
+
// // filter(e => e instanceof NavigationStart)
|
|
270
|
+
// ).subscribe((e) => {
|
|
271
|
+
// console.log(e);
|
|
272
|
+
// });
|
|
273
|
+
this.router.events
|
|
274
|
+
.pipe(filter((e) => e instanceof NavigationEnd), map$1((e) => e))
|
|
275
|
+
.subscribe((e) => this._processRouterNavigationEnd(e));
|
|
276
|
+
this.#device.init();
|
|
277
|
+
this.userService.user$.subscribe((user) => {
|
|
278
|
+
if (user) {
|
|
279
|
+
this.checkedForInitialRoute = !(!this.user || this.user.id !== user.id);
|
|
280
|
+
this.enableTenantSwitch = user.authorities.includes(UserRoles.MULTI_TENANT);
|
|
281
|
+
}
|
|
282
|
+
this.user = user;
|
|
283
|
+
});
|
|
284
|
+
window.addEventListener('storage', (evt) => {
|
|
285
|
+
if (evt.key === this.APP_LOGOUT_EVENT_KEY) {
|
|
286
|
+
this.appLogout(true);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
openNotifications() {
|
|
291
|
+
this.router.navigate([{}]);
|
|
292
|
+
}
|
|
293
|
+
// getNotifications(id: string) {
|
|
294
|
+
// return this.shellNotifications.getNotifications(id);
|
|
295
|
+
// }
|
|
296
|
+
_dragContainsFiles(event) {
|
|
297
|
+
// do not allow to drop files/images from iframes
|
|
298
|
+
if (event.relatedTarget?.tagName.toLowerCase() === 'iframe')
|
|
299
|
+
return 0;
|
|
300
|
+
return event.dataTransfer ? Array.from(event.dataTransfer.items || []).filter((i) => i.kind === 'file' && i.type).length : 0;
|
|
301
|
+
}
|
|
302
|
+
_setCommands(update) {
|
|
303
|
+
const commands = this.apps().map((a, i) => ({
|
|
304
|
+
id: `nav.app.${i}`,
|
|
305
|
+
label: this.translate.instant('yuv.shell.cmd.app.open', { title: a.title }),
|
|
306
|
+
callback: () => this.router.navigate([a.path])
|
|
307
|
+
}));
|
|
308
|
+
commands.push({
|
|
309
|
+
id: `nav.shell.settings`,
|
|
310
|
+
label: this.translate.instant('yuv.shell.cmd.open.settings'),
|
|
311
|
+
callback: () => this.router.navigate(['settings'])
|
|
312
|
+
});
|
|
313
|
+
commands.push({
|
|
314
|
+
id: `nav.shell.logout`,
|
|
315
|
+
label: this.translate.instant('yuv.shell.cmd.logout'),
|
|
316
|
+
callback: () => this.appLogout()
|
|
317
|
+
});
|
|
318
|
+
if (update)
|
|
319
|
+
this.commandPalette.updateCommands(commands);
|
|
320
|
+
else
|
|
321
|
+
this.commandPalette.registerCommands(commands);
|
|
322
|
+
}
|
|
323
|
+
requestSubscription() {
|
|
324
|
+
if (!this.#swPush.isEnabled) {
|
|
325
|
+
console.log('Notification is not enabled.');
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
this.#swPush.messages
|
|
329
|
+
.pipe(tap((msg) => console.log({ msg })), catchError((error) => {
|
|
330
|
+
console.log({ error });
|
|
331
|
+
return of(null);
|
|
332
|
+
}))
|
|
333
|
+
.subscribe();
|
|
334
|
+
}
|
|
335
|
+
appLogout(triggeredFromOtherTab) {
|
|
336
|
+
if (!triggeredFromOtherTab) {
|
|
337
|
+
// send storage event to logout all other open tabs
|
|
338
|
+
window.localStorage.setItem(this.APP_LOGOUT_EVENT_KEY, `${Date.now()}`);
|
|
339
|
+
}
|
|
340
|
+
this.userService.logout('');
|
|
341
|
+
}
|
|
342
|
+
_processRouterNavigationEnd(e) {
|
|
343
|
+
if (!this.checkedForInitialRoute) {
|
|
344
|
+
this.checkedForInitialRoute = true;
|
|
345
|
+
// redirect to the page the user logged out from the last time
|
|
346
|
+
// but only if current route is not a deep link
|
|
347
|
+
const ignoreRoutes = ['', 'dashboard', 'index.html'].map((s) => `${Utils.getBaseHref()}${s}`.replace('//', '/'));
|
|
348
|
+
const currentRoute = this.routeWithBaseHref(this.router.routerState.snapshot.url);
|
|
349
|
+
if (this.userService.getCurrentUser() && !ignoreRoutes.includes(currentRoute)) {
|
|
350
|
+
// get persisted routes to decide where to redirect the logged in user to
|
|
351
|
+
this.auth
|
|
352
|
+
.getInitialRequestUri()
|
|
353
|
+
.pipe(switchMap((res) => this.auth.resetInitialRequestUri().pipe(map$1((_) => res))))
|
|
354
|
+
.subscribe((res) => {
|
|
355
|
+
const loginRes = res && !ignoreRoutes.includes(res.uri) ? res : null;
|
|
356
|
+
if (loginRes)
|
|
357
|
+
this.router.navigateByUrl(loginRes.uri);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
routeWithBaseHref(r) {
|
|
363
|
+
return `${Utils.getBaseHref()}${r}`.replace('//', '/');
|
|
364
|
+
}
|
|
365
|
+
ngOnInit() {
|
|
366
|
+
this.#shell._init();
|
|
367
|
+
clientShellRoutes.forEach((route) => {
|
|
368
|
+
this.router.config.push(route);
|
|
369
|
+
});
|
|
370
|
+
this.router.resetConfig(this.router.config);
|
|
371
|
+
this._setCommands();
|
|
372
|
+
this.requestSubscription();
|
|
373
|
+
}
|
|
374
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ClientShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
375
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ClientShellComponent, isStandalone: true, selector: "yuv-client-shell", inputs: { apps: { classPropertyName: "apps", publicName: "apps", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:focusin": "onFocusChange($event)", "dragover": "onDragOver($event)" } }, ngImport: i0, template: "<yuv-metadata-default-templates></yuv-metadata-default-templates>\n<!-- <yuv-focus-indicator /> -->\n\n<!-- gloabl busy indicator -->\n@if (busy$ | async) {\n <div class=\"yuv-loader-linear\"></div>\n}\n<nav class=\"apps\" [inert]=\"asideOutlet.isActivated\" [attr.aria-label]=\"'yuv.shell.naviagtion.aria.label' | translate\">\n <div class=\"app-icon\">\n <button routerLink=\"/\" routerLinkActive=\"active\" [attr.aria-label]=\"'yuv.shell.logo.aria.label' | translate\">\n <yvc-icon [svg]=\"shellConfig().icons!.appIcon!\"></yvc-icon>\n </button>\n </div>\n <ul class=\"apps\">\n @for (a of apps(); track a.path) {\n <li>\n <button routerLinkActive=\"active\" [routerLink]=\"a.path\" title=\"{{ a.title }}\">\n <yvc-icon [svg]=\"a.icon\" title=\"{{ a.title }}\" *ngIf=\"a.icon\"></yvc-icon>\n <!-- @if (getNotifications(a.id)) {\n <div [ngClass]=\"'badge ' + getNotifications(a.id).maxLevel\">{{ getNotifications(a.id).count }}</div>\n } -->\n </button>\n </li>\n }\n </ul>\n\n <section class=\"actions\">\n @if (showNotifications()) {\n <button [routerLink]=\"[{ outlets: { aside: 'notifications' } }]\" routerLinkActive=\"active\" title=\"{{ 'yuv.shell.notifications.title' | translate }}\">\n <yvc-icon [svg]=\"shellConfig().icons!.notifications!\"></yvc-icon>\n @if (newNotifications(); as note) {\n <div class=\"badge {{ note.maxLevel }}\">{{ note.count }}</div>\n }\n </button>\n }\n <button [routerLink]=\"['/settings']\" routerLinkActive=\"active\" title=\"{{ 'yuv.shell.settings.title' | translate }}\">\n <yvc-icon [svg]=\"shellConfig().icons!.settings!\"></yvc-icon>\n </button>\n <button (click)=\"appLogout()\" title=\"{{ 'yuv.shell.cmd.logout' | translate }}\"><yvc-icon [svg]=\"shellConfig().icons!.logout!\"></yvc-icon></button>\n </section>\n</nav>\n<main id=\"main-shell_content\" aria-label=\"main shell content\" [inert]=\"asideOutlet.isActivated\">\n <router-outlet></router-outlet>\n</main>\n\n<!-- outlet for aside modals like notifications -->\n<div class=\"asideOutlet\" [hidden]=\"!asideOutlet.isActivated\">\n <router-outlet name=\"aside\" #asideOutlet=\"outlet\"></router-outlet>\n</div>\n\n<div id=\"fi\" inert></div>\n", styles: [":host{--client-shell-background-color: var(--main-background);--client-shell-bar-background-color: var(--panel-background);--client-shell-bar-icon-size: 24px;--client-shell-bar-button-padding: calc(var(--app-pane-padding) * .75);--client-shell-bar-width: calc(var(--client-shell-bar-icon-size) + var(--client-shell-bar-button-padding) * 2 + 1px);position:absolute;inset:0;overflow:hidden;display:flex;background-color:var(--client-shell-background-color)}:host .yuv-loader-linear{position:absolute}:host nav{background-color:var(--client-shell-bar-background-color);height:100%;overflow-y:auto;border-inline-end:1px solid var(--panel-divider-color);flex:0 0 auto;display:var(--nav-display, grid);grid-template-rows:auto 1fr auto;grid-template-columns:1fr;grid-template-areas:\"appIcon\" \"apps\" \"actions\"}:host nav button{padding:var(--client-shell-bar-button-padding);border-radius:0;border:0}:host nav button yvc-icon{--icon-size: var(--client-shell-bar-icon-size)}:host nav button.active{color:var(--color-accent)}:host nav .app-icon{grid-area:appIcon}:host nav ul.apps{grid-area:apps;list-style:none;margin:0;padding:0;overflow-y:auto}:host nav ul.apps button{position:relative}:host nav ul.apps button .badge{--badge-color: var(--color-accent);--badge-color-tone: var(--color-accent-tone);position:absolute;background-color:var(--badge-color);color:var(--badge-color-tone);font-size:10px;display:block;padding:1px 2px;border-radius:.25em;line-height:1em;top:calc(var(--app-pane-padding) / 4);right:calc(var(--app-pane-padding) / 4)}:host nav ul.apps button .badge.success{--badge-color: var(--color-success);--badge-color-tone: #fff}:host nav ul.apps button .badge.warning{--badge-color: var(--color-warning);--badge-color-tone: #fff}:host nav ul.apps button .badge.alert{--badge-color: var(--color-error);--badge-color-tone: #fff}:host nav ul.apps li a{display:block;padding:var(--app-pane-padding)}:host nav section.actions{grid-area:actions}:host nav section.actions button{position:relative}:host nav section.actions button .badge{--badge-color: var(--color-accent);--badge-color-tone: var(--color-accent-tone);position:absolute;background-color:var(--badge-color);color:var(--badge-color-tone);font-size:10px;display:block;padding:1px 2px;border-radius:.25em;line-height:1em;top:calc(var(--app-pane-padding) / 4);right:calc(var(--app-pane-padding) / 4)}:host nav section.actions button .badge.success{--badge-color: var(--color-success);--badge-color-tone: #fff}:host nav section.actions button .badge.warning{--badge-color: var(--color-warning);--badge-color-tone: #fff}:host nav section.actions button .badge.alert{--badge-color: var(--color-error);--badge-color-tone: #fff}:host main{flex:1;color:var(--text-color-body)}:host .asideOutlet{position:absolute;inset:0;padding-inline-start:var(--client-shell-bar-width)}:host-context([data-screen-size=s][data-screen-orientation=portrait]){flex-flow:column-reverse}:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav{height:auto;grid-template-rows:1fr;grid-template-columns:auto 1fr auto;grid-template-areas:\"appIcon apps actions\";border:0;border-block-start:1px solid var(--panel-divider-color)}:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav .app-icon{display:none}:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav ul.apps,:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav section.actions{display:flex}:host-context([data-screen-size=s][data-screen-orientation=portrait]) main{overflow:hidden}:host-context([data-screen-size=s][data-screen-orientation=portrait]) .asideOutlet{padding-inline-start:0}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i2$2.RouterOutlet, selector: "router-outlet", inputs: ["name"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: i2$2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2$2.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i2$1.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "component", type: MetadataDefaultTemplatesComponent, selector: "yuv-metadata-default-templates" }] }); }
|
|
376
|
+
}
|
|
377
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ClientShellComponent, decorators: [{
|
|
378
|
+
type: Component,
|
|
379
|
+
args: [{ selector: 'yuv-client-shell', standalone: true, imports: [NgIf, AsyncPipe, TranslateModule, RouterModule, YvcIconModule, MetadataDefaultTemplatesComponent], template: "<yuv-metadata-default-templates></yuv-metadata-default-templates>\n<!-- <yuv-focus-indicator /> -->\n\n<!-- gloabl busy indicator -->\n@if (busy$ | async) {\n <div class=\"yuv-loader-linear\"></div>\n}\n<nav class=\"apps\" [inert]=\"asideOutlet.isActivated\" [attr.aria-label]=\"'yuv.shell.naviagtion.aria.label' | translate\">\n <div class=\"app-icon\">\n <button routerLink=\"/\" routerLinkActive=\"active\" [attr.aria-label]=\"'yuv.shell.logo.aria.label' | translate\">\n <yvc-icon [svg]=\"shellConfig().icons!.appIcon!\"></yvc-icon>\n </button>\n </div>\n <ul class=\"apps\">\n @for (a of apps(); track a.path) {\n <li>\n <button routerLinkActive=\"active\" [routerLink]=\"a.path\" title=\"{{ a.title }}\">\n <yvc-icon [svg]=\"a.icon\" title=\"{{ a.title }}\" *ngIf=\"a.icon\"></yvc-icon>\n <!-- @if (getNotifications(a.id)) {\n <div [ngClass]=\"'badge ' + getNotifications(a.id).maxLevel\">{{ getNotifications(a.id).count }}</div>\n } -->\n </button>\n </li>\n }\n </ul>\n\n <section class=\"actions\">\n @if (showNotifications()) {\n <button [routerLink]=\"[{ outlets: { aside: 'notifications' } }]\" routerLinkActive=\"active\" title=\"{{ 'yuv.shell.notifications.title' | translate }}\">\n <yvc-icon [svg]=\"shellConfig().icons!.notifications!\"></yvc-icon>\n @if (newNotifications(); as note) {\n <div class=\"badge {{ note.maxLevel }}\">{{ note.count }}</div>\n }\n </button>\n }\n <button [routerLink]=\"['/settings']\" routerLinkActive=\"active\" title=\"{{ 'yuv.shell.settings.title' | translate }}\">\n <yvc-icon [svg]=\"shellConfig().icons!.settings!\"></yvc-icon>\n </button>\n <button (click)=\"appLogout()\" title=\"{{ 'yuv.shell.cmd.logout' | translate }}\"><yvc-icon [svg]=\"shellConfig().icons!.logout!\"></yvc-icon></button>\n </section>\n</nav>\n<main id=\"main-shell_content\" aria-label=\"main shell content\" [inert]=\"asideOutlet.isActivated\">\n <router-outlet></router-outlet>\n</main>\n\n<!-- outlet for aside modals like notifications -->\n<div class=\"asideOutlet\" [hidden]=\"!asideOutlet.isActivated\">\n <router-outlet name=\"aside\" #asideOutlet=\"outlet\"></router-outlet>\n</div>\n\n<div id=\"fi\" inert></div>\n", styles: [":host{--client-shell-background-color: var(--main-background);--client-shell-bar-background-color: var(--panel-background);--client-shell-bar-icon-size: 24px;--client-shell-bar-button-padding: calc(var(--app-pane-padding) * .75);--client-shell-bar-width: calc(var(--client-shell-bar-icon-size) + var(--client-shell-bar-button-padding) * 2 + 1px);position:absolute;inset:0;overflow:hidden;display:flex;background-color:var(--client-shell-background-color)}:host .yuv-loader-linear{position:absolute}:host nav{background-color:var(--client-shell-bar-background-color);height:100%;overflow-y:auto;border-inline-end:1px solid var(--panel-divider-color);flex:0 0 auto;display:var(--nav-display, grid);grid-template-rows:auto 1fr auto;grid-template-columns:1fr;grid-template-areas:\"appIcon\" \"apps\" \"actions\"}:host nav button{padding:var(--client-shell-bar-button-padding);border-radius:0;border:0}:host nav button yvc-icon{--icon-size: var(--client-shell-bar-icon-size)}:host nav button.active{color:var(--color-accent)}:host nav .app-icon{grid-area:appIcon}:host nav ul.apps{grid-area:apps;list-style:none;margin:0;padding:0;overflow-y:auto}:host nav ul.apps button{position:relative}:host nav ul.apps button .badge{--badge-color: var(--color-accent);--badge-color-tone: var(--color-accent-tone);position:absolute;background-color:var(--badge-color);color:var(--badge-color-tone);font-size:10px;display:block;padding:1px 2px;border-radius:.25em;line-height:1em;top:calc(var(--app-pane-padding) / 4);right:calc(var(--app-pane-padding) / 4)}:host nav ul.apps button .badge.success{--badge-color: var(--color-success);--badge-color-tone: #fff}:host nav ul.apps button .badge.warning{--badge-color: var(--color-warning);--badge-color-tone: #fff}:host nav ul.apps button .badge.alert{--badge-color: var(--color-error);--badge-color-tone: #fff}:host nav ul.apps li a{display:block;padding:var(--app-pane-padding)}:host nav section.actions{grid-area:actions}:host nav section.actions button{position:relative}:host nav section.actions button .badge{--badge-color: var(--color-accent);--badge-color-tone: var(--color-accent-tone);position:absolute;background-color:var(--badge-color);color:var(--badge-color-tone);font-size:10px;display:block;padding:1px 2px;border-radius:.25em;line-height:1em;top:calc(var(--app-pane-padding) / 4);right:calc(var(--app-pane-padding) / 4)}:host nav section.actions button .badge.success{--badge-color: var(--color-success);--badge-color-tone: #fff}:host nav section.actions button .badge.warning{--badge-color: var(--color-warning);--badge-color-tone: #fff}:host nav section.actions button .badge.alert{--badge-color: var(--color-error);--badge-color-tone: #fff}:host main{flex:1;color:var(--text-color-body)}:host .asideOutlet{position:absolute;inset:0;padding-inline-start:var(--client-shell-bar-width)}:host-context([data-screen-size=s][data-screen-orientation=portrait]){flex-flow:column-reverse}:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav{height:auto;grid-template-rows:1fr;grid-template-columns:auto 1fr auto;grid-template-areas:\"appIcon apps actions\";border:0;border-block-start:1px solid var(--panel-divider-color)}:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav .app-icon{display:none}:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav ul.apps,:host-context([data-screen-size=s][data-screen-orientation=portrait]) nav section.actions{display:flex}:host-context([data-screen-size=s][data-screen-orientation=portrait]) main{overflow:hidden}:host-context([data-screen-size=s][data-screen-orientation=portrait]) .asideOutlet{padding-inline-start:0}\n"] }]
|
|
380
|
+
}], ctorParameters: () => [], propDecorators: { onFocusChange: [{
|
|
381
|
+
type: HostListener,
|
|
382
|
+
args: ['document:focusin', ['$event']]
|
|
383
|
+
}], onDragOver: [{
|
|
384
|
+
type: HostListener,
|
|
385
|
+
args: ['dragover', ['$event']]
|
|
386
|
+
}] } });
|
|
387
|
+
|
|
388
|
+
class AppLogoComponent {
|
|
389
|
+
constructor() {
|
|
390
|
+
this.icon = input();
|
|
391
|
+
this.label = input.required();
|
|
392
|
+
}
|
|
393
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppLogoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
394
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppLogoComponent, isStandalone: true, selector: "yuv-app-logo", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let ico = icon();\n@if(ico){\n<yvc-icon [svg]=\"ico\"></yvc-icon>\n}<span class=\"label\">{{label()}}</span>", styles: [":host{--band-color: var(--text-color-body);--band-height: var(--client-shell-bar-icon-size);--band-icon-size: 32px;--text-color: var(--main-background);--icon-color: var(--text-color);--icon-background-color: transparent;display:flex;align-items:center;padding:0 calc(var(--app-pane-padding) / 1) 0 calc(var(--app-pane-padding) / 2);height:calc(var(--client-shell-bar-icon-size));font-size:var(--font-caption);line-height:1em;cursor:pointer;background-color:var(--band-color);color:var(--text-color)}:host yvc-icon{--icon-size: var(--band-icon-size);grid-column:2;grid-row:1;border-radius:4px;margin-inline-end:calc(var(--app-pane-padding) / 2);opacity:.5;color:var(--icon-color);background-color:var(--icon-background-color)}:host .label{line-height:1em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i2$1.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }] }); }
|
|
395
|
+
}
|
|
396
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppLogoComponent, decorators: [{
|
|
397
|
+
type: Component,
|
|
398
|
+
args: [{ selector: 'yuv-app-logo', standalone: true, imports: [CommonModule, YvcIconModule], template: "@let ico = icon();\n@if(ico){\n<yvc-icon [svg]=\"ico\"></yvc-icon>\n}<span class=\"label\">{{label()}}</span>", styles: [":host{--band-color: var(--text-color-body);--band-height: var(--client-shell-bar-icon-size);--band-icon-size: 32px;--text-color: var(--main-background);--icon-color: var(--text-color);--icon-background-color: transparent;display:flex;align-items:center;padding:0 calc(var(--app-pane-padding) / 1) 0 calc(var(--app-pane-padding) / 2);height:calc(var(--client-shell-bar-icon-size));font-size:var(--font-caption);line-height:1em;cursor:pointer;background-color:var(--band-color);color:var(--text-color)}:host yvc-icon{--icon-size: var(--band-icon-size);grid-column:2;grid-row:1;border-radius:4px;margin-inline-end:calc(var(--app-pane-padding) / 2);opacity:.5;color:var(--icon-color);background-color:var(--icon-background-color)}:host .label{line-height:1em}\n"] }]
|
|
399
|
+
}] });
|
|
400
|
+
|
|
401
|
+
class ManageFlavorsComponent {
|
|
402
|
+
constructor() {
|
|
403
|
+
this.#overlayRef = inject(YvcOverlayRef);
|
|
404
|
+
this.#shell = inject(ShellService);
|
|
405
|
+
this.#dmsService = inject(DmsService);
|
|
406
|
+
this.item = this.#overlayRef.data;
|
|
407
|
+
this.busy = signal(false);
|
|
408
|
+
this.appliedFlavors = [];
|
|
409
|
+
this.applicableFlavors = [];
|
|
410
|
+
}
|
|
411
|
+
#overlayRef;
|
|
412
|
+
#shell;
|
|
413
|
+
#dmsService;
|
|
414
|
+
applyFlavor(flavor) {
|
|
415
|
+
this.busy.set(true);
|
|
416
|
+
this.#shell.triggerApplyObjectFlavor(this.item, flavor).subscribe(() => {
|
|
417
|
+
this.#overlayRef.close();
|
|
418
|
+
this.busy.set(false);
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
removeFlavor(flavor) {
|
|
422
|
+
this.busy.set(true);
|
|
423
|
+
this.#shell.removeObjectFlavor(this.item, flavor).subscribe(() => {
|
|
424
|
+
this.#overlayRef.close();
|
|
425
|
+
this.busy.set(false);
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
#refreshDmsObject() {
|
|
429
|
+
this.busy.set(true);
|
|
430
|
+
this.#dmsService
|
|
431
|
+
.getDmsObject(this.item.id)
|
|
432
|
+
.pipe(tap$1((dmsObject) => {
|
|
433
|
+
this.item = dmsObject;
|
|
434
|
+
this.#getAppliedFlavors(this.item);
|
|
435
|
+
}))
|
|
436
|
+
.subscribe()
|
|
437
|
+
.add(() => this.busy.set(false));
|
|
438
|
+
}
|
|
439
|
+
#getAppliedFlavors(dmsObject) {
|
|
440
|
+
const res = this.#shell.getAppliedObjectFlavors(dmsObject);
|
|
441
|
+
this.appliedFlavors = res.applied;
|
|
442
|
+
this.applicableFlavors = res.applicable;
|
|
443
|
+
}
|
|
444
|
+
cancel() {
|
|
445
|
+
if (this.#overlayRef)
|
|
446
|
+
this.#overlayRef.close();
|
|
447
|
+
}
|
|
448
|
+
ngOnInit() {
|
|
449
|
+
this.#refreshDmsObject();
|
|
450
|
+
}
|
|
451
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ManageFlavorsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
452
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ManageFlavorsComponent, isStandalone: true, selector: "yuv-manage-flavors", ngImport: i0, template: "<header>\n <h2>{{ 'yuv.shell.action.manage-flavors.title' | translate }}</h2>\n <p>{{ 'yuv.shell.action.manage-flavors.text' | translate }}</p>\n</header>\n<main [yuvBusyOverlay]=\"busy()\">\n @if (appliedFlavors.length) {\n <h3>{{ 'yuv.shell.action.manage-flavors.applied.headline' | translate }}</h3>\n <ul>\n @for (f of appliedFlavors; track $index) {\n <li>\n <yuv-flavor-chip [flavor]=\"f\" yuvListItem></yuv-flavor-chip>\n <button class=\"secondary\" (click)=\"removeFlavor(f)\">{{ 'yuv.shell.action.manage-flavors.applicable.button.remove' | translate }}</button>\n </li>\n }\n </ul>\n }\n @if (applicableFlavors.length) {\n <h3>{{ 'yuv.shell.action.manage-flavors.applicable.headline' | translate }}</h3>\n <ul>\n @for (f of applicableFlavors; track $index) {\n <li>\n <yuv-flavor-chip [flavor]=\"f\" yuvListItem></yuv-flavor-chip>\n <button class=\"secondary\" (click)=\"applyFlavor(f)\">{{ 'yuv.shell.action.manage-flavors.applied.button.apply' | translate }}</button>\n </li>\n }\n </ul>\n }\n</main>\n<footer>\n <button class=\"secondary\" (click)=\"cancel()\">{{ 'yuv.shell.action.manage-flavors.button.cancel' | translate }}</button>\n</footer>\n", styles: [":host{display:flex;flex-flow:column;padding:var(--app-pane-padding)}:host header{flex:0 0 auto}:host header h2{padding:0;font-weight:400;font-size:var(--font-headline);margin:0 0 var(--app-pane-padding) 0}:host header p{max-width:42ch;line-height:1.3em}:host main{flex:1;overflow-y:auto}:host main yuv-flavor-chip{border-color:transparent;flex:1}:host main ul{padding:0;margin:0;list-style-type:none}:host main li{display:flex;gap:calc(var(--app-pane-padding) / 2);align-items:center;border:1px solid var(--panel-divider-color);margin-block-end:2px;padding:calc(var(--app-pane-padding) / 4)}:host main li button{padding:calc(var(--app-pane-padding) / 4) calc(var(--app-pane-padding) / 2)}:host footer{flex:0 0 auto;margin-block-start:var(--app-pane-padding)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "directive", type: ListItemDirective, selector: "[yuvListItem]", inputs: ["disabled", "active", "selected"] }, { kind: "component", type: FlavorChipComponent, selector: "yuv-flavor-chip", inputs: ["flavor", "enableRemove", "enableDescription"], outputs: ["flavorRemove"] }] }); }
|
|
453
|
+
}
|
|
454
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ManageFlavorsComponent, decorators: [{
|
|
455
|
+
type: Component,
|
|
456
|
+
args: [{ selector: 'yuv-manage-flavors', standalone: true, imports: [CommonModule, ListComponent, BusyOverlayDirective, TranslateModule, ListItemDirective, FlavorChipComponent], template: "<header>\n <h2>{{ 'yuv.shell.action.manage-flavors.title' | translate }}</h2>\n <p>{{ 'yuv.shell.action.manage-flavors.text' | translate }}</p>\n</header>\n<main [yuvBusyOverlay]=\"busy()\">\n @if (appliedFlavors.length) {\n <h3>{{ 'yuv.shell.action.manage-flavors.applied.headline' | translate }}</h3>\n <ul>\n @for (f of appliedFlavors; track $index) {\n <li>\n <yuv-flavor-chip [flavor]=\"f\" yuvListItem></yuv-flavor-chip>\n <button class=\"secondary\" (click)=\"removeFlavor(f)\">{{ 'yuv.shell.action.manage-flavors.applicable.button.remove' | translate }}</button>\n </li>\n }\n </ul>\n }\n @if (applicableFlavors.length) {\n <h3>{{ 'yuv.shell.action.manage-flavors.applicable.headline' | translate }}</h3>\n <ul>\n @for (f of applicableFlavors; track $index) {\n <li>\n <yuv-flavor-chip [flavor]=\"f\" yuvListItem></yuv-flavor-chip>\n <button class=\"secondary\" (click)=\"applyFlavor(f)\">{{ 'yuv.shell.action.manage-flavors.applied.button.apply' | translate }}</button>\n </li>\n }\n </ul>\n }\n</main>\n<footer>\n <button class=\"secondary\" (click)=\"cancel()\">{{ 'yuv.shell.action.manage-flavors.button.cancel' | translate }}</button>\n</footer>\n", styles: [":host{display:flex;flex-flow:column;padding:var(--app-pane-padding)}:host header{flex:0 0 auto}:host header h2{padding:0;font-weight:400;font-size:var(--font-headline);margin:0 0 var(--app-pane-padding) 0}:host header p{max-width:42ch;line-height:1.3em}:host main{flex:1;overflow-y:auto}:host main yuv-flavor-chip{border-color:transparent;flex:1}:host main ul{padding:0;margin:0;list-style-type:none}:host main li{display:flex;gap:calc(var(--app-pane-padding) / 2);align-items:center;border:1px solid var(--panel-divider-color);margin-block-end:2px;padding:calc(var(--app-pane-padding) / 4)}:host main li button{padding:calc(var(--app-pane-padding) / 4) calc(var(--app-pane-padding) / 2)}:host footer{flex:0 0 auto;margin-block-start:var(--app-pane-padding)}\n"] }]
|
|
457
|
+
}] });
|
|
458
|
+
|
|
459
|
+
class ManageFlavorsAction extends AbstractContextAction {
|
|
460
|
+
constructor() {
|
|
461
|
+
super(...arguments);
|
|
462
|
+
this.#shell = inject(ShellService);
|
|
463
|
+
this.#overlay = inject(YvcOverlayService);
|
|
464
|
+
this.translate = inject(TranslateService);
|
|
465
|
+
this.id = 'yuv.base.manage-flavor';
|
|
466
|
+
this.label = this.translate.instant('yuv.shell.action.manage-flavor.label');
|
|
467
|
+
this.description = this.translate.instant('yuv.shell.action.manage-flavor.description');
|
|
468
|
+
this.priority = 8;
|
|
469
|
+
this.icon = ACTION_ICON.manageFlavor;
|
|
470
|
+
this.group = 'common';
|
|
471
|
+
this.range = SelectionRange.SINGLE_SELECT;
|
|
472
|
+
this.supports = {
|
|
473
|
+
pattern: '*'
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
#shell;
|
|
477
|
+
#overlay;
|
|
478
|
+
isExecutable(items) {
|
|
479
|
+
const item = items[0];
|
|
480
|
+
return of(item && !!item.permissions?.writeIndexData && !!item.content && this.#shell.getApplicableObjectFlavors(item.content.mimeType).length > 0);
|
|
481
|
+
}
|
|
482
|
+
run(items) {
|
|
483
|
+
this.#overlay.open(ManageFlavorsComponent, items[0], {
|
|
484
|
+
width: '400px',
|
|
485
|
+
maxWidth: '90vw',
|
|
486
|
+
});
|
|
487
|
+
return of(true);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Generated bundle index. Do not edit.
|
|
493
|
+
*/
|
|
494
|
+
|
|
495
|
+
export { AppLogoComponent, ClientShellComponent, InertDirective, ManageFlavorsAction, clientShellRoutes };
|
|
496
|
+
//# sourceMappingURL=yuuvis-client-shell.mjs.map
|