@yuuvis/client-framework 3.8.3 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/yuuvis-client-framework-forms.mjs +7 -7
- package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-metadata-form.mjs +1 -1
- package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-form.mjs +10 -0
- package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-smart-search.mjs +16 -2
- package/fesm2022/yuuvis-client-framework-smart-search.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-tile-list.mjs +96 -51
- package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
- package/lib/assets/i18n/de.json +1 -0
- package/lib/assets/i18n/en.json +1 -0
- package/package.json +5 -5
- package/types/yuuvis-client-framework-tile-list.d.ts +35 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output, viewChild, ChangeDetectionStrategy, Component, forwardRef,
|
|
2
|
+
import { input, output, viewChild, ChangeDetectionStrategy, Component, forwardRef, inject, ViewContainerRef, effect, Directive, DestroyRef, ElementRef, ChangeDetectorRef, contentChild, viewChildren, computed, signal, linkedSignal, untracked, Injectable } from '@angular/core';
|
|
3
3
|
import * as i3 from '@angular/material/icon';
|
|
4
4
|
import { MatIcon, MatIconModule } from '@angular/material/icon';
|
|
5
5
|
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
|
|
@@ -20,6 +20,7 @@ import { YuvQueryListModule } from '@yuuvis/client-framework/query-list';
|
|
|
20
20
|
import { RendererDirective } from '@yuuvis/client-framework/renderer';
|
|
21
21
|
import { YmtMatIconRegistryService, YmtIconButtonDirective, YmtButtonDirective } from '@yuuvis/material';
|
|
22
22
|
import { switchMap, forkJoin, take } from 'rxjs';
|
|
23
|
+
import { ShellService } from '@yuuvis/client-shell-core';
|
|
23
24
|
import { NgClass } from '@angular/common';
|
|
24
25
|
import * as i1$1 from '@angular/material/button';
|
|
25
26
|
import { MatButtonModule } from '@angular/material/button';
|
|
@@ -57,61 +58,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
57
58
|
args: [{ selector: 'yuv-tile-actions-menu', imports: [MatMenu, MatIcon, MatMenuItem, MatMenuTrigger, MatTooltip, forwardRef(() => TileActionsMenuComponent)], providers: [{ provide: MAT_TOOLTIP_DEFAULT_OPTIONS, useValue: { position: 'right' } }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mat-menu #menuRef>\n <!-- @if (loading() && !actions().length) {\n <div class=\"loading-indicator\">\n <mat-spinner diameter=\"24\"></mat-spinner>\n </div>\n } -->\n @for (action of actions(); track action.id) {\n @if (action.children?.length) {\n <span [matTooltip]=\"action.description\" [matTooltipDisabled]=\"!action.description\">\n <button\n mat-menu-item\n [disabled]=\"!!action.disabled\"\n [attr.disabled]=\"!!action.disabled\"\n [matMenuTriggerFor]=\"subMenu.matMenu()\"\n >\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n <yuv-tile-actions-menu #subMenu [actions]=\"action.children!\" (itemSelect)=\"itemSelect.emit($event)\" />\n </span>\n } @else {\n <span [matTooltip]=\"action.description\" [matTooltipDisabled]=\"!action.description\">\n <button\n mat-menu-item\n [disabled]=\"!!action.disabled\"\n [attr.disabled]=\"!!action.disabled\"\n (click)=\"itemClicked($event, action)\"\n >\n @if (action.icon) {\n <mat-icon>{{ action.icon }}</mat-icon>\n }\n <span>{{ action.label }}</span>\n </button>\n </span>\n }\n }\n</mat-menu>\n", styles: [":host{display:block}.loading-indicator{display:flex;justify-content:center;padding:8px 16px}button[mat-menu-item][disabled]{opacity:var(--ymt-disabled-opacity, .38);cursor:default;pointer-events:none}\n"] }]
|
|
58
59
|
}], propDecorators: { actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: true }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], itemSelect: [{ type: i0.Output, args: ["itemSelect"] }], matMenu: [{ type: i0.ViewChild, args: ['menuRef', { isSignal: true }] }] } });
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Get tile extensions for a certain type
|
|
77
|
-
* @param typeId ID of the type to fetch extesion for (objectTypeID or secondaryObjectTypeID)
|
|
78
|
-
* @returns
|
|
79
|
-
*/
|
|
80
|
-
getTileExtension(typeId) {
|
|
81
|
-
return this._extensions[typeId];
|
|
82
|
-
}
|
|
83
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
84
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionService, providedIn: 'root' }); }
|
|
85
|
-
}
|
|
86
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionService, decorators: [{
|
|
87
|
-
type: Injectable,
|
|
88
|
-
args: [{
|
|
89
|
-
providedIn: 'root'
|
|
90
|
-
}]
|
|
91
|
-
}], ctorParameters: () => [] });
|
|
92
|
-
|
|
61
|
+
/**
|
|
62
|
+
* Structural directive that renders the {@link TileExtension} registered for a
|
|
63
|
+
* tile's object type or applied flavor, if any. Used internally by
|
|
64
|
+
* `yuv-tile-list` via `*yuvTileExtension` on each tile, passing the tile's
|
|
65
|
+
* `objectTypeId`, applied `flavorTypeId` and `instanceData`.
|
|
66
|
+
*
|
|
67
|
+
* On each input change it resolves an extension from {@link ShellService}: the
|
|
68
|
+
* applied flavor's SOT (`flavorTypeId`) takes precedence over the object type
|
|
69
|
+
* (`typeId`). When a match exists it renders the registered component and feeds
|
|
70
|
+
* it the tile's `data`; the component is only recreated when the resolved
|
|
71
|
+
* extension changes. When nothing matches, any previously rendered extension is
|
|
72
|
+
* cleared.
|
|
73
|
+
*
|
|
74
|
+
* Register extensions through {@link ShellService.registerTileExtension}.
|
|
75
|
+
*/
|
|
93
76
|
class TileExtensionDirective {
|
|
94
77
|
constructor() {
|
|
95
|
-
this.#
|
|
78
|
+
this.#shell = inject(ShellService);
|
|
96
79
|
this.#containerRef = inject(ViewContainerRef);
|
|
80
|
+
/** The tile's object type id, applied flavor SOT and instance data, see {@link TileExtensionDirectiveInput}. */
|
|
97
81
|
this.yuvTileExtension = input.required(...(ngDevMode ? [{ debugName: "yuvTileExtension" }] : /* istanbul ignore next */ []));
|
|
98
82
|
this.#yuvTileExtensionEffect = effect(() => {
|
|
99
83
|
const tile = this.yuvTileExtension();
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
84
|
+
const ext = (tile.flavorTypeId ? this.#shell.getTileExtension(tile.flavorTypeId) : undefined) ??
|
|
85
|
+
(tile.typeId ? this.#shell.getTileExtension(tile.typeId) : undefined);
|
|
86
|
+
if (ext)
|
|
87
|
+
this._render(ext, tile.data);
|
|
88
|
+
else
|
|
89
|
+
this._clear();
|
|
105
90
|
}, ...(ngDevMode ? [{ debugName: "#yuvTileExtensionEffect" }] : /* istanbul ignore next */ []));
|
|
106
91
|
}
|
|
107
|
-
#
|
|
92
|
+
#shell;
|
|
108
93
|
#containerRef;
|
|
94
|
+
#renderedCmp;
|
|
109
95
|
#yuvTileExtensionEffect;
|
|
110
96
|
_render(ext, data) {
|
|
111
|
-
|
|
97
|
+
// recreate only when the resolved extension component changes; otherwise just
|
|
98
|
+
// update its data input so toggling flavors doesn't needlessly rebuild it.
|
|
99
|
+
if (this.#renderedCmp !== ext.cmp) {
|
|
112
100
|
this.#containerRef.clear();
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
this.component = this.#containerRef.createComponent(ext.cmp);
|
|
102
|
+
this.#renderedCmp = ext.cmp;
|
|
103
|
+
}
|
|
104
|
+
this.component?.setInput('data', data);
|
|
105
|
+
}
|
|
106
|
+
_clear() {
|
|
107
|
+
if (this.#renderedCmp) {
|
|
108
|
+
this.#containerRef.clear();
|
|
109
|
+
this.component = undefined;
|
|
110
|
+
this.#renderedCmp = undefined;
|
|
111
|
+
}
|
|
115
112
|
}
|
|
116
113
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
117
114
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.12", type: TileExtensionDirective, isStandalone: true, selector: "[yuvTileExtension]", inputs: { yuvTileExtension: { classPropertyName: "yuvTileExtension", publicName: "yuvTileExtension", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
|
|
@@ -937,6 +934,9 @@ class TileListComponent {
|
|
|
937
934
|
this.appliedFlavor = this.appliedFlavor?.id === flavor.id ? undefined : flavor;
|
|
938
935
|
if (this.#rawResultItems)
|
|
939
936
|
this.items.set(this.#mapToTileData(this.#rawResultItems.map((i) => new DmsObject(i))));
|
|
937
|
+
// Re-run the inner query-list transformer so the *rendered* tiles pick up the
|
|
938
|
+
// flavor-driven config and `flavorTypeId` (the transformer reads `appliedFlavor`).
|
|
939
|
+
this.list().runTransformerAgain();
|
|
940
940
|
}
|
|
941
941
|
/**
|
|
942
942
|
* Applies per-index optimistic overrides to the displayed tile data.
|
|
@@ -1246,6 +1246,8 @@ class TileListComponent {
|
|
|
1246
1246
|
badges: objectConfig.badges,
|
|
1247
1247
|
instanceData: dmsObject.data,
|
|
1248
1248
|
dmsObject,
|
|
1249
|
+
// expose the applied flavor's SOT so a flavor-specific tile extension can be resolved
|
|
1250
|
+
flavorTypeId: this.appliedFlavor && sots.includes(this.appliedFlavor.sot) ? this.appliedFlavor.sot : undefined,
|
|
1249
1251
|
title: objectConfig.title
|
|
1250
1252
|
? this.#getResolvedObjectConfigItem(objectConfig.title.propertyName, dmsObject.data)
|
|
1251
1253
|
: { propertyName: '', value: '' }
|
|
@@ -1300,7 +1302,7 @@ class TileListComponent {
|
|
|
1300
1302
|
#closeMenuEffect;
|
|
1301
1303
|
#outsideClickCloseEffect;
|
|
1302
1304
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1303
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TileListComponent, isStandalone: true, selector: "yuv-tile-list", inputs: { bucket: { classPropertyName: "bucket", publicName: "bucket", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, flavor: { classPropertyName: "flavor", publicName: "flavor", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, preselect: { classPropertyName: "preselect", publicName: "preselect", isSignal: true, isRequired: false, transformFunction: null }, highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: false, transformFunction: null }, preventChangeUntil: { classPropertyName: "preventChangeUntil", publicName: "preventChangeUntil", isSignal: true, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null }, disableCustomContextMenu: { classPropertyName: "disableCustomContextMenu", publicName: "disableCustomContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", tileCopy: "tileCopy", tileCut: "tileCut", busy: "busy", queryResult: "queryResult", selectionChange: "selectionChange", itemDblClick: "itemDblClick", ctxMenu: "ctxMenu" }, host: { listeners: { "keydown.control.c": "onCopy($event)", "keydown.control.x": "onCut($event)" }, properties: { "class.dense": "dense()" } }, providers: [], queries: [{ propertyName: "menuComponent", first: true, predicate: TileActionsMenuComponent, descendants: true, isSignal: true }, { propertyName: "emptyContent", first: true, predicate: ["empty"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "menuTriggers", predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n [disabled]=\"a.disabled\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>\n <yuv-tile-badges [dmsObject]=\"item.dmsObject\" [badgeIds]=\"badgeIdsFor(item)\" [bucket]=\"bucket()\" />\n </ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: YuvListModule }, { kind: "component", type: i1.ListTileComponent, selector: "yuv-list-tile" }, { kind: "ngmodule", type: YuvQueryListModule }, { kind: "component", type: i2.QueryListComponent, selector: "yuv-query-list", inputs: ["query", "idProperty", "transformer", "preventChangeUntil", "autoSelect", "pageSize", "enableDragSelect", "multiselect", "selfHandleSelection", "includePermissions"], outputs: ["itemSelect", "dragSelectChange", "itemDoubleClick", "queryResult"] }, { kind: "directive", type: RendererDirective, selector: "[yuvRenderer]", inputs: ["yuvRenderer"] }, { kind: "directive", type: TileExtensionDirective, selector: "[yuvTileExtension]", inputs: ["yuvTileExtension"] }, { kind: "component", type: TileBadgesComponent, selector: "yuv-tile-badges", inputs: ["dmsObject", "badgeIds", "bucket"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1305
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: TileListComponent, isStandalone: true, selector: "yuv-tile-list", inputs: { bucket: { classPropertyName: "bucket", publicName: "bucket", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, dense: { classPropertyName: "dense", publicName: "dense", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, flavor: { classPropertyName: "flavor", publicName: "flavor", isSignal: true, isRequired: false, transformFunction: null }, query: { classPropertyName: "query", publicName: "query", isSignal: true, isRequired: false, transformFunction: null }, preselect: { classPropertyName: "preselect", publicName: "preselect", isSignal: true, isRequired: false, transformFunction: null }, highlights: { classPropertyName: "highlights", publicName: "highlights", isSignal: true, isRequired: false, transformFunction: null }, preventChangeUntil: { classPropertyName: "preventChangeUntil", publicName: "preventChangeUntil", isSignal: true, isRequired: false, transformFunction: null }, autoSelect: { classPropertyName: "autoSelect", publicName: "autoSelect", isSignal: true, isRequired: false, transformFunction: null }, disableCustomContextMenu: { classPropertyName: "disableCustomContextMenu", publicName: "disableCustomContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelect: "itemSelect", tileCopy: "tileCopy", tileCut: "tileCut", busy: "busy", queryResult: "queryResult", selectionChange: "selectionChange", itemDblClick: "itemDblClick", ctxMenu: "ctxMenu" }, host: { listeners: { "keydown.control.c": "onCopy($event)", "keydown.control.x": "onCut($event)" }, properties: { "class.dense": "dense()" } }, providers: [], queries: [{ propertyName: "menuComponent", first: true, predicate: TileActionsMenuComponent, descendants: true, isSignal: true }, { propertyName: "emptyContent", first: true, predicate: ["empty"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "menuTriggers", predicate: MatMenuTrigger, descendants: true, isSignal: true }], ngImport: i0, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n [disabled]=\"a.disabled\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, flavorTypeId: item.flavorTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>\n <yuv-tile-badges [dmsObject]=\"item.dmsObject\" [badgeIds]=\"badgeIdsFor(item)\" [bucket]=\"bucket()\" />\n </ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: YuvListModule }, { kind: "component", type: i1.ListTileComponent, selector: "yuv-list-tile" }, { kind: "ngmodule", type: YuvQueryListModule }, { kind: "component", type: i2.QueryListComponent, selector: "yuv-query-list", inputs: ["query", "idProperty", "transformer", "preventChangeUntil", "autoSelect", "pageSize", "enableDragSelect", "multiselect", "selfHandleSelection", "includePermissions"], outputs: ["itemSelect", "dragSelectChange", "itemDoubleClick", "queryResult"] }, { kind: "directive", type: RendererDirective, selector: "[yuvRenderer]", inputs: ["yuvRenderer"] }, { kind: "directive", type: TileExtensionDirective, selector: "[yuvTileExtension]", inputs: ["yuvTileExtension"] }, { kind: "component", type: TileBadgesComponent, selector: "yuv-tile-badges", inputs: ["dmsObject", "badgeIds", "bucket"] }, { kind: "directive", type: YmtIconButtonDirective, selector: "button[ymtIconButton],button[ymt-icon-button],a[ymtIconButton],a[ymt-icon-button]", inputs: ["disabled", "disableRipple", "aria-disabled", "disabledInteractive", "icon-button-size"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1304
1306
|
}
|
|
1305
1307
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileListComponent, decorators: [{
|
|
1306
1308
|
type: Component,
|
|
@@ -1319,7 +1321,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1319
1321
|
'[class.dense]': 'dense()',
|
|
1320
1322
|
'(keydown.control.c)': 'onCopy($event)',
|
|
1321
1323
|
'(keydown.control.x)': 'onCut($event)'
|
|
1322
|
-
}, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n [disabled]=\"a.disabled\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>\n <yuv-tile-badges [dmsObject]=\"item.dmsObject\" [badgeIds]=\"badgeIdsFor(item)\" [bucket]=\"bucket()\" />\n </ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"] }]
|
|
1324
|
+
}, template: "<yuv-query-list\n #list\n [query]=\"query()\"\n [transformer]=\"transformer\"\n idProperty=\"id\"\n [preventChangeUntil]=\"preventChangeUntil()\"\n [autoSelect]=\"autoSelect()\"\n [pageSize]=\"pageSize()\"\n [multiselect]=\"multiselect()\"\n (itemDoubleClick)=\"onItemDoubleClick($event)\"\n (itemSelect)=\"onListItemsSelect($event)\"\n (queryResult)=\"onQueryResult($event)\"\n (dragSelectChange)=\"onDragSelectChange($event)\"\n>\n <ng-template #yuvQueryListItem let-item let-index=\"index\">\n <yuv-list-tile [class.dense]=\"dense()\" [style]=\"highlightStyles()[item.id]\" (contextmenu)=\"contextMenuHandler($event, index)\">\n <ng-template #iconSlot><ng-container *yuvRenderer=\"item.icon\" /></ng-template>\n <ng-template #titleSlot><ng-container *yuvRenderer=\"item.title\" /></ng-template>\n <ng-template #descriptionSlot><ng-container *yuvRenderer=\"item.description\" /></ng-template>\n <ng-template #metaSlot><ng-container *yuvRenderer=\"item.meta\" /></ng-template>\n <ng-template #asideSlot><ng-container *yuvRenderer=\"item.aside\" /></ng-template>\n <ng-template #actionsSlot>\n @for (a of item.actions; track a.id) {\n <button\n ymt-icon-button\n [matTooltip]=\"a.label\"\n icon-button-size=\"small\"\n [disabled]=\"a.disabled\"\n (click)=\"executeAction(item, a, $event)\"\n >\n <mat-icon inert=\"true\">{{ a.icon }}</mat-icon>\n </button>\n }\n\n @if (menu()) {\n <button\n ymt-icon-button\n icon-button-size=\"small\"\n (click)=\"menuItemClicked(item, $event)\"\n [matTooltip]=\"'yuv.tile-list.item.actions-menu.button.tooltip' | translate\"\n [matMenuTriggerFor]=\"menu()\"\n >\n <mat-icon inert=\"true\">more_vert</mat-icon>\n </button>\n }\n <ng-content select=\"yuv-tile-actions-menu, [yuv-tile-actions-menu]\" />\n </ng-template>\n <ng-template #extensionSlot>\n <ng-container *yuvTileExtension=\"{ typeId: item.objectTypeId, flavorTypeId: item.flavorTypeId, data: item.instanceData }\" />\n </ng-template>\n <ng-template #badgesSlot>\n <yuv-tile-badges [dmsObject]=\"item.dmsObject\" [badgeIds]=\"badgeIdsFor(item)\" [bucket]=\"bucket()\" />\n </ng-template>\n </yuv-list-tile>\n </ng-template>\n\n <ng-template #yuvQueryListEmpty>\n <div class=\"empty-list\">\n @let searchExe = searchExecuted();\n @if (searchExe && emptyContent()) {\n <ng-content />\n }\n </div>\n </ng-template>\n <div class=\"offset\" (click)=\"clearSelection()\"></div>\n</yuv-query-list>\n", styles: [":host{--paging-background: var(--ymt-surface);display:flex;flex-direction:column}:host yuv-query-list{flex:1;overflow-y:auto;display:flex;flex-flow:column;height:100%}:host yuv-query-list .offset{flex:1 1 auto}:host .empty-list{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}\n"] }]
|
|
1323
1325
|
}], ctorParameters: () => [], propDecorators: { menuComponent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TileActionsMenuComponent), { isSignal: true }] }], emptyContent: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], list: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }], menuTriggers: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => MatMenuTrigger), { isSignal: true }] }], bucket: [{ type: i0.Input, args: [{ isSignal: true, alias: "bucket", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], multiselect: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiselect", required: false }] }], dense: [{ type: i0.Input, args: [{ isSignal: true, alias: "dense", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], flavor: [{ type: i0.Input, args: [{ isSignal: true, alias: "flavor", required: false }] }], query: [{ type: i0.Input, args: [{ isSignal: true, alias: "query", required: false }] }], preselect: [{ type: i0.Input, args: [{ isSignal: true, alias: "preselect", required: false }] }], highlights: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlights", required: false }] }], preventChangeUntil: [{ type: i0.Input, args: [{ isSignal: true, alias: "preventChangeUntil", required: false }] }], autoSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoSelect", required: false }] }], disableCustomContextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableCustomContextMenu", required: false }] }], itemSelect: [{ type: i0.Output, args: ["itemSelect"] }], tileCopy: [{ type: i0.Output, args: ["tileCopy"] }], tileCut: [{ type: i0.Output, args: ["tileCut"] }], busy: [{ type: i0.Output, args: ["busy"] }], queryResult: [{ type: i0.Output, args: ["queryResult"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], itemDblClick: [{ type: i0.Output, args: ["itemDblClick"] }], ctxMenu: [{ type: i0.Output, args: ["ctxMenu"] }] } });
|
|
1324
1326
|
|
|
1325
1327
|
class ActionSelectComponent {
|
|
@@ -1798,17 +1800,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1798
1800
|
args: [{ selector: 'yuv-tile-config-trigger', standalone: true, imports: [TileConfigComponent, TranslatePipe$1, YmtIconButtonDirective, MatButtonModule, MatTooltipModule, MatIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n ymt-icon-button\n [icon-button-size]=\"small() ? 'small' : 'medium'\"\n class=\"settings icon\"\n (click)=\"openTileConfigOverlay()\"\n [matTooltip]=\"'yuv.tile-config.trigger.tooltip' | translate\"\n>\n <mat-icon>settings</mat-icon>\n</button>\n\n<ng-template #tplTileConfig>\n <yuv-tile-config\n (save)=\"onObjectConfigSave()\"\n (canceled)=\"onObjectConfigCancel()\"\n [bucket]=\"bucket() || undefined\"\n [bucketLabel]=\"bucketLabel()\"\n [configTypes]=\"options()?.configTypes\"\n [configFlavors]=\"options()?.configFlavors || []\"\n />\n</ng-template>\n" }]
|
|
1799
1801
|
}], propDecorators: { tplTileConfig: [{ type: i0.ViewChild, args: ['tplTileConfig', { isSignal: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], bucket: [{ type: i0.Input, args: [{ isSignal: true, alias: "bucket", required: false }] }], bucketLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "bucketLabel", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], small: [{ type: i0.Input, args: [{ isSignal: true, alias: "small", required: false }] }] } });
|
|
1800
1802
|
|
|
1803
|
+
/**
|
|
1804
|
+
* Reference {@link TileExtensionComponent} implementation: shows an attachment
|
|
1805
|
+
* count and clip icon on email tiles. Register it for the email object type via
|
|
1806
|
+
* `ShellService.registerTileExtension({ typeId: 'appSystemmail:email', cmp: EmailTileExtensionComponent })`.
|
|
1807
|
+
*/
|
|
1801
1808
|
class EmailTileExtensionComponent {
|
|
1802
1809
|
constructor() {
|
|
1803
1810
|
this.data = input.required(...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
1804
1811
|
this.attachments = computed(() => this.data()['appSystemmail:attachments'] || [], ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
|
|
1805
1812
|
this.hasAttachements = computed(() => !!this.data()['appSystemmail:attachmentCount'], ...(ngDevMode ? [{ debugName: "hasAttachements" }] : /* istanbul ignore next */ []));
|
|
1806
1813
|
}
|
|
1807
|
-
onClick(a, evt) {
|
|
1808
|
-
evt.preventDefault();
|
|
1809
|
-
evt.stopPropagation();
|
|
1810
|
-
alert(`You clicked '${a}' my friend.`);
|
|
1811
|
-
}
|
|
1812
1814
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EmailTileExtensionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1813
1815
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: EmailTileExtensionComponent, isStandalone: true, selector: "yuv-email-tile-extension", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "class.attachments": "hasAttachements()" } }, ngImport: i0, template: `
|
|
1814
1816
|
@if (hasAttachements()) {
|
|
@@ -1837,6 +1839,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1837
1839
|
}, styles: [":host{display:flex;justify-content:end;margin-top:.5rem}:host .icon{height:1rem}\n"] }]
|
|
1838
1840
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }] } });
|
|
1839
1841
|
|
|
1842
|
+
/**
|
|
1843
|
+
* @deprecated Use {@link ShellService} instead. Tile extension registration was
|
|
1844
|
+
* consolidated into `ShellService` (see `registerTileExtension`,
|
|
1845
|
+
* `getRegisteredTileExtensions`, `getTileExtension`). This service now only
|
|
1846
|
+
* delegates to `ShellService` so existing callers keep working against a single
|
|
1847
|
+
* registry. It is kept temporarily for backwards compatibility and will be
|
|
1848
|
+
* removed in a future release — migrate consumers to `ShellService`.
|
|
1849
|
+
*/
|
|
1850
|
+
class TileExtensionService {
|
|
1851
|
+
constructor() {
|
|
1852
|
+
this.shellService = inject(ShellService);
|
|
1853
|
+
}
|
|
1854
|
+
/**
|
|
1855
|
+
* @deprecated Use {@link ShellService.registerTileExtension} instead.
|
|
1856
|
+
*/
|
|
1857
|
+
registerTileExtension(ext) {
|
|
1858
|
+
this.shellService.registerTileExtension(ext);
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* @deprecated Use {@link ShellService.getTileExtension} instead.
|
|
1862
|
+
*/
|
|
1863
|
+
hasTileExtension(objectTypeId) {
|
|
1864
|
+
return !!this.shellService.getTileExtension(objectTypeId);
|
|
1865
|
+
}
|
|
1866
|
+
/**
|
|
1867
|
+
* Get tile extensions for a certain type
|
|
1868
|
+
* @param typeId ID of the type to fetch extesion for (objectTypeID or secondaryObjectTypeID)
|
|
1869
|
+
* @returns
|
|
1870
|
+
* @deprecated Use {@link ShellService.getTileExtension} instead.
|
|
1871
|
+
*/
|
|
1872
|
+
getTileExtension(typeId) {
|
|
1873
|
+
return this.shellService.getTileExtension(typeId);
|
|
1874
|
+
}
|
|
1875
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1876
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionService, providedIn: 'root' }); }
|
|
1877
|
+
}
|
|
1878
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TileExtensionService, decorators: [{
|
|
1879
|
+
type: Injectable,
|
|
1880
|
+
args: [{
|
|
1881
|
+
providedIn: 'root'
|
|
1882
|
+
}]
|
|
1883
|
+
}] });
|
|
1884
|
+
|
|
1840
1885
|
/**
|
|
1841
1886
|
* Generated bundle index. Do not edit.
|
|
1842
1887
|
*/
|