@masterteam/components 0.0.150 → 0.0.152
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/assets/common.css +1 -1
- package/assets/i18n/ar.json +5 -0
- package/assets/i18n/en.json +5 -0
- package/fesm2022/masterteam-components-business-fields.mjs +1 -1
- package/fesm2022/masterteam-components-business-fields.mjs.map +1 -1
- package/fesm2022/masterteam-components-entities.mjs +47 -4
- package/fesm2022/masterteam-components-entities.mjs.map +1 -1
- package/fesm2022/masterteam-components-table.mjs +1015 -196
- package/fesm2022/masterteam-components-table.mjs.map +1 -1
- package/package.json +1 -1
- package/types/masterteam-components-entities.d.ts +30 -2
- package/types/masterteam-components-table.d.ts +332 -32
|
@@ -1,33 +1,120 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, output,
|
|
2
|
+
import { input, booleanAttribute, output, viewChild, computed, ChangeDetectionStrategy, Component, model, signal, forwardRef, Injectable, inject, contentChild, effect } from '@angular/core';
|
|
3
3
|
import { NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import { Card } from '@masterteam/components/card';
|
|
5
|
-
import * as i1 from '@angular/forms';
|
|
5
|
+
import * as i1$1 from '@angular/forms';
|
|
6
6
|
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
|
+
import * as i2 from '@jsverse/transloco';
|
|
8
|
+
import { TranslocoModule } from '@jsverse/transloco';
|
|
7
9
|
import { Button } from '@masterteam/components/button';
|
|
10
|
+
import { Tabs } from '@masterteam/components/tabs';
|
|
11
|
+
import { TextField } from '@masterteam/components/text-field';
|
|
12
|
+
import { Avatar } from '@masterteam/components/avatar';
|
|
13
|
+
import { Icon } from '@masterteam/icons';
|
|
14
|
+
import * as i1 from 'primeng/tieredmenu';
|
|
15
|
+
import { TieredMenuModule } from 'primeng/tieredmenu';
|
|
16
|
+
import * as i1$2 from 'primeng/popover';
|
|
17
|
+
import { PopoverModule } from 'primeng/popover';
|
|
8
18
|
import { DateField } from '@masterteam/components/date-field';
|
|
9
19
|
import { SelectField } from '@masterteam/components/select-field';
|
|
10
|
-
import { TextField } from '@masterteam/components/text-field';
|
|
11
20
|
import { UserSearchField } from '@masterteam/components/user-search-field';
|
|
12
|
-
import * as
|
|
13
|
-
import { TranslocoModule } from '@jsverse/transloco';
|
|
14
|
-
import * as i2 from 'primeng/popover';
|
|
15
|
-
import { PopoverModule } from 'primeng/popover';
|
|
21
|
+
import * as XLSX from 'xlsx';
|
|
16
22
|
import { ToggleField } from '@masterteam/components/toggle-field';
|
|
17
23
|
import { Paginator } from '@masterteam/components/paginator';
|
|
18
24
|
import { CheckboxField } from '@masterteam/components/checkbox-field';
|
|
19
|
-
import * as i1$
|
|
25
|
+
import * as i1$3 from 'primeng/table';
|
|
20
26
|
import { TableModule } from 'primeng/table';
|
|
21
|
-
import
|
|
22
|
-
import * as i3$1 from 'primeng/skeleton';
|
|
27
|
+
import * as i3 from 'primeng/skeleton';
|
|
23
28
|
import { SkeletonModule } from 'primeng/skeleton';
|
|
24
29
|
import * as i4 from 'primeng/progressbar';
|
|
25
30
|
import { ProgressBarModule } from 'primeng/progressbar';
|
|
26
31
|
import { MTDateFormatPipe } from '@masterteam/components';
|
|
27
32
|
import { ConfirmationService } from '@masterteam/components/confirmation';
|
|
28
33
|
import { EntityPreview } from '@masterteam/components/entities';
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Top-right `⋯` menu. Uses PrimeNG TieredMenu (popup mode) so submenu
|
|
37
|
+
* cascading, keyboard navigation, and outside-click-to-close come for free.
|
|
38
|
+
* Item rendering is overridden via the `#item` template so each row shows
|
|
39
|
+
* either a flat tone chip (main actions) or an `mt-avatar` (column picker).
|
|
40
|
+
*/
|
|
41
|
+
class TableActionsMenu {
|
|
42
|
+
exportable = input(false, { ...(ngDevMode ? { debugName: "exportable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
43
|
+
printable = input(false, { ...(ngDevMode ? { debugName: "printable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
44
|
+
groupable = input(false, { ...(ngDevMode ? { debugName: "groupable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
45
|
+
groupColumns = input([], ...(ngDevMode ? [{ debugName: "groupColumns" }] : /* istanbul ignore next */ []));
|
|
46
|
+
activeGroup = input(null, ...(ngDevMode ? [{ debugName: "activeGroup" }] : /* istanbul ignore next */ []));
|
|
47
|
+
exportRequested = output();
|
|
48
|
+
printRequested = output();
|
|
49
|
+
groupChange = output();
|
|
50
|
+
menu = viewChild('menu', ...(ngDevMode ? [{ debugName: "menu" }] : /* istanbul ignore next */ []));
|
|
51
|
+
/** Tailwind classes for flat tone chips, keyed by `iconTone`. */
|
|
52
|
+
toneClass = {
|
|
53
|
+
emerald: 'bg-emerald-50 text-emerald-700',
|
|
54
|
+
sky: 'bg-sky-50 text-sky-700',
|
|
55
|
+
indigo: 'bg-indigo-50 text-indigo-700',
|
|
56
|
+
secondary: 'bg-gray-100 text-gray-700',
|
|
57
|
+
};
|
|
58
|
+
items = computed(() => {
|
|
59
|
+
const items = [];
|
|
60
|
+
if (this.exportable()) {
|
|
61
|
+
items.push({
|
|
62
|
+
labelKey: 'components.table.exportExcel',
|
|
63
|
+
iconKey: 'file.file-download-02',
|
|
64
|
+
iconTone: 'emerald',
|
|
65
|
+
command: () => this.exportRequested.emit(),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (this.printable()) {
|
|
69
|
+
items.push({
|
|
70
|
+
labelKey: 'components.table.printPdf',
|
|
71
|
+
iconKey: 'media.printer',
|
|
72
|
+
iconTone: 'sky',
|
|
73
|
+
command: () => this.printRequested.emit(),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (this.groupable()) {
|
|
77
|
+
const activeKey = this.activeGroup();
|
|
78
|
+
const activeLabel = this.groupColumns().find((c) => c.key === activeKey)?.label ??
|
|
79
|
+
activeKey ??
|
|
80
|
+
null;
|
|
81
|
+
items.push({
|
|
82
|
+
labelKey: 'components.table.groupBy',
|
|
83
|
+
iconKey: 'layout.columns-03',
|
|
84
|
+
iconTone: 'indigo',
|
|
85
|
+
badge: activeLabel ?? undefined,
|
|
86
|
+
items: [
|
|
87
|
+
{
|
|
88
|
+
labelKey: 'components.table.noGrouping',
|
|
89
|
+
iconKey: 'general.x-close',
|
|
90
|
+
iconTone: 'secondary',
|
|
91
|
+
useAvatar: true,
|
|
92
|
+
selected: !activeKey,
|
|
93
|
+
command: () => this.groupChange.emit(null),
|
|
94
|
+
},
|
|
95
|
+
...this.groupColumns().map((col) => ({
|
|
96
|
+
rawLabel: col.label,
|
|
97
|
+
iconKey: 'layout.columns-03',
|
|
98
|
+
iconTone: 'secondary',
|
|
99
|
+
useAvatar: true,
|
|
100
|
+
selected: activeKey === col.key,
|
|
101
|
+
command: () => this.groupChange.emit(col.key),
|
|
102
|
+
})),
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return items;
|
|
107
|
+
}, ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
108
|
+
toggle(event) {
|
|
109
|
+
this.menu()?.toggle(event);
|
|
110
|
+
}
|
|
111
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableActionsMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
112
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TableActionsMenu, isStandalone: true, selector: "mt-table-actions-menu", inputs: { exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, printable: { classPropertyName: "printable", publicName: "printable", isSignal: true, isRequired: false, transformFunction: null }, groupable: { classPropertyName: "groupable", publicName: "groupable", isSignal: true, isRequired: false, transformFunction: null }, groupColumns: { classPropertyName: "groupColumns", publicName: "groupColumns", isSignal: true, isRequired: false, transformFunction: null }, activeGroup: { classPropertyName: "activeGroup", publicName: "activeGroup", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { exportRequested: "exportRequested", printRequested: "printRequested", groupChange: "groupChange" }, viewQueries: [{ propertyName: "menu", first: true, predicate: ["menu"], descendants: true, isSignal: true }], ngImport: i0, template: "<mt-button\n (click)=\"toggle($event)\"\n icon=\"general.dots-horizontal\"\n severity=\"secondary\"\n variant=\"outlined\"\n size=\"small\"\n [tooltip]=\"'components.table.actions' | transloco\"\n/>\n\n<p-tieredMenu\n #menu\n [model]=\"items()\"\n [popup]=\"true\"\n appendTo=\"body\"\n styleClass=\"mt-table-actions-menu\"\n>\n <ng-template #item let-item let-hasSubmenu=\"hasSubmenu\">\n <button\n type=\"button\"\n class=\"flex items-center gap-2.5 w-full px-2.5 py-2 text-sm cursor-pointer text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-surface-700 transition-colors\"\n [class.bg-primary-50]=\"item.selected\"\n [class.dark:bg-primary-950]=\"item.selected\"\n [class.text-primary-700]=\"item.selected\"\n >\n @if (item.iconKey) {\n @if (item.useAvatar) {\n <mt-avatar [icon]=\"item.iconKey\" shape=\"circle\" />\n } @else {\n <span\n class=\"inline-flex items-center justify-center w-7 h-7 rounded-full shrink-0\"\n [class]=\"toneClass[item.iconTone ?? 'secondary']\"\n >\n <mt-icon [icon]=\"item.iconKey\" class=\"text-sm\" />\n </span>\n }\n }\n <span class=\"flex-1 text-start truncate\">\n @if (item.labelKey) {\n {{ item.labelKey | transloco }}\n } @else {\n {{ item.rawLabel }}\n }\n </span>\n @if (item.badge) {\n <span\n class=\"text-xs px-1.5 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300 shrink-0\"\n >\n {{ item.badge }}\n </span>\n }\n @if (hasSubmenu) {\n <mt-icon\n icon=\"arrow.chevron-right\"\n class=\"text-xs text-gray-400 shrink-0\"\n />\n }\n </button>\n </ng-template>\n</p-tieredMenu>\n", dependencies: [{ kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "ngmodule", type: TieredMenuModule }, { kind: "component", type: i1.TieredMenu, selector: "p-tieredMenu, p-tieredmenu, p-tiered-menu", inputs: ["model", "popup", "style", "styleClass", "breakpoint", "autoZIndex", "baseZIndex", "autoDisplay", "showTransitionOptions", "hideTransitionOptions", "id", "ariaLabel", "ariaLabelledBy", "disabled", "tabindex", "appendTo", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
113
|
+
}
|
|
114
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableActionsMenu, decorators: [{
|
|
115
|
+
type: Component,
|
|
116
|
+
args: [{ selector: 'mt-table-actions-menu', standalone: true, imports: [Avatar, Button, Icon, TieredMenuModule, TranslocoModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mt-button\n (click)=\"toggle($event)\"\n icon=\"general.dots-horizontal\"\n severity=\"secondary\"\n variant=\"outlined\"\n size=\"small\"\n [tooltip]=\"'components.table.actions' | transloco\"\n/>\n\n<p-tieredMenu\n #menu\n [model]=\"items()\"\n [popup]=\"true\"\n appendTo=\"body\"\n styleClass=\"mt-table-actions-menu\"\n>\n <ng-template #item let-item let-hasSubmenu=\"hasSubmenu\">\n <button\n type=\"button\"\n class=\"flex items-center gap-2.5 w-full px-2.5 py-2 text-sm cursor-pointer text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-surface-700 transition-colors\"\n [class.bg-primary-50]=\"item.selected\"\n [class.dark:bg-primary-950]=\"item.selected\"\n [class.text-primary-700]=\"item.selected\"\n >\n @if (item.iconKey) {\n @if (item.useAvatar) {\n <mt-avatar [icon]=\"item.iconKey\" shape=\"circle\" />\n } @else {\n <span\n class=\"inline-flex items-center justify-center w-7 h-7 rounded-full shrink-0\"\n [class]=\"toneClass[item.iconTone ?? 'secondary']\"\n >\n <mt-icon [icon]=\"item.iconKey\" class=\"text-sm\" />\n </span>\n }\n }\n <span class=\"flex-1 text-start truncate\">\n @if (item.labelKey) {\n {{ item.labelKey | transloco }}\n } @else {\n {{ item.rawLabel }}\n }\n </span>\n @if (item.badge) {\n <span\n class=\"text-xs px-1.5 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300 shrink-0\"\n >\n {{ item.badge }}\n </span>\n }\n @if (hasSubmenu) {\n <mt-icon\n icon=\"arrow.chevron-right\"\n class=\"text-xs text-gray-400 shrink-0\"\n />\n }\n </button>\n </ng-template>\n</p-tieredMenu>\n" }]
|
|
117
|
+
}], propDecorators: { exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], printable: [{ type: i0.Input, args: [{ isSignal: true, alias: "printable", required: false }] }], groupable: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupable", required: false }] }], groupColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupColumns", required: false }] }], activeGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeGroup", required: false }] }], exportRequested: [{ type: i0.Output, args: ["exportRequested"] }], printRequested: [{ type: i0.Output, args: ["printRequested"] }], groupChange: [{ type: i0.Output, args: ["groupChange"] }], menu: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }] } });
|
|
31
118
|
|
|
32
119
|
class TableValueResolver {
|
|
33
120
|
static ALL_ENTITY_VIEW_TYPES = [
|
|
@@ -107,6 +194,241 @@ class TableValueResolver {
|
|
|
107
194
|
return 'text';
|
|
108
195
|
}
|
|
109
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* Returns a column with its filterConfig normalized for rendering:
|
|
199
|
+
* - `type` is resolved via `getColumnFilterType`
|
|
200
|
+
* - `options` for `select` filters are auto-generated from `data` when not provided
|
|
201
|
+
*
|
|
202
|
+
* Used by both popover and per-column filter modes so option-building stays in one place.
|
|
203
|
+
*/
|
|
204
|
+
static buildFilterableColumn(column, data) {
|
|
205
|
+
const sampleRow = data[0];
|
|
206
|
+
const filterType = TableValueResolver.getColumnFilterType(column, sampleRow);
|
|
207
|
+
if (filterType === 'select' && !column.filterConfig?.options?.length) {
|
|
208
|
+
const uniqueOptions = Array.from(data.reduce((options, row) => {
|
|
209
|
+
const value = TableValueResolver.getColumnFilterValue(row, column);
|
|
210
|
+
if (value === null || value === undefined || value === '') {
|
|
211
|
+
return options;
|
|
212
|
+
}
|
|
213
|
+
const optionKey = `${typeof value}:${String(value)}`;
|
|
214
|
+
if (!options.has(optionKey)) {
|
|
215
|
+
options.set(optionKey, {
|
|
216
|
+
label: String(value),
|
|
217
|
+
value,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return options;
|
|
221
|
+
}, new Map()))
|
|
222
|
+
.map(([, option]) => option)
|
|
223
|
+
.sort((a, b) => a.label.localeCompare(b.label));
|
|
224
|
+
return {
|
|
225
|
+
...column,
|
|
226
|
+
filterConfig: {
|
|
227
|
+
...column.filterConfig,
|
|
228
|
+
type: filterType,
|
|
229
|
+
options: uniqueOptions,
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
...column,
|
|
235
|
+
filterConfig: {
|
|
236
|
+
...column.filterConfig,
|
|
237
|
+
type: filterType ?? column.filterConfig?.type ?? 'text',
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Returns true when `item` passes the filter for `key`. Pure function — callers
|
|
243
|
+
* pass `column` so the resolver can apply type-aware normalisation (entity,
|
|
244
|
+
* status, user, date, boolean). Shared by `mt-table` row-filtering and
|
|
245
|
+
* `client-list-cards-view` card-filtering.
|
|
246
|
+
*/
|
|
247
|
+
static matchesFilter(item, key, filterValue, column) {
|
|
248
|
+
if (filterValue === null ||
|
|
249
|
+
filterValue === undefined ||
|
|
250
|
+
filterValue === '') {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
const itemValue = TableValueResolver.getProperty(item, key);
|
|
254
|
+
const normalizedFilterValue = column
|
|
255
|
+
? TableValueResolver.getColumnFilterValue(item, column)
|
|
256
|
+
: TableValueResolver.resolveDisplayValue(itemValue);
|
|
257
|
+
const filterType = column
|
|
258
|
+
? TableValueResolver.getColumnFilterType(column, item)
|
|
259
|
+
: null;
|
|
260
|
+
if (typeof filterValue === 'object' && filterValue !== null) {
|
|
261
|
+
const objectFilter = filterValue;
|
|
262
|
+
if (objectFilter.from || objectFilter.to) {
|
|
263
|
+
const itemDateValue = filterType === 'date'
|
|
264
|
+
? typeof normalizedFilterValue === 'number'
|
|
265
|
+
? normalizedFilterValue
|
|
266
|
+
: null
|
|
267
|
+
: itemValue instanceof Date
|
|
268
|
+
? itemValue.getTime()
|
|
269
|
+
: new Date(String(itemValue)).getTime();
|
|
270
|
+
if (itemDateValue === null ||
|
|
271
|
+
itemDateValue === undefined ||
|
|
272
|
+
Number.isNaN(itemDateValue)) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
if (objectFilter.from &&
|
|
276
|
+
itemDateValue < new Date(objectFilter.from).getTime()) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
if (objectFilter.to &&
|
|
280
|
+
itemDateValue > new Date(objectFilter.to).getTime()) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
if (objectFilter.userName) {
|
|
286
|
+
const normalizedItemUser = itemValue;
|
|
287
|
+
if (!normalizedItemUser)
|
|
288
|
+
return false;
|
|
289
|
+
return (normalizedItemUser['id'] === objectFilter.id ||
|
|
290
|
+
normalizedItemUser['userName'] === objectFilter.userName ||
|
|
291
|
+
normalizedItemUser['displayName'] === objectFilter.displayName);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (typeof filterValue === 'boolean') {
|
|
295
|
+
return normalizedFilterValue === filterValue;
|
|
296
|
+
}
|
|
297
|
+
if (typeof normalizedFilterValue === 'string' ||
|
|
298
|
+
typeof normalizedFilterValue === 'number') {
|
|
299
|
+
return String(normalizedFilterValue)
|
|
300
|
+
.toLowerCase()
|
|
301
|
+
.includes(String(filterValue).toLowerCase());
|
|
302
|
+
}
|
|
303
|
+
return normalizedFilterValue === filterValue;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Applies every entry of `filters` against `item` — used by cards view and
|
|
307
|
+
* anywhere else that consumes the same filter shape as mt-table.
|
|
308
|
+
*/
|
|
309
|
+
static matchesAllFilters(item, filters, columns) {
|
|
310
|
+
return Object.keys(filters).every((key) => {
|
|
311
|
+
if (key === 'generalSearch')
|
|
312
|
+
return true;
|
|
313
|
+
const column = columns.find((col) => col.key === key);
|
|
314
|
+
return TableValueResolver.matchesFilter(item, key, filters[key], column);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* True when a filter slot holds a meaningful value (scalar, text, date-range bounds,
|
|
319
|
+
* or user lookup). Shared by popover and per-column modes to compute active counts.
|
|
320
|
+
*/
|
|
321
|
+
static hasFilterValue(value) {
|
|
322
|
+
if (value === null || value === undefined || value === '') {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
if (typeof value === 'object') {
|
|
326
|
+
const filterValue = value;
|
|
327
|
+
return (filterValue.from != null ||
|
|
328
|
+
filterValue.to != null ||
|
|
329
|
+
filterValue.value != null ||
|
|
330
|
+
filterValue.userName != null ||
|
|
331
|
+
filterValue.id != null);
|
|
332
|
+
}
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Produces the filter payload a cell-click should apply for `column`.
|
|
337
|
+
* Returns null when the cell type is not click-filterable.
|
|
338
|
+
*
|
|
339
|
+
* Shapes match `Table.matchesFilter` branches:
|
|
340
|
+
* - user / entity(User) → `{ id, userName, displayName }`
|
|
341
|
+
* - status / entity(Status|Lookup) → scalar display string
|
|
342
|
+
* - boolean → boolean
|
|
343
|
+
*/
|
|
344
|
+
static buildClickFilterValue(row, column) {
|
|
345
|
+
const cellValue = TableValueResolver.getProperty(row, column.key);
|
|
346
|
+
if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
const filterType = TableValueResolver.getColumnFilterType(column, row);
|
|
350
|
+
if (column.type === 'user' || filterType === 'user') {
|
|
351
|
+
// Entity(User) envelopes store the user object under `.value`; plain user
|
|
352
|
+
// columns may hold it directly. Both paths produce the {id,userName,displayName} shape.
|
|
353
|
+
const source = column.type === 'entity' &&
|
|
354
|
+
cellValue &&
|
|
355
|
+
typeof cellValue === 'object' &&
|
|
356
|
+
'value' in cellValue
|
|
357
|
+
? cellValue['value']
|
|
358
|
+
: cellValue;
|
|
359
|
+
return TableValueResolver.extractUserFilterValue(source);
|
|
360
|
+
}
|
|
361
|
+
// Entity-typed columns carry a `{ viewType, value, rawValue, ... }` envelope.
|
|
362
|
+
// Unwrap once so boolean / scalar branches below operate on the inner value,
|
|
363
|
+
// matching what `matchesFilter` -> `getColumnFilterValue` compares against.
|
|
364
|
+
const normalized = column.type === 'entity'
|
|
365
|
+
? TableValueResolver.getEntityValueByType(cellValue, 'filter')
|
|
366
|
+
: cellValue;
|
|
367
|
+
if (normalized === null || normalized === undefined || normalized === '') {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
if (filterType === 'boolean') {
|
|
371
|
+
return TableValueResolver.resolveBooleanValue(normalized);
|
|
372
|
+
}
|
|
373
|
+
if (filterType === 'select' || filterType === 'text') {
|
|
374
|
+
if (column.type === 'entity') {
|
|
375
|
+
return String(normalized);
|
|
376
|
+
}
|
|
377
|
+
const display = TableValueResolver.resolveDisplayValue(cellValue);
|
|
378
|
+
return display === null ? null : String(display);
|
|
379
|
+
}
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* True when two filter values refer to the same thing. Mirrors the branches
|
|
384
|
+
* in `Table.matchesFilter`: scalar equality, boolean equality, or user-object
|
|
385
|
+
* identity on id / userName / displayName.
|
|
386
|
+
*/
|
|
387
|
+
static isFilterValueEqual(a, b) {
|
|
388
|
+
if (a === b)
|
|
389
|
+
return true;
|
|
390
|
+
if (a === null || a === undefined || b === null || b === undefined) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
394
|
+
const left = a;
|
|
395
|
+
const right = b;
|
|
396
|
+
if (left['id'] != null && left['id'] === right['id'])
|
|
397
|
+
return true;
|
|
398
|
+
if (left['userName'] != null && left['userName'] === right['userName']) {
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
if (left['displayName'] != null &&
|
|
402
|
+
left['displayName'] === right['displayName']) {
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
return String(a) === String(b);
|
|
408
|
+
}
|
|
409
|
+
static extractUserFilterValue(value) {
|
|
410
|
+
if (value === null || value === undefined)
|
|
411
|
+
return null;
|
|
412
|
+
if (typeof value === 'object') {
|
|
413
|
+
const record = value;
|
|
414
|
+
const inner = record['value'] && typeof record['value'] === 'object'
|
|
415
|
+
? record['value']
|
|
416
|
+
: record;
|
|
417
|
+
const id = inner['id'];
|
|
418
|
+
const userName = inner['userName'] ?? inner['username'];
|
|
419
|
+
const displayName = inner['displayName'] ?? inner['name'];
|
|
420
|
+
if (id == null && userName == null && displayName == null) {
|
|
421
|
+
const fallback = TableValueResolver.resolveDisplayValue(value);
|
|
422
|
+
return fallback === null ? null : String(fallback);
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
...(id != null ? { id } : {}),
|
|
426
|
+
...(userName != null ? { userName } : {}),
|
|
427
|
+
...(displayName != null ? { displayName } : {}),
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
return String(value);
|
|
431
|
+
}
|
|
110
432
|
static getColumnFilterValue(row, column) {
|
|
111
433
|
const cellValue = TableValueResolver.getProperty(row, column.key);
|
|
112
434
|
if (cellValue === null || cellValue === undefined) {
|
|
@@ -273,6 +595,57 @@ class TableValueResolver {
|
|
|
273
595
|
}
|
|
274
596
|
}
|
|
275
597
|
|
|
598
|
+
/**
|
|
599
|
+
* Renders a single filter control for one `ColumnDef`, dispatching on
|
|
600
|
+
* `column.filterConfig.type` (`text` | `select` | `date` | `boolean` | `user`).
|
|
601
|
+
*
|
|
602
|
+
* Two-way binds the filter value via `value` / `valueChange`. Shared by both
|
|
603
|
+
* filter UX modes (popover + per-column) so field rendering lives in one place.
|
|
604
|
+
* Add a new filter type by adding a `@case` in the template and extending
|
|
605
|
+
* `FilterConfig['type']`.
|
|
606
|
+
*/
|
|
607
|
+
class TableFilterField {
|
|
608
|
+
column = input.required(...(ngDevMode ? [{ debugName: "column" }] : /* istanbul ignore next */ []));
|
|
609
|
+
value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
610
|
+
booleanOptions = [
|
|
611
|
+
{ label: 'Yes', value: true },
|
|
612
|
+
{ label: 'No', value: false },
|
|
613
|
+
];
|
|
614
|
+
getFilterType() {
|
|
615
|
+
return this.column().filterConfig?.type ?? 'text';
|
|
616
|
+
}
|
|
617
|
+
getScalarValue() {
|
|
618
|
+
const current = this.value();
|
|
619
|
+
return current?.value ?? current ?? null;
|
|
620
|
+
}
|
|
621
|
+
getDateRangeValue(part) {
|
|
622
|
+
const current = this.value();
|
|
623
|
+
if (!current || typeof current !== 'object')
|
|
624
|
+
return null;
|
|
625
|
+
return part === 'from' ? (current.from ?? null) : (current.to ?? null);
|
|
626
|
+
}
|
|
627
|
+
updateScalar(next) {
|
|
628
|
+
this.value.set(next);
|
|
629
|
+
}
|
|
630
|
+
updateDate(part, next) {
|
|
631
|
+
const current = this.value() ?? {};
|
|
632
|
+
this.value.set({ ...current, [part]: next });
|
|
633
|
+
}
|
|
634
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableFilterField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
635
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TableFilterField, isStandalone: true, selector: "mt-table-filter-field", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, ngImport: i0, template: "@switch (getFilterType()) {\n @case (\"text\") {\n <mt-text-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [placeholder]=\"\n ('components.table.select' | transloco) +\n ' ' +\n (column().filterConfig?.label || column().label)\n \"\n />\n }\n @case (\"select\") {\n <mt-select-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [options]=\"column().filterConfig?.options ?? []\"\n [placeholder]=\"\n ('components.table.select' | transloco) +\n ' ' +\n (column().filterConfig?.label || column().label)\n \"\n [hasPlaceholderPrefix]=\"false\"\n showClear\n />\n }\n @case (\"date\") {\n <div class=\"space-y-3\">\n <div class=\"space-y-1\">\n <label\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {{ \"components.table.from\" | transloco }}\n </label>\n <mt-date-field\n [ngModel]=\"getDateRangeValue('from')\"\n (ngModelChange)=\"updateDate('from', $event)\"\n [placeholder]=\"'components.table.from' | transloco\"\n />\n </div>\n <div class=\"space-y-1\">\n <label\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {{ \"components.table.to\" | transloco }}\n </label>\n <mt-date-field\n [ngModel]=\"getDateRangeValue('to')\"\n (ngModelChange)=\"updateDate('to', $event)\"\n [placeholder]=\"'components.table.to' | transloco\"\n />\n </div>\n </div>\n }\n @case (\"boolean\") {\n <mt-select-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [options]=\"booleanOptions\"\n [placeholder]=\"'components.table.select' | transloco\"\n [hasPlaceholderPrefix]=\"false\"\n showClear\n />\n }\n @case (\"user\") {\n <mt-user-search-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [placeholder]=\"column().filterConfig?.label || column().label\"\n [apiUrl]=\"column().filterConfig?.apiUrl ?? ''\"\n [context]=\"column().filterConfig?.context\"\n />\n }\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs", "required"] }, { kind: "component", type: UserSearchField, selector: "mt-user-search-field", inputs: ["hint", "label", "placeholder", "class", "readonly", "required", "isMultiple", "apiUrl", "dataKey", "paramName", "context", "size"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
636
|
+
}
|
|
637
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableFilterField, decorators: [{
|
|
638
|
+
type: Component,
|
|
639
|
+
args: [{ selector: 'mt-table-filter-field', standalone: true, imports: [
|
|
640
|
+
FormsModule,
|
|
641
|
+
TextField,
|
|
642
|
+
SelectField,
|
|
643
|
+
DateField,
|
|
644
|
+
UserSearchField,
|
|
645
|
+
TranslocoModule,
|
|
646
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@switch (getFilterType()) {\n @case (\"text\") {\n <mt-text-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [placeholder]=\"\n ('components.table.select' | transloco) +\n ' ' +\n (column().filterConfig?.label || column().label)\n \"\n />\n }\n @case (\"select\") {\n <mt-select-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [options]=\"column().filterConfig?.options ?? []\"\n [placeholder]=\"\n ('components.table.select' | transloco) +\n ' ' +\n (column().filterConfig?.label || column().label)\n \"\n [hasPlaceholderPrefix]=\"false\"\n showClear\n />\n }\n @case (\"date\") {\n <div class=\"space-y-3\">\n <div class=\"space-y-1\">\n <label\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {{ \"components.table.from\" | transloco }}\n </label>\n <mt-date-field\n [ngModel]=\"getDateRangeValue('from')\"\n (ngModelChange)=\"updateDate('from', $event)\"\n [placeholder]=\"'components.table.from' | transloco\"\n />\n </div>\n <div class=\"space-y-1\">\n <label\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {{ \"components.table.to\" | transloco }}\n </label>\n <mt-date-field\n [ngModel]=\"getDateRangeValue('to')\"\n (ngModelChange)=\"updateDate('to', $event)\"\n [placeholder]=\"'components.table.to' | transloco\"\n />\n </div>\n </div>\n }\n @case (\"boolean\") {\n <mt-select-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [options]=\"booleanOptions\"\n [placeholder]=\"'components.table.select' | transloco\"\n [hasPlaceholderPrefix]=\"false\"\n showClear\n />\n }\n @case (\"user\") {\n <mt-user-search-field\n [ngModel]=\"getScalarValue()\"\n (ngModelChange)=\"updateScalar($event)\"\n [placeholder]=\"column().filterConfig?.label || column().label\"\n [apiUrl]=\"column().filterConfig?.apiUrl ?? ''\"\n [context]=\"column().filterConfig?.context\"\n />\n }\n}\n" }]
|
|
647
|
+
}], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }] } });
|
|
648
|
+
|
|
276
649
|
class TableFilter {
|
|
277
650
|
columns = input.required(...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
278
651
|
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
@@ -280,68 +653,12 @@ class TableFilter {
|
|
|
280
653
|
filterReset = output();
|
|
281
654
|
pendingFilters = signal({}, ...(ngDevMode ? [{ debugName: "pendingFilters" }] : /* istanbul ignore next */ []));
|
|
282
655
|
appliedFilters = signal({}, ...(ngDevMode ? [{ debugName: "appliedFilters" }] : /* istanbul ignore next */ []));
|
|
283
|
-
booleanOptions = [
|
|
284
|
-
{ label: 'Yes', value: true },
|
|
285
|
-
{ label: 'No', value: false },
|
|
286
|
-
];
|
|
287
656
|
onChange = () => { };
|
|
288
657
|
onTouched = () => { };
|
|
289
658
|
filterableColumns = computed(() => this.columns()
|
|
290
659
|
.filter((col) => TableValueResolver.getColumnFilterType(col, this.data()[0]) !== null)
|
|
291
|
-
.map((col) => {
|
|
292
|
-
|
|
293
|
-
// Auto-generate select options from data if not provided
|
|
294
|
-
if (filterType === 'select' && !col.filterConfig?.options?.length) {
|
|
295
|
-
const uniqueOptions = Array.from(this.data().reduce((options, row) => {
|
|
296
|
-
const value = TableValueResolver.getColumnFilterValue(row, col);
|
|
297
|
-
if (value === null || value === undefined || value === '') {
|
|
298
|
-
return options;
|
|
299
|
-
}
|
|
300
|
-
const optionKey = `${typeof value}:${String(value)}`;
|
|
301
|
-
if (!options.has(optionKey)) {
|
|
302
|
-
options.set(optionKey, {
|
|
303
|
-
label: String(value),
|
|
304
|
-
value,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
return options;
|
|
308
|
-
}, new Map()))
|
|
309
|
-
.map(([, option]) => option)
|
|
310
|
-
.sort((a, b) => a.label.localeCompare(b.label));
|
|
311
|
-
return {
|
|
312
|
-
...col,
|
|
313
|
-
filterConfig: {
|
|
314
|
-
...col.filterConfig,
|
|
315
|
-
type: filterType,
|
|
316
|
-
options: uniqueOptions,
|
|
317
|
-
},
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
return {
|
|
321
|
-
...col,
|
|
322
|
-
filterConfig: {
|
|
323
|
-
...col.filterConfig,
|
|
324
|
-
type: filterType ?? col.filterConfig?.type ?? 'text',
|
|
325
|
-
},
|
|
326
|
-
};
|
|
327
|
-
}), ...(ngDevMode ? [{ debugName: "filterableColumns" }] : /* istanbul ignore next */ []));
|
|
328
|
-
activeFilterCount = computed(() => {
|
|
329
|
-
const filters = this.appliedFilters();
|
|
330
|
-
return Object.values(filters).filter((v) => this.hasValue(v)).length;
|
|
331
|
-
}, ...(ngDevMode ? [{ debugName: "activeFilterCount" }] : /* istanbul ignore next */ []));
|
|
332
|
-
getFilterType(col) {
|
|
333
|
-
return (TableValueResolver.getColumnFilterType(col, this.data()[0]) ?? 'text');
|
|
334
|
-
}
|
|
335
|
-
getFilterValue(key) {
|
|
336
|
-
const value = this.pendingFilters()[key];
|
|
337
|
-
return value?.value ?? value ?? null;
|
|
338
|
-
}
|
|
339
|
-
getDateRangeValue(key, part) {
|
|
340
|
-
const value = this.pendingFilters()[key];
|
|
341
|
-
if (!value || typeof value !== 'object')
|
|
342
|
-
return null;
|
|
343
|
-
return part === 'from' ? (value.from ?? null) : (value.to ?? null);
|
|
344
|
-
}
|
|
660
|
+
.map((col) => TableValueResolver.buildFilterableColumn(col, this.data())), ...(ngDevMode ? [{ debugName: "filterableColumns" }] : /* istanbul ignore next */ []));
|
|
661
|
+
activeFilterCount = computed(() => Object.values(this.appliedFilters()).filter((value) => TableValueResolver.hasFilterValue(value)).length, ...(ngDevMode ? [{ debugName: "activeFilterCount" }] : /* istanbul ignore next */ []));
|
|
345
662
|
updateFilter(key, value) {
|
|
346
663
|
this.pendingFilters.update((filters) => ({
|
|
347
664
|
...filters,
|
|
@@ -349,19 +666,6 @@ class TableFilter {
|
|
|
349
666
|
}));
|
|
350
667
|
this.onTouched();
|
|
351
668
|
}
|
|
352
|
-
updateDateFilter(key, part, value) {
|
|
353
|
-
this.pendingFilters.update((filters) => {
|
|
354
|
-
const current = filters[key] ?? {};
|
|
355
|
-
return {
|
|
356
|
-
...filters,
|
|
357
|
-
[key]: {
|
|
358
|
-
...current,
|
|
359
|
-
[part]: value,
|
|
360
|
-
},
|
|
361
|
-
};
|
|
362
|
-
});
|
|
363
|
-
this.onTouched();
|
|
364
|
-
}
|
|
365
669
|
apply() {
|
|
366
670
|
const filters = { ...this.pendingFilters() };
|
|
367
671
|
this.appliedFilters.set(filters);
|
|
@@ -374,14 +678,6 @@ class TableFilter {
|
|
|
374
678
|
this.onChange({});
|
|
375
679
|
this.filterReset.emit();
|
|
376
680
|
}
|
|
377
|
-
hasValue(value) {
|
|
378
|
-
if (value === null || value === undefined || value === '')
|
|
379
|
-
return false;
|
|
380
|
-
if (typeof value === 'object') {
|
|
381
|
-
return value.from != null || value.to != null || value.value != null;
|
|
382
|
-
}
|
|
383
|
-
return true;
|
|
384
|
-
}
|
|
385
681
|
// ControlValueAccessor
|
|
386
682
|
writeValue(value) {
|
|
387
683
|
const filters = value ?? {};
|
|
@@ -401,28 +697,429 @@ class TableFilter {
|
|
|
401
697
|
useExisting: forwardRef(() => TableFilter),
|
|
402
698
|
multi: true,
|
|
403
699
|
},
|
|
404
|
-
], ngImport: i0, template: "<mt-button\
|
|
700
|
+
], ngImport: i0, template: "<mt-button\n (click)=\"popover.toggle($event)\"\n [label]=\"'components.table.filter' | transloco\"\n [badge]=\"activeFilterCount()\"\n severity=\"primary\"\n size=\"small\"\n icon=\"general.filter-funnel-01\"\n/>\n\n<p-popover #popover [style]=\"{ width: '320px' }\" appendTo=\"body\">\n <div class=\"flex flex-col max-h-[50vh]\">\n <h4\n class=\"text-lg py-2 font-semibold border-b border-surface-200 dark:border-surface-700 shrink-0\"\n >\n {{ \"components.table.filterOptions\" | transloco }}\n </h4>\n\n <div\n class=\"space-y-3 overflow-y-auto flex-1 py-3\"\n (keydown.enter)=\"apply(); popover.hide()\"\n >\n @for (col of filterableColumns(); track col.key) {\n <div class=\"space-y-1\">\n <label\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {{ col.filterConfig?.label || col.label }}\n </label>\n <mt-table-filter-field\n [column]=\"col\"\n [value]=\"pendingFilters()[col.key]\"\n (valueChange)=\"updateFilter(col.key, $event)\"\n />\n </div>\n }\n </div>\n\n <div\n class=\"flex justify-end gap-2 pt-4 border-t border-surface-200 dark:border-surface-700 shrink-0\"\n >\n <mt-button\n variant=\"outlined\"\n (click)=\"reset(); popover.hide()\"\n [label]=\"'components.table.reset' | transloco\"\n />\n <mt-button\n (click)=\"apply(); popover.hide()\"\n [label]=\"'components.table.apply' | transloco\"\n />\n </div>\n </div>\n</p-popover>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1$2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: TableFilterField, selector: "mt-table-filter-field", inputs: ["column", "value"], outputs: ["valueChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
405
701
|
}
|
|
406
702
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableFilter, decorators: [{
|
|
407
703
|
type: Component,
|
|
408
704
|
args: [{ selector: 'mt-table-filter', standalone: true, imports: [
|
|
409
705
|
FormsModule,
|
|
410
|
-
TextField,
|
|
411
|
-
SelectField,
|
|
412
|
-
DateField,
|
|
413
|
-
UserSearchField,
|
|
414
706
|
Button,
|
|
415
707
|
PopoverModule,
|
|
416
708
|
TranslocoModule,
|
|
709
|
+
TableFilterField,
|
|
417
710
|
], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
418
711
|
{
|
|
419
712
|
provide: NG_VALUE_ACCESSOR,
|
|
420
713
|
useExisting: forwardRef(() => TableFilter),
|
|
421
714
|
multi: true,
|
|
422
715
|
},
|
|
423
|
-
], template: "<mt-button\
|
|
716
|
+
], template: "<mt-button\n (click)=\"popover.toggle($event)\"\n [label]=\"'components.table.filter' | transloco\"\n [badge]=\"activeFilterCount()\"\n severity=\"primary\"\n size=\"small\"\n icon=\"general.filter-funnel-01\"\n/>\n\n<p-popover #popover [style]=\"{ width: '320px' }\" appendTo=\"body\">\n <div class=\"flex flex-col max-h-[50vh]\">\n <h4\n class=\"text-lg py-2 font-semibold border-b border-surface-200 dark:border-surface-700 shrink-0\"\n >\n {{ \"components.table.filterOptions\" | transloco }}\n </h4>\n\n <div\n class=\"space-y-3 overflow-y-auto flex-1 py-3\"\n (keydown.enter)=\"apply(); popover.hide()\"\n >\n @for (col of filterableColumns(); track col.key) {\n <div class=\"space-y-1\">\n <label\n class=\"block text-sm font-medium text-gray-700 dark:text-gray-300\"\n >\n {{ col.filterConfig?.label || col.label }}\n </label>\n <mt-table-filter-field\n [column]=\"col\"\n [value]=\"pendingFilters()[col.key]\"\n (valueChange)=\"updateFilter(col.key, $event)\"\n />\n </div>\n }\n </div>\n\n <div\n class=\"flex justify-end gap-2 pt-4 border-t border-surface-200 dark:border-surface-700 shrink-0\"\n >\n <mt-button\n variant=\"outlined\"\n (click)=\"reset(); popover.hide()\"\n [label]=\"'components.table.reset' | transloco\"\n />\n <mt-button\n (click)=\"apply(); popover.hide()\"\n [label]=\"'components.table.apply' | transloco\"\n />\n </div>\n </div>\n</p-popover>\n" }]
|
|
424
717
|
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], filterApplied: [{ type: i0.Output, args: ["filterApplied"] }], filterReset: [{ type: i0.Output, args: ["filterReset"] }] } });
|
|
425
718
|
|
|
719
|
+
/**
|
|
720
|
+
* Stateless, controlled toolbar used by `mt-table` and by list-style consumers
|
|
721
|
+
* (e.g. `client-list-cards-view`) so the two share one caption UI without
|
|
722
|
+
* duplicating the search/filter/actions markup.
|
|
723
|
+
*
|
|
724
|
+
* The caption only renders the popover-mode filter button — per-column filter
|
|
725
|
+
* icons live in the table header itself (cards have no columns).
|
|
726
|
+
*/
|
|
727
|
+
class TableCaption {
|
|
728
|
+
// Capability flags
|
|
729
|
+
generalSearch = input(false, { ...(ngDevMode ? { debugName: "generalSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
730
|
+
showFilters = input(false, { ...(ngDevMode ? { debugName: "showFilters" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
731
|
+
filterMode = input('popover', ...(ngDevMode ? [{ debugName: "filterMode" }] : /* istanbul ignore next */ []));
|
|
732
|
+
exportable = input(false, { ...(ngDevMode ? { debugName: "exportable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
733
|
+
printable = input(false, { ...(ngDevMode ? { debugName: "printable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
734
|
+
groupable = input(false, { ...(ngDevMode ? { debugName: "groupable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
735
|
+
// Context for pickers
|
|
736
|
+
columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
737
|
+
data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
738
|
+
groupColumns = input([], ...(ngDevMode ? [{ debugName: "groupColumns" }] : /* istanbul ignore next */ []));
|
|
739
|
+
// Tabs
|
|
740
|
+
tabs = input(...(ngDevMode ? [undefined, { debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
741
|
+
tabsOptionLabel = input('label', ...(ngDevMode ? [{ debugName: "tabsOptionLabel" }] : /* istanbul ignore next */ []));
|
|
742
|
+
tabsOptionValue = input('value', ...(ngDevMode ? [{ debugName: "tabsOptionValue" }] : /* istanbul ignore next */ []));
|
|
743
|
+
// Toolbar-level action buttons rendered inline (not the dots menu)
|
|
744
|
+
actions = input([], ...(ngDevMode ? [{ debugName: "actions" }] : /* istanbul ignore next */ []));
|
|
745
|
+
// Projected caption slots
|
|
746
|
+
captionStart = input(null, ...(ngDevMode ? [{ debugName: "captionStart" }] : /* istanbul ignore next */ []));
|
|
747
|
+
captionEnd = input(null, ...(ngDevMode ? [{ debugName: "captionEnd" }] : /* istanbul ignore next */ []));
|
|
748
|
+
// Two-way state (the caption is a controlled component)
|
|
749
|
+
activeTab = model(...(ngDevMode ? [undefined, { debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
750
|
+
filters = model({}, ...(ngDevMode ? [{ debugName: "filters" }] : /* istanbul ignore next */ []));
|
|
751
|
+
filterTerm = model('', ...(ngDevMode ? [{ debugName: "filterTerm" }] : /* istanbul ignore next */ []));
|
|
752
|
+
groupBy = model(null, ...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
|
|
753
|
+
// Events
|
|
754
|
+
exportRequested = output();
|
|
755
|
+
printRequested = output();
|
|
756
|
+
onTabChange = output();
|
|
757
|
+
searchChange = output();
|
|
758
|
+
filterApplied = output();
|
|
759
|
+
filterReset = output();
|
|
760
|
+
showsAnything = computed(() => !!this.captionStart() ||
|
|
761
|
+
!!this.captionEnd() ||
|
|
762
|
+
this.generalSearch() ||
|
|
763
|
+
(this.showFilters() && this.filterMode() === 'popover') ||
|
|
764
|
+
this.exportable() ||
|
|
765
|
+
this.printable() ||
|
|
766
|
+
this.groupable() ||
|
|
767
|
+
(this.tabs()?.length ?? 0) > 0 ||
|
|
768
|
+
this.actions().length > 0, ...(ngDevMode ? [{ debugName: "showsAnything" }] : /* istanbul ignore next */ []));
|
|
769
|
+
onSearch(term) {
|
|
770
|
+
this.filterTerm.set(term);
|
|
771
|
+
this.searchChange.emit(term);
|
|
772
|
+
}
|
|
773
|
+
onFilterApplied(next) {
|
|
774
|
+
this.filters.set(next);
|
|
775
|
+
this.filterApplied.emit(next);
|
|
776
|
+
}
|
|
777
|
+
onFilterReset() {
|
|
778
|
+
this.filters.set({});
|
|
779
|
+
this.filterReset.emit();
|
|
780
|
+
}
|
|
781
|
+
onGroupChange(key) {
|
|
782
|
+
this.groupBy.set(key);
|
|
783
|
+
}
|
|
784
|
+
tabChanged(tab) {
|
|
785
|
+
this.onTabChange.emit(tab);
|
|
786
|
+
}
|
|
787
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableCaption, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
788
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TableCaption, isStandalone: true, selector: "mt-table-caption", inputs: { generalSearch: { classPropertyName: "generalSearch", publicName: "generalSearch", isSignal: true, isRequired: false, transformFunction: null }, showFilters: { classPropertyName: "showFilters", publicName: "showFilters", isSignal: true, isRequired: false, transformFunction: null }, filterMode: { classPropertyName: "filterMode", publicName: "filterMode", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, printable: { classPropertyName: "printable", publicName: "printable", isSignal: true, isRequired: false, transformFunction: null }, groupable: { classPropertyName: "groupable", publicName: "groupable", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, groupColumns: { classPropertyName: "groupColumns", publicName: "groupColumns", isSignal: true, isRequired: false, transformFunction: null }, tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, tabsOptionLabel: { classPropertyName: "tabsOptionLabel", publicName: "tabsOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, tabsOptionValue: { classPropertyName: "tabsOptionValue", publicName: "tabsOptionValue", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, captionStart: { classPropertyName: "captionStart", publicName: "captionStart", isSignal: true, isRequired: false, transformFunction: null }, captionEnd: { classPropertyName: "captionEnd", publicName: "captionEnd", isSignal: true, isRequired: false, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, filterTerm: { classPropertyName: "filterTerm", publicName: "filterTerm", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeTab: "activeTabChange", filters: "filtersChange", filterTerm: "filterTermChange", groupBy: "groupByChange", exportRequested: "exportRequested", printRequested: "printRequested", onTabChange: "onTabChange", searchChange: "searchChange", filterApplied: "filterApplied", filterReset: "filterReset" }, ngImport: i0, template: "@if (showsAnything()) {\n <div class=\"mt-table-caption\">\n <div\n class=\"flex relative items-center gap-2 pb-4\"\n [class]=\"!generalSearch() ? 'justify-end' : 'justify-between'\"\n >\n <div class=\"flex items-center gap-2\">\n @if (captionStart(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\"></ng-container>\n }\n @if (tabs()) {\n <mt-tabs\n [(active)]=\"activeTab\"\n [options]=\"tabs()\"\n [optionLabel]=\"tabsOptionLabel()\"\n [optionValue]=\"tabsOptionValue()\"\n (onChange)=\"tabChanged($event)\"\n size=\"large\"\n ></mt-tabs>\n }\n @if (generalSearch()) {\n <mt-text-field\n [ngModel]=\"filterTerm()\"\n (ngModelChange)=\"onSearch($event)\"\n icon=\"general.search-lg\"\n [placeholder]=\"'components.table.search' | transloco\"\n ></mt-text-field>\n }\n </div>\n <div class=\"flex items-center gap-2\">\n @if (showFilters() && filterMode() === \"popover\") {\n <mt-table-filter\n [columns]=\"columns()\"\n [data]=\"data()\"\n [ngModel]=\"filters()\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterReset)=\"onFilterReset()\"\n />\n }\n @if (exportable() || printable() || groupable()) {\n <mt-table-actions-menu\n [exportable]=\"exportable()\"\n [printable]=\"printable()\"\n [groupable]=\"groupable()\"\n [groupColumns]=\"groupColumns()\"\n [activeGroup]=\"groupBy()\"\n (exportRequested)=\"exportRequested.emit()\"\n (printRequested)=\"printRequested.emit()\"\n (groupChange)=\"onGroupChange($event)\"\n />\n }\n @if (actions().length > 0) {\n <div class=\"flex items-center space-x-2\">\n @for (action of actions(); track action.label) {\n <mt-button\n [icon]=\"action.icon\"\n [severity]=\"action.color\"\n [variant]=\"action.variant\"\n [size]=\"$any(action).size\"\n (click)=\"action.action(null)\"\n [label]=\"action.label\"\n [tooltip]=\"action.tooltip\"\n ></mt-button>\n }\n </div>\n }\n @if (captionEnd(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\"></ng-container>\n }\n </div>\n </div>\n </div>\n}\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: TableFilter, selector: "mt-table-filter", inputs: ["columns", "data"], outputs: ["filterApplied", "filterReset"] }, { kind: "component", type: TableActionsMenu, selector: "mt-table-actions-menu", inputs: ["exportable", "printable", "groupable", "groupColumns", "activeGroup"], outputs: ["exportRequested", "printRequested", "groupChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
789
|
+
}
|
|
790
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableCaption, decorators: [{
|
|
791
|
+
type: Component,
|
|
792
|
+
args: [{ selector: 'mt-table-caption', standalone: true, imports: [
|
|
793
|
+
NgTemplateOutlet,
|
|
794
|
+
FormsModule,
|
|
795
|
+
TranslocoModule,
|
|
796
|
+
Button,
|
|
797
|
+
Tabs,
|
|
798
|
+
TextField,
|
|
799
|
+
TableFilter,
|
|
800
|
+
TableActionsMenu,
|
|
801
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (showsAnything()) {\n <div class=\"mt-table-caption\">\n <div\n class=\"flex relative items-center gap-2 pb-4\"\n [class]=\"!generalSearch() ? 'justify-end' : 'justify-between'\"\n >\n <div class=\"flex items-center gap-2\">\n @if (captionStart(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\"></ng-container>\n }\n @if (tabs()) {\n <mt-tabs\n [(active)]=\"activeTab\"\n [options]=\"tabs()\"\n [optionLabel]=\"tabsOptionLabel()\"\n [optionValue]=\"tabsOptionValue()\"\n (onChange)=\"tabChanged($event)\"\n size=\"large\"\n ></mt-tabs>\n }\n @if (generalSearch()) {\n <mt-text-field\n [ngModel]=\"filterTerm()\"\n (ngModelChange)=\"onSearch($event)\"\n icon=\"general.search-lg\"\n [placeholder]=\"'components.table.search' | transloco\"\n ></mt-text-field>\n }\n </div>\n <div class=\"flex items-center gap-2\">\n @if (showFilters() && filterMode() === \"popover\") {\n <mt-table-filter\n [columns]=\"columns()\"\n [data]=\"data()\"\n [ngModel]=\"filters()\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterReset)=\"onFilterReset()\"\n />\n }\n @if (exportable() || printable() || groupable()) {\n <mt-table-actions-menu\n [exportable]=\"exportable()\"\n [printable]=\"printable()\"\n [groupable]=\"groupable()\"\n [groupColumns]=\"groupColumns()\"\n [activeGroup]=\"groupBy()\"\n (exportRequested)=\"exportRequested.emit()\"\n (printRequested)=\"printRequested.emit()\"\n (groupChange)=\"onGroupChange($event)\"\n />\n }\n @if (actions().length > 0) {\n <div class=\"flex items-center space-x-2\">\n @for (action of actions(); track action.label) {\n <mt-button\n [icon]=\"action.icon\"\n [severity]=\"action.color\"\n [variant]=\"action.variant\"\n [size]=\"$any(action).size\"\n (click)=\"action.action(null)\"\n [label]=\"action.label\"\n [tooltip]=\"action.tooltip\"\n ></mt-button>\n }\n </div>\n }\n @if (captionEnd(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl\"></ng-container>\n }\n </div>\n </div>\n </div>\n}\n" }]
|
|
802
|
+
}], propDecorators: { generalSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalSearch", required: false }] }], showFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilters", required: false }] }], filterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMode", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], printable: [{ type: i0.Input, args: [{ isSignal: true, alias: "printable", required: false }] }], groupable: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupable", required: false }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], groupColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupColumns", required: false }] }], tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], tabsOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabsOptionLabel", required: false }] }], tabsOptionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabsOptionValue", required: false }] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], captionStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionStart", required: false }] }], captionEnd: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionEnd", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], filterTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTerm", required: false }] }, { type: i0.Output, args: ["filterTermChange"] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }, { type: i0.Output, args: ["groupByChange"] }], exportRequested: [{ type: i0.Output, args: ["exportRequested"] }], printRequested: [{ type: i0.Output, args: ["printRequested"] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], filterApplied: [{ type: i0.Output, args: ["filterApplied"] }], filterReset: [{ type: i0.Output, args: ["filterReset"] }] } });
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Per-column filter affordance: a small funnel icon in the column header that
|
|
806
|
+
* opens a popover with a single `TableFilterField`.
|
|
807
|
+
*
|
|
808
|
+
* Buffers edits in `pendingValue` until the user hits Apply — matches the
|
|
809
|
+
* popover-mode UX so behavior is predictable between modes. Emits `filterChange`
|
|
810
|
+
* with either the new value or `null` to clear.
|
|
811
|
+
*/
|
|
812
|
+
class TableColumnFilter {
|
|
813
|
+
column = input.required(...(ngDevMode ? [{ debugName: "column" }] : /* istanbul ignore next */ []));
|
|
814
|
+
value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
815
|
+
filterChange = output();
|
|
816
|
+
pendingValue = signal(null, ...(ngDevMode ? [{ debugName: "pendingValue" }] : /* istanbul ignore next */ []));
|
|
817
|
+
hasActiveValue = computed(() => TableValueResolver.hasFilterValue(this.value()), ...(ngDevMode ? [{ debugName: "hasActiveValue" }] : /* istanbul ignore next */ []));
|
|
818
|
+
open(popover, event) {
|
|
819
|
+
event.stopPropagation();
|
|
820
|
+
this.pendingValue.set(this.cloneValue(this.value()));
|
|
821
|
+
popover.toggle(event);
|
|
822
|
+
}
|
|
823
|
+
apply(popover) {
|
|
824
|
+
const next = this.pendingValue();
|
|
825
|
+
this.filterChange.emit(TableValueResolver.hasFilterValue(next) ? next : null);
|
|
826
|
+
popover.hide();
|
|
827
|
+
}
|
|
828
|
+
clear(popover) {
|
|
829
|
+
this.pendingValue.set(null);
|
|
830
|
+
this.filterChange.emit(null);
|
|
831
|
+
popover.hide();
|
|
832
|
+
}
|
|
833
|
+
cloneValue(value) {
|
|
834
|
+
if (value === null || value === undefined)
|
|
835
|
+
return null;
|
|
836
|
+
if (typeof value === 'object')
|
|
837
|
+
return { ...value };
|
|
838
|
+
return value;
|
|
839
|
+
}
|
|
840
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableColumnFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
841
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.8", type: TableColumnFilter, isStandalone: true, selector: "mt-table-column-filter", inputs: { column: { classPropertyName: "column", publicName: "column", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterChange: "filterChange" }, ngImport: i0, template: "<mt-button\n (onClick)=\"open(popover, $event)\"\n [icon]=\"\n hasActiveValue() ? 'general.filter-funnel-02' : 'general.filter-funnel-01'\n \"\n [severity]=\"hasActiveValue() ? 'primary' : 'secondary'\"\n variant=\"text\"\n size=\"small\"\n [tooltip]=\"'components.table.filter' | transloco\"\n styleClass=\"!p-1 !text-sm\"\n/>\n\n<p-popover #popover [style]=\"{ width: '280px' }\" appendTo=\"body\">\n <div\n class=\"flex flex-col gap-3\"\n (keydown.enter)=\"apply(popover)\"\n (click)=\"$event.stopPropagation()\"\n >\n <h4\n class=\"text-sm font-semibold text-gray-700 dark:text-gray-300 truncate\"\n [title]=\"column().filterConfig?.label || column().label\"\n >\n {{ column().filterConfig?.label || column().label }}\n </h4>\n\n <mt-table-filter-field\n [column]=\"column()\"\n [value]=\"pendingValue()\"\n (valueChange)=\"pendingValue.set($event)\"\n />\n\n <div\n class=\"flex justify-end gap-2 pt-2 border-t border-surface-200 dark:border-surface-700\"\n >\n <mt-button\n variant=\"outlined\"\n size=\"small\"\n (onClick)=\"clear(popover)\"\n [label]=\"'components.table.reset' | transloco\"\n />\n <mt-button\n size=\"small\"\n (onClick)=\"apply(popover)\"\n [label]=\"'components.table.apply' | transloco\"\n />\n </div>\n </div>\n</p-popover>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1$2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: TableFilterField, selector: "mt-table-filter-field", inputs: ["column", "value"], outputs: ["valueChange"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
842
|
+
}
|
|
843
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableColumnFilter, decorators: [{
|
|
844
|
+
type: Component,
|
|
845
|
+
args: [{ selector: 'mt-table-column-filter', standalone: true, imports: [
|
|
846
|
+
FormsModule,
|
|
847
|
+
Button,
|
|
848
|
+
PopoverModule,
|
|
849
|
+
TranslocoModule,
|
|
850
|
+
TableFilterField,
|
|
851
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<mt-button\n (onClick)=\"open(popover, $event)\"\n [icon]=\"\n hasActiveValue() ? 'general.filter-funnel-02' : 'general.filter-funnel-01'\n \"\n [severity]=\"hasActiveValue() ? 'primary' : 'secondary'\"\n variant=\"text\"\n size=\"small\"\n [tooltip]=\"'components.table.filter' | transloco\"\n styleClass=\"!p-1 !text-sm\"\n/>\n\n<p-popover #popover [style]=\"{ width: '280px' }\" appendTo=\"body\">\n <div\n class=\"flex flex-col gap-3\"\n (keydown.enter)=\"apply(popover)\"\n (click)=\"$event.stopPropagation()\"\n >\n <h4\n class=\"text-sm font-semibold text-gray-700 dark:text-gray-300 truncate\"\n [title]=\"column().filterConfig?.label || column().label\"\n >\n {{ column().filterConfig?.label || column().label }}\n </h4>\n\n <mt-table-filter-field\n [column]=\"column()\"\n [value]=\"pendingValue()\"\n (valueChange)=\"pendingValue.set($event)\"\n />\n\n <div\n class=\"flex justify-end gap-2 pt-2 border-t border-surface-200 dark:border-surface-700\"\n >\n <mt-button\n variant=\"outlined\"\n size=\"small\"\n (onClick)=\"clear(popover)\"\n [label]=\"'components.table.reset' | transloco\"\n />\n <mt-button\n size=\"small\"\n (onClick)=\"apply(popover)\"\n [label]=\"'components.table.apply' | transloco\"\n />\n </div>\n </div>\n</p-popover>\n" }]
|
|
852
|
+
}], propDecorators: { column: [{ type: i0.Input, args: [{ isSignal: true, alias: "column", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }] } });
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Centralises table export/print so any `mt-table` (and future tables) can
|
|
856
|
+
* drop in the behaviour without reimplementing XLSX serialisation or print
|
|
857
|
+
* DOM cloning. Injected schema-agnostically via `resolveValue` on the config.
|
|
858
|
+
*/
|
|
859
|
+
class TableExportService {
|
|
860
|
+
static PRINT_ROOT_CLASS = 'mt-printing';
|
|
861
|
+
static PRINT_REGION_CLASS = 'mt-print-region';
|
|
862
|
+
static PRINT_STYLE_ID = 'mt-table-print-style';
|
|
863
|
+
static PRINT_CSS = `
|
|
864
|
+
@media print {
|
|
865
|
+
html.mt-printing body > *:not(.mt-print-region) { display: none !important; }
|
|
866
|
+
html.mt-printing, html.mt-printing body { background: #ffffff !important; }
|
|
867
|
+
.mt-print-region { display: block !important; padding: 16px; color: #111827;
|
|
868
|
+
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif; }
|
|
869
|
+
.mt-print-region h1 { font-size: 18px; font-weight: 600; margin: 0 0 12px; }
|
|
870
|
+
.mt-print-region table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
|
871
|
+
.mt-print-region th, .mt-print-region td { text-align: start; padding: 6px 8px;
|
|
872
|
+
border: 1px solid #e5e7eb; vertical-align: top; }
|
|
873
|
+
.mt-print-region thead th { background: #f3f4f6; font-weight: 600; }
|
|
874
|
+
.mt-print-region tbody tr { break-inside: avoid; page-break-inside: avoid; }
|
|
875
|
+
}
|
|
876
|
+
.mt-print-region { display: none; }
|
|
877
|
+
`;
|
|
878
|
+
exportToExcel(config) {
|
|
879
|
+
const columns = this.getExportableColumns(config.columns);
|
|
880
|
+
const workbook = XLSX.utils.book_new();
|
|
881
|
+
const worksheet = XLSX.utils.json_to_sheet(this.buildLabeledRows(config.rows, columns, config.resolveValue));
|
|
882
|
+
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
|
|
883
|
+
XLSX.writeFileXLSX(workbook, `${this.normalizeFilename(config.filename)}.xlsx`);
|
|
884
|
+
}
|
|
885
|
+
printPdf(config) {
|
|
886
|
+
if (typeof document === 'undefined' || typeof window === 'undefined') {
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
const columns = this.getExportableColumns(config.columns);
|
|
890
|
+
const region = this.buildPrintRegion(config, columns);
|
|
891
|
+
this.ensurePrintStyles();
|
|
892
|
+
document.body.appendChild(region);
|
|
893
|
+
document.documentElement.classList.add(TableExportService.PRINT_ROOT_CLASS);
|
|
894
|
+
const cleanup = () => {
|
|
895
|
+
document.documentElement.classList.remove(TableExportService.PRINT_ROOT_CLASS);
|
|
896
|
+
region.remove();
|
|
897
|
+
window.removeEventListener('afterprint', cleanup);
|
|
898
|
+
};
|
|
899
|
+
window.addEventListener('afterprint', cleanup);
|
|
900
|
+
window.print();
|
|
901
|
+
}
|
|
902
|
+
ensurePrintStyles() {
|
|
903
|
+
if (document.getElementById(TableExportService.PRINT_STYLE_ID)) {
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const style = document.createElement('style');
|
|
907
|
+
style.id = TableExportService.PRINT_STYLE_ID;
|
|
908
|
+
style.textContent = TableExportService.PRINT_CSS;
|
|
909
|
+
document.head.appendChild(style);
|
|
910
|
+
}
|
|
911
|
+
getExportableColumns(columns) {
|
|
912
|
+
return columns.filter((column) => column.type !== 'custom');
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Produces rows keyed by column label (Excel header row).
|
|
916
|
+
* Entity columns use the dedicated entity resolver for a clean export value.
|
|
917
|
+
*/
|
|
918
|
+
buildLabeledRows(rows, columns, resolveValue) {
|
|
919
|
+
return rows.map((row) => {
|
|
920
|
+
const labeledRow = {};
|
|
921
|
+
columns.forEach((column) => {
|
|
922
|
+
const cellValue = column.type === 'entity'
|
|
923
|
+
? TableValueResolver.getEntityValueByType(TableValueResolver.getProperty(row, column.key), 'export')
|
|
924
|
+
: resolveValue(row, column);
|
|
925
|
+
labeledRow[column.label] = cellValue ?? null;
|
|
926
|
+
});
|
|
927
|
+
return labeledRow;
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
buildPrintRegion(config, columns) {
|
|
931
|
+
const region = document.createElement('section');
|
|
932
|
+
region.className = TableExportService.PRINT_REGION_CLASS;
|
|
933
|
+
if (config.title) {
|
|
934
|
+
const heading = document.createElement('h1');
|
|
935
|
+
heading.textContent = config.title;
|
|
936
|
+
region.appendChild(heading);
|
|
937
|
+
}
|
|
938
|
+
const table = document.createElement('table');
|
|
939
|
+
const thead = document.createElement('thead');
|
|
940
|
+
const headerRow = document.createElement('tr');
|
|
941
|
+
columns.forEach((column) => {
|
|
942
|
+
const th = document.createElement('th');
|
|
943
|
+
th.textContent = column.label;
|
|
944
|
+
headerRow.appendChild(th);
|
|
945
|
+
});
|
|
946
|
+
thead.appendChild(headerRow);
|
|
947
|
+
table.appendChild(thead);
|
|
948
|
+
const tbody = document.createElement('tbody');
|
|
949
|
+
config.rows.forEach((row) => {
|
|
950
|
+
const tr = document.createElement('tr');
|
|
951
|
+
columns.forEach((column) => {
|
|
952
|
+
const td = document.createElement('td');
|
|
953
|
+
const cellValue = column.type === 'entity'
|
|
954
|
+
? TableValueResolver.getEntityValueByType(TableValueResolver.getProperty(row, column.key), 'export')
|
|
955
|
+
: config.resolveValue(row, column);
|
|
956
|
+
td.textContent = cellValue === null ? '' : String(cellValue);
|
|
957
|
+
tr.appendChild(td);
|
|
958
|
+
});
|
|
959
|
+
tbody.appendChild(tr);
|
|
960
|
+
});
|
|
961
|
+
table.appendChild(tbody);
|
|
962
|
+
region.appendChild(table);
|
|
963
|
+
return region;
|
|
964
|
+
}
|
|
965
|
+
normalizeFilename(value) {
|
|
966
|
+
const sanitized = (value ?? '').trim().replace(/[\\/:*?"<>|]+/g, '-');
|
|
967
|
+
return sanitized.length ? sanitized : 'download';
|
|
968
|
+
}
|
|
969
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableExportService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
970
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableExportService, providedIn: 'root' });
|
|
971
|
+
}
|
|
972
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TableExportService, decorators: [{
|
|
973
|
+
type: Injectable,
|
|
974
|
+
args: [{ providedIn: 'root' }]
|
|
975
|
+
}] });
|
|
976
|
+
|
|
977
|
+
/**
|
|
978
|
+
* Column filter types that produce useful (low-cardinality) row groups.
|
|
979
|
+
* Unique-valued columns (plain text, dates) would create a group per row —
|
|
980
|
+
* pointless visually and slow — so we exclude them from the group picker.
|
|
981
|
+
*/
|
|
982
|
+
const GROUPABLE_FILTER_TYPES = new Set([
|
|
983
|
+
'select',
|
|
984
|
+
'boolean',
|
|
985
|
+
'user',
|
|
986
|
+
]);
|
|
987
|
+
/**
|
|
988
|
+
* Pure controller owning all row-grouping concerns. Table instantiates one and
|
|
989
|
+
* binds its signals — keeps grouping logic out of table.ts.
|
|
990
|
+
*
|
|
991
|
+
* PrimeNG's subheader grouping renders only when `sortField === groupRowsBy`.
|
|
992
|
+
* `setGroup` therefore also pins the sort to the grouped column; clearing the
|
|
993
|
+
* group leaves the user's sort untouched.
|
|
994
|
+
*/
|
|
995
|
+
class TableGroupingController {
|
|
996
|
+
columns;
|
|
997
|
+
rows;
|
|
998
|
+
groupBy;
|
|
999
|
+
sortField;
|
|
1000
|
+
sortDirection;
|
|
1001
|
+
constructor(columns, rows, groupBy, sortField, sortDirection) {
|
|
1002
|
+
this.columns = columns;
|
|
1003
|
+
this.rows = rows;
|
|
1004
|
+
this.groupBy = groupBy;
|
|
1005
|
+
this.sortField = sortField;
|
|
1006
|
+
this.sortDirection = sortDirection;
|
|
1007
|
+
}
|
|
1008
|
+
groupableColumns = computed(() => {
|
|
1009
|
+
const sampleRow = this.rows()[0];
|
|
1010
|
+
return this.columns().filter((col) => {
|
|
1011
|
+
if (col.type === 'custom')
|
|
1012
|
+
return false;
|
|
1013
|
+
const filterType = TableValueResolver.getColumnFilterType(col, sampleRow);
|
|
1014
|
+
return filterType !== null && GROUPABLE_FILTER_TYPES.has(filterType);
|
|
1015
|
+
});
|
|
1016
|
+
}, ...(ngDevMode ? [{ debugName: "groupableColumns" }] : /* istanbul ignore next */ []));
|
|
1017
|
+
/**
|
|
1018
|
+
* Row counts per group key — consumed by the group header template so each
|
|
1019
|
+
* subheader can show "Status: Active (12)".
|
|
1020
|
+
*/
|
|
1021
|
+
groupCounts = computed(() => {
|
|
1022
|
+
const column = this.activeGroupColumn();
|
|
1023
|
+
if (!column)
|
|
1024
|
+
return new Map();
|
|
1025
|
+
const counts = new Map();
|
|
1026
|
+
for (const row of this.rows()) {
|
|
1027
|
+
const key = this.getGroupKey(row, column);
|
|
1028
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
1029
|
+
}
|
|
1030
|
+
return counts;
|
|
1031
|
+
}, ...(ngDevMode ? [{ debugName: "groupCounts" }] : /* istanbul ignore next */ []));
|
|
1032
|
+
getGroupCount(row) {
|
|
1033
|
+
const column = this.activeGroupColumn();
|
|
1034
|
+
if (!column)
|
|
1035
|
+
return 0;
|
|
1036
|
+
return this.groupCounts().get(this.getGroupKey(row, column)) ?? 0;
|
|
1037
|
+
}
|
|
1038
|
+
activeGroupColumn = computed(() => {
|
|
1039
|
+
const key = this.groupBy();
|
|
1040
|
+
if (!key)
|
|
1041
|
+
return null;
|
|
1042
|
+
return this.columns().find((col) => col.key === key) ?? null;
|
|
1043
|
+
}, ...(ngDevMode ? [{ debugName: "activeGroupColumn" }] : /* istanbul ignore next */ []));
|
|
1044
|
+
groupingActive = computed(() => this.activeGroupColumn() !== null, ...(ngDevMode ? [{ debugName: "groupingActive" }] : /* istanbul ignore next */ []));
|
|
1045
|
+
/**
|
|
1046
|
+
* Returns true when the given column is the active group column and
|
|
1047
|
+
* therefore cannot have its sort cleared (PrimeNG requirement).
|
|
1048
|
+
*/
|
|
1049
|
+
isGroupLockedSort(columnKey) {
|
|
1050
|
+
return this.groupingActive() && this.activeGroupColumn()?.key === columnKey;
|
|
1051
|
+
}
|
|
1052
|
+
setGroup(key) {
|
|
1053
|
+
this.groupBy.set(key && key.length > 0 ? key : null);
|
|
1054
|
+
if (key) {
|
|
1055
|
+
this.sortField.set(key);
|
|
1056
|
+
if (this.sortDirection() === null) {
|
|
1057
|
+
this.sortDirection.set('asc');
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Display label for a row's grouped value — used by the `#groupheader`
|
|
1063
|
+
* template. Leverages the same resolver pipeline the cells use, so status
|
|
1064
|
+
* maps / user display names render consistently.
|
|
1065
|
+
*/
|
|
1066
|
+
getGroupLabel(row) {
|
|
1067
|
+
const column = this.activeGroupColumn();
|
|
1068
|
+
if (!column)
|
|
1069
|
+
return '';
|
|
1070
|
+
const cellValue = TableValueResolver.getProperty(row, column.key);
|
|
1071
|
+
if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
1072
|
+
return '—';
|
|
1073
|
+
}
|
|
1074
|
+
if (column.type === 'entity') {
|
|
1075
|
+
const entityValue = TableValueResolver.getEntityValueByType(cellValue, 'export');
|
|
1076
|
+
return entityValue === null ? '—' : String(entityValue);
|
|
1077
|
+
}
|
|
1078
|
+
const display = TableValueResolver.resolveDisplayValue(cellValue);
|
|
1079
|
+
if (display === null || display === undefined)
|
|
1080
|
+
return '—';
|
|
1081
|
+
if (typeof display === 'boolean')
|
|
1082
|
+
return display ? 'Yes' : 'No';
|
|
1083
|
+
return String(display);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Accent color for status/entity-Status group headers. Reused from the
|
|
1087
|
+
* cell renderer's status-map pipeline so tint is consistent with the cell.
|
|
1088
|
+
*/
|
|
1089
|
+
getGroupAccentColor(row) {
|
|
1090
|
+
const column = this.activeGroupColumn();
|
|
1091
|
+
if (!column)
|
|
1092
|
+
return null;
|
|
1093
|
+
if (column.type !== 'status' && column.type !== 'entity')
|
|
1094
|
+
return null;
|
|
1095
|
+
const cellValue = TableValueResolver.getProperty(row, column.key);
|
|
1096
|
+
if (cellValue === null || cellValue === undefined)
|
|
1097
|
+
return null;
|
|
1098
|
+
if (typeof cellValue === 'object') {
|
|
1099
|
+
const obj = cellValue;
|
|
1100
|
+
const color = obj['color'];
|
|
1101
|
+
if (typeof color === 'string' && color.length > 0)
|
|
1102
|
+
return color;
|
|
1103
|
+
}
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
/** Stable key used to bucket rows into groups — normalised to string. */
|
|
1107
|
+
getGroupKey(row, column) {
|
|
1108
|
+
const cellValue = TableValueResolver.getProperty(row, column.key);
|
|
1109
|
+
if (cellValue === null || cellValue === undefined || cellValue === '') {
|
|
1110
|
+
return '__mt_group_empty__';
|
|
1111
|
+
}
|
|
1112
|
+
if (column.type === 'entity') {
|
|
1113
|
+
const entityValue = TableValueResolver.getEntityValueByType(cellValue, 'filter');
|
|
1114
|
+
return entityValue === null ? '__mt_group_empty__' : String(entityValue);
|
|
1115
|
+
}
|
|
1116
|
+
const display = TableValueResolver.resolveDisplayValue(cellValue);
|
|
1117
|
+
return display === null || display === undefined
|
|
1118
|
+
? '__mt_group_empty__'
|
|
1119
|
+
: String(display);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
|
|
426
1123
|
class Table {
|
|
427
1124
|
static LOADING_COLUMN_COUNT = 5;
|
|
428
1125
|
selectionChange = output();
|
|
@@ -443,6 +1140,7 @@ class Table {
|
|
|
443
1140
|
generalSearch = input(false, { ...(ngDevMode ? { debugName: "generalSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
444
1141
|
lazyLocalSearch = input(false, { ...(ngDevMode ? { debugName: "lazyLocalSearch" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
445
1142
|
showFilters = input(false, { ...(ngDevMode ? { debugName: "showFilters" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1143
|
+
filterMode = input('popover', ...(ngDevMode ? [{ debugName: "filterMode" }] : /* istanbul ignore next */ []));
|
|
446
1144
|
loading = input(false, { ...(ngDevMode ? { debugName: "loading" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
447
1145
|
updating = input(false, { ...(ngDevMode ? { debugName: "updating" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
448
1146
|
lazy = input(false, { ...(ngDevMode ? { debugName: "lazy" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
@@ -454,10 +1152,15 @@ class Table {
|
|
|
454
1152
|
storageKey = input(null, ...(ngDevMode ? [{ debugName: "storageKey" }] : /* istanbul ignore next */ []));
|
|
455
1153
|
storageMode = input('local', ...(ngDevMode ? [{ debugName: "storageMode" }] : /* istanbul ignore next */ []));
|
|
456
1154
|
exportable = input(false, { ...(ngDevMode ? { debugName: "exportable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1155
|
+
printable = input(false, { ...(ngDevMode ? { debugName: "printable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1156
|
+
groupable = input(false, { ...(ngDevMode ? { debugName: "groupable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1157
|
+
cellClickFilter = input(false, { ...(ngDevMode ? { debugName: "cellClickFilter" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1158
|
+
printTitle = input('', ...(ngDevMode ? [{ debugName: "printTitle" }] : /* istanbul ignore next */ []));
|
|
457
1159
|
exportFilename = input('download', ...(ngDevMode ? [{ debugName: "exportFilename" }] : /* istanbul ignore next */ []));
|
|
458
1160
|
actionShape = input('flat', ...(ngDevMode ? [{ debugName: "actionShape" }] : /* istanbul ignore next */ []));
|
|
459
1161
|
tableLayout = input('fixed', ...(ngDevMode ? [{ debugName: "tableLayout" }] : /* istanbul ignore next */ []));
|
|
460
1162
|
noCard = input(false, { ...(ngDevMode ? { debugName: "noCard" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
1163
|
+
dateFormat = inject(MTDateFormatPipe);
|
|
461
1164
|
// Tabs inputs and outputs
|
|
462
1165
|
tabs = input(...(ngDevMode ? [undefined, { debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
463
1166
|
tabsOptionLabel = input('label', ...(ngDevMode ? [{ debugName: "tabsOptionLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -477,13 +1180,44 @@ class Table {
|
|
|
477
1180
|
currentPage = model(0, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
|
|
478
1181
|
first = model(0, ...(ngDevMode ? [{ debugName: "first" }] : /* istanbul ignore next */ []));
|
|
479
1182
|
filterTerm = model('', ...(ngDevMode ? [{ debugName: "filterTerm" }] : /* istanbul ignore next */ []));
|
|
1183
|
+
groupBy = model(null, ...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
|
|
480
1184
|
sortField = signal(null, ...(ngDevMode ? [{ debugName: "sortField" }] : /* istanbul ignore next */ []));
|
|
481
1185
|
sortDirection = signal(null, ...(ngDevMode ? [{ debugName: "sortDirection" }] : /* istanbul ignore next */ []));
|
|
482
1186
|
confirmationService = inject(ConfirmationService);
|
|
1187
|
+
exportService = inject(TableExportService);
|
|
1188
|
+
grouping;
|
|
483
1189
|
selectedRowKeys = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedRowKeys" }] : /* istanbul ignore next */ []));
|
|
484
1190
|
transientSelectedRows = signal(new Set(), ...(ngDevMode ? [{ debugName: "transientSelectedRows" }] : /* istanbul ignore next */ []));
|
|
485
1191
|
hydratedStorageKey = signal(null, ...(ngDevMode ? [{ debugName: "hydratedStorageKey" }] : /* istanbul ignore next */ []));
|
|
486
1192
|
storageHydrated = signal(false, ...(ngDevMode ? [{ debugName: "storageHydrated" }] : /* istanbul ignore next */ []));
|
|
1193
|
+
isColumnFilterMode = computed(() => this.showFilters() && this.filterMode() === 'column', ...(ngDevMode ? [{ debugName: "isColumnFilterMode" }] : /* istanbul ignore next */ []));
|
|
1194
|
+
filterableColumnMap = computed(() => {
|
|
1195
|
+
if (!this.isColumnFilterMode()) {
|
|
1196
|
+
return new Map();
|
|
1197
|
+
}
|
|
1198
|
+
const data = this.data();
|
|
1199
|
+
const map = new Map();
|
|
1200
|
+
this.columns().forEach((col) => {
|
|
1201
|
+
if (TableValueResolver.getColumnFilterType(col, data[0]) === null) {
|
|
1202
|
+
return;
|
|
1203
|
+
}
|
|
1204
|
+
map.set(col.key, TableValueResolver.buildFilterableColumn(col, data));
|
|
1205
|
+
});
|
|
1206
|
+
return map;
|
|
1207
|
+
}, ...(ngDevMode ? [{ debugName: "filterableColumnMap" }] : /* istanbul ignore next */ []));
|
|
1208
|
+
getFilterableColumn(key) {
|
|
1209
|
+
return this.filterableColumnMap().get(key);
|
|
1210
|
+
}
|
|
1211
|
+
onColumnFilterChange(key, value) {
|
|
1212
|
+
const next = { ...this.filters() };
|
|
1213
|
+
if (value === null || value === undefined) {
|
|
1214
|
+
delete next[key];
|
|
1215
|
+
}
|
|
1216
|
+
else {
|
|
1217
|
+
next[key] = value;
|
|
1218
|
+
}
|
|
1219
|
+
this.onFilterApplied(next);
|
|
1220
|
+
}
|
|
487
1221
|
activeFilterCount = computed(() => {
|
|
488
1222
|
const filters = this.filters();
|
|
489
1223
|
return Object.values(filters).filter((value) => value !== null && value !== undefined && value !== '').length;
|
|
@@ -546,7 +1280,12 @@ class Table {
|
|
|
546
1280
|
return false;
|
|
547
1281
|
return pageData.every((row) => this.isRowSelected(row));
|
|
548
1282
|
}, ...(ngDevMode ? [{ debugName: "allSelectedOnPage" }] : /* istanbul ignore next */ []));
|
|
1283
|
+
totalColumnSpan = computed(() => this.renderedColumns().length +
|
|
1284
|
+
(this.reorderableRows() ? 1 : 0) +
|
|
1285
|
+
(this.selectableRows() ? 1 : 0) +
|
|
1286
|
+
(this.rowActions().length > 0 ? 1 : 0), ...(ngDevMode ? [{ debugName: "totalColumnSpan" }] : /* istanbul ignore next */ []));
|
|
549
1287
|
constructor() {
|
|
1288
|
+
this.grouping = new TableGroupingController(this.columns, this.filteredData, this.groupBy, this.sortField, this.sortDirection);
|
|
550
1289
|
effect(() => {
|
|
551
1290
|
const storageKey = this.getNormalizedStorageKey();
|
|
552
1291
|
const storage = this.getStorage();
|
|
@@ -580,6 +1319,27 @@ class Table {
|
|
|
580
1319
|
}
|
|
581
1320
|
this.writePersistedState(storage, storageKey, this.buildPersistedState());
|
|
582
1321
|
});
|
|
1322
|
+
// Drop filters / groupBy whose column no longer exists. Dynamic tables
|
|
1323
|
+
// (e.g. runtime schemas) can drop columns between fetches, which would
|
|
1324
|
+
// otherwise strand a filter the user can't clear from the UI.
|
|
1325
|
+
effect(() => {
|
|
1326
|
+
const columns = this.columns();
|
|
1327
|
+
if (columns.length === 0 || this.loading()) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const validKeys = new Set(columns.map((c) => c.key));
|
|
1331
|
+
const currentFilters = this.filters();
|
|
1332
|
+
const staleFilterKeys = Object.keys(currentFilters).filter((key) => key !== 'generalSearch' && !validKeys.has(key));
|
|
1333
|
+
if (staleFilterKeys.length > 0) {
|
|
1334
|
+
const next = { ...currentFilters };
|
|
1335
|
+
staleFilterKeys.forEach((key) => delete next[key]);
|
|
1336
|
+
this.filters.set(next);
|
|
1337
|
+
}
|
|
1338
|
+
const currentGroup = this.groupBy();
|
|
1339
|
+
if (currentGroup && !validKeys.has(currentGroup)) {
|
|
1340
|
+
this.groupBy.set(null);
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
583
1343
|
effect(() => {
|
|
584
1344
|
if (this.lazy()) {
|
|
585
1345
|
return;
|
|
@@ -620,65 +1380,8 @@ class Table {
|
|
|
620
1380
|
}
|
|
621
1381
|
}
|
|
622
1382
|
matchesFilter(item, key, filterValue) {
|
|
623
|
-
if (filterValue === null ||
|
|
624
|
-
filterValue === undefined ||
|
|
625
|
-
filterValue === '') {
|
|
626
|
-
return true;
|
|
627
|
-
}
|
|
628
1383
|
const column = this.columns().find((col) => col.key === key);
|
|
629
|
-
|
|
630
|
-
const normalizedFilterValue = column
|
|
631
|
-
? TableValueResolver.getColumnFilterValue(item, column)
|
|
632
|
-
: TableValueResolver.resolveDisplayValue(itemValue);
|
|
633
|
-
const filterType = column
|
|
634
|
-
? TableValueResolver.getColumnFilterType(column, item)
|
|
635
|
-
: null;
|
|
636
|
-
// Date range filter
|
|
637
|
-
if (typeof filterValue === 'object') {
|
|
638
|
-
if (filterValue.from || filterValue.to) {
|
|
639
|
-
const itemDateValue = filterType === 'date'
|
|
640
|
-
? typeof normalizedFilterValue === 'number'
|
|
641
|
-
? normalizedFilterValue
|
|
642
|
-
: null
|
|
643
|
-
: itemValue instanceof Date
|
|
644
|
-
? itemValue.getTime()
|
|
645
|
-
: new Date(String(itemValue)).getTime();
|
|
646
|
-
if (itemDateValue === null ||
|
|
647
|
-
itemDateValue === undefined ||
|
|
648
|
-
Number.isNaN(itemDateValue)) {
|
|
649
|
-
return true;
|
|
650
|
-
}
|
|
651
|
-
if (filterValue.from &&
|
|
652
|
-
itemDateValue < new Date(filterValue.from).getTime()) {
|
|
653
|
-
return false;
|
|
654
|
-
}
|
|
655
|
-
if (filterValue.to &&
|
|
656
|
-
itemDateValue > new Date(filterValue.to).getTime()) {
|
|
657
|
-
return false;
|
|
658
|
-
}
|
|
659
|
-
return true;
|
|
660
|
-
}
|
|
661
|
-
else if (filterValue?.userName) {
|
|
662
|
-
const normalizedItemUser = itemValue;
|
|
663
|
-
if (!normalizedItemUser)
|
|
664
|
-
return false;
|
|
665
|
-
return (normalizedItemUser.id === filterValue?.id ||
|
|
666
|
-
normalizedItemUser.userName === filterValue?.userName ||
|
|
667
|
-
normalizedItemUser.displayName === filterValue?.displayName);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
// Boolean filter
|
|
671
|
-
if (typeof filterValue === 'boolean') {
|
|
672
|
-
return normalizedFilterValue === filterValue;
|
|
673
|
-
}
|
|
674
|
-
// Text filter
|
|
675
|
-
if (typeof normalizedFilterValue === 'string' ||
|
|
676
|
-
typeof normalizedFilterValue === 'number') {
|
|
677
|
-
return String(normalizedFilterValue)
|
|
678
|
-
.toLowerCase()
|
|
679
|
-
.includes(String(filterValue).toLowerCase());
|
|
680
|
-
}
|
|
681
|
-
return normalizedFilterValue === filterValue;
|
|
1384
|
+
return TableValueResolver.matchesFilter(item, key, filterValue, column);
|
|
682
1385
|
}
|
|
683
1386
|
toggleRow(row) {
|
|
684
1387
|
const rowKey = this.getRowSelectionKey(row);
|
|
@@ -747,6 +1450,20 @@ class Table {
|
|
|
747
1450
|
}
|
|
748
1451
|
return null;
|
|
749
1452
|
}
|
|
1453
|
+
/**
|
|
1454
|
+
* Entity data resolver that abstracts over the `user` / `status` vs `entity`
|
|
1455
|
+
* distinction — used by the shared filterable-cell template so the three
|
|
1456
|
+
* cases don't duplicate markup.
|
|
1457
|
+
*/
|
|
1458
|
+
resolveCellEntityData(row, col) {
|
|
1459
|
+
if (col.type === 'entity') {
|
|
1460
|
+
return this.getEntityColumnData(row, col);
|
|
1461
|
+
}
|
|
1462
|
+
if (col.type === 'user' || col.type === 'status') {
|
|
1463
|
+
return this.getEntityPreviewData(row, col);
|
|
1464
|
+
}
|
|
1465
|
+
return null;
|
|
1466
|
+
}
|
|
750
1467
|
tabChanged(tab) {
|
|
751
1468
|
this.filterTerm.set('');
|
|
752
1469
|
this.first.set(0);
|
|
@@ -787,10 +1504,26 @@ class Table {
|
|
|
787
1504
|
if (this.sortField() !== column.key) {
|
|
788
1505
|
this.sortField.set(column.key);
|
|
789
1506
|
this.sortDirection.set('asc');
|
|
1507
|
+
return;
|
|
790
1508
|
}
|
|
791
|
-
|
|
792
|
-
|
|
1509
|
+
const direction = this.sortDirection();
|
|
1510
|
+
if (direction === 'asc') {
|
|
1511
|
+
this.sortDirection.set('desc');
|
|
1512
|
+
return;
|
|
793
1513
|
}
|
|
1514
|
+
if (direction === 'desc') {
|
|
1515
|
+
// Tri-state reset. PrimeNG subheader grouping breaks without a matching
|
|
1516
|
+
// sort, so when this column is the active group we wrap to 'asc' instead.
|
|
1517
|
+
if (this.grouping.isGroupLockedSort(column.key)) {
|
|
1518
|
+
this.sortDirection.set('asc');
|
|
1519
|
+
}
|
|
1520
|
+
else {
|
|
1521
|
+
this.sortField.set(null);
|
|
1522
|
+
this.sortDirection.set(null);
|
|
1523
|
+
}
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
this.sortDirection.set('asc');
|
|
794
1527
|
}
|
|
795
1528
|
isColumnSortable(column) {
|
|
796
1529
|
return column.sortable === true && (!this.lazy() || this.lazyLocalSort());
|
|
@@ -863,11 +1596,69 @@ class Table {
|
|
|
863
1596
|
if (this.loading()) {
|
|
864
1597
|
return;
|
|
865
1598
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
1599
|
+
this.exportService.exportToExcel({
|
|
1600
|
+
rows: this.filteredData(),
|
|
1601
|
+
columns: this.columns(),
|
|
1602
|
+
filename: this.exportFilename(),
|
|
1603
|
+
resolveValue: (row, column) => this.getColumnExportValue(row, column),
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
printPdf() {
|
|
1607
|
+
if (this.loading()) {
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
this.exportService.printPdf({
|
|
1611
|
+
rows: this.filteredData(),
|
|
1612
|
+
columns: this.columns(),
|
|
1613
|
+
filename: this.exportFilename(),
|
|
1614
|
+
title: this.printTitle() || undefined,
|
|
1615
|
+
resolveValue: (row, column) => this.getColumnExportValue(row, column),
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
onCellFilterClick(event, row, column) {
|
|
1619
|
+
if (!this.cellClickFilter())
|
|
1620
|
+
return;
|
|
1621
|
+
const next = TableValueResolver.buildClickFilterValue(row, column);
|
|
1622
|
+
if (next === null || next === undefined)
|
|
1623
|
+
return;
|
|
1624
|
+
event.stopPropagation();
|
|
1625
|
+
const current = this.filters();
|
|
1626
|
+
const patched = { ...current };
|
|
1627
|
+
if (TableValueResolver.isFilterValueEqual(current[column.key], next)) {
|
|
1628
|
+
delete patched[column.key];
|
|
1629
|
+
}
|
|
1630
|
+
else {
|
|
1631
|
+
patched[column.key] = next;
|
|
1632
|
+
}
|
|
1633
|
+
this.onFilterApplied(patched);
|
|
1634
|
+
}
|
|
1635
|
+
isCellFilterActive(row, column) {
|
|
1636
|
+
if (!this.cellClickFilter())
|
|
1637
|
+
return false;
|
|
1638
|
+
const current = this.filters()[column.key];
|
|
1639
|
+
if (current === null || current === undefined)
|
|
1640
|
+
return false;
|
|
1641
|
+
const next = TableValueResolver.buildClickFilterValue(row, column);
|
|
1642
|
+
if (next === null || next === undefined)
|
|
1643
|
+
return false;
|
|
1644
|
+
return TableValueResolver.isFilterValueEqual(current, next);
|
|
1645
|
+
}
|
|
1646
|
+
isCellClickFilterable(column, row) {
|
|
1647
|
+
if (!this.cellClickFilter())
|
|
1648
|
+
return false;
|
|
1649
|
+
if (column.type === 'boolean') {
|
|
1650
|
+
// Editable booleans keep the toggle interaction; only readonly ones filter.
|
|
1651
|
+
return column.readonly === true;
|
|
1652
|
+
}
|
|
1653
|
+
if (column.type === 'status' || column.type === 'user')
|
|
1654
|
+
return true;
|
|
1655
|
+
if (column.type === 'entity') {
|
|
1656
|
+
const filterType = TableValueResolver.getColumnFilterType(column, row);
|
|
1657
|
+
return (filterType === 'select' ||
|
|
1658
|
+
filterType === 'user' ||
|
|
1659
|
+
filterType === 'boolean');
|
|
1660
|
+
}
|
|
1661
|
+
return false;
|
|
871
1662
|
}
|
|
872
1663
|
rowAction(event, action, row) {
|
|
873
1664
|
if (!action.confirmation) {
|
|
@@ -1210,6 +2001,57 @@ class Table {
|
|
|
1210
2001
|
}
|
|
1211
2002
|
return TableValueResolver.normalizeTextSortValue(resolvedValue);
|
|
1212
2003
|
}
|
|
2004
|
+
/**
|
|
2005
|
+
* Export/print value resolver — same pipeline as `getColumnResolvedValue`
|
|
2006
|
+
* except date / dateTime columns (and their entity counterparts) are
|
|
2007
|
+
* formatted via the MT date pipe so Excel and PDF show locale-aware dates
|
|
2008
|
+
* instead of raw ISO strings. Sort path keeps the ISO form for ordering.
|
|
2009
|
+
*/
|
|
2010
|
+
getColumnExportValue(row, column) {
|
|
2011
|
+
const cellValue = this.getProperty(row, column.key);
|
|
2012
|
+
if (cellValue === null || cellValue === undefined)
|
|
2013
|
+
return null;
|
|
2014
|
+
const dateType = this.resolveDateColumnType(column, row);
|
|
2015
|
+
if (dateType) {
|
|
2016
|
+
const dateValue = TableValueResolver.resolveDateValue(column.type === 'entity'
|
|
2017
|
+
? TableValueResolver.getEntityValueByType(cellValue, 'sort')
|
|
2018
|
+
: cellValue);
|
|
2019
|
+
if (dateValue === null)
|
|
2020
|
+
return null;
|
|
2021
|
+
const formatted = this.dateFormat.transform(dateValue, dateType);
|
|
2022
|
+
return formatted || null;
|
|
2023
|
+
}
|
|
2024
|
+
return this.getColumnResolvedValue(row, column);
|
|
2025
|
+
}
|
|
2026
|
+
/**
|
|
2027
|
+
* Detects whether a column should be treated as a date for export purposes:
|
|
2028
|
+
* native `date` / `dateTime` types, or entity columns whose viewType is
|
|
2029
|
+
* `Date` / `DateTime`.
|
|
2030
|
+
*/
|
|
2031
|
+
resolveDateColumnType(column, row) {
|
|
2032
|
+
if (column.type === 'date')
|
|
2033
|
+
return 'date';
|
|
2034
|
+
if (column.type === 'dateTime')
|
|
2035
|
+
return 'dateTime';
|
|
2036
|
+
if (column.type === 'entity') {
|
|
2037
|
+
const filterType = TableValueResolver.getColumnFilterType(column, row);
|
|
2038
|
+
if (filterType !== 'date')
|
|
2039
|
+
return null;
|
|
2040
|
+
const viewType = column.viewType;
|
|
2041
|
+
if (typeof viewType === 'string' &&
|
|
2042
|
+
viewType.toLowerCase() === 'datetime') {
|
|
2043
|
+
return 'dateTime';
|
|
2044
|
+
}
|
|
2045
|
+
const cellValue = this.getProperty(row, column.key);
|
|
2046
|
+
if (cellValue &&
|
|
2047
|
+
typeof cellValue === 'object' &&
|
|
2048
|
+
cellValue.viewType === 'DateTime') {
|
|
2049
|
+
return 'dateTime';
|
|
2050
|
+
}
|
|
2051
|
+
return 'date';
|
|
2052
|
+
}
|
|
2053
|
+
return null;
|
|
2054
|
+
}
|
|
1213
2055
|
getColumnResolvedValue(row, column) {
|
|
1214
2056
|
const cellValue = this.getProperty(row, column.key);
|
|
1215
2057
|
if (cellValue === null || cellValue === undefined) {
|
|
@@ -1233,28 +2075,6 @@ class Table {
|
|
|
1233
2075
|
}
|
|
1234
2076
|
return TableValueResolver.resolveDisplayValue(cellValue);
|
|
1235
2077
|
}
|
|
1236
|
-
buildExportRows(rows, columns) {
|
|
1237
|
-
return rows.map((row) => {
|
|
1238
|
-
const exportRow = {};
|
|
1239
|
-
columns.forEach((column) => {
|
|
1240
|
-
exportRow[column.key] =
|
|
1241
|
-
column.type === 'entity'
|
|
1242
|
-
? TableValueResolver.getEntityValueByType(this.getProperty(row, column.key), 'export')
|
|
1243
|
-
: this.getColumnResolvedValue(row, column);
|
|
1244
|
-
});
|
|
1245
|
-
return exportRow;
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
buildExcelRows(rows, columns) {
|
|
1249
|
-
const exportRows = this.buildExportRows(rows, columns);
|
|
1250
|
-
return exportRows.map((row) => {
|
|
1251
|
-
const excelRow = {};
|
|
1252
|
-
columns.forEach((column) => {
|
|
1253
|
-
excelRow[column.label] = row[column.key] ?? null;
|
|
1254
|
-
});
|
|
1255
|
-
return excelRow;
|
|
1256
|
-
});
|
|
1257
|
-
}
|
|
1258
2078
|
isRowSelected(row) {
|
|
1259
2079
|
const rowKey = this.getRowSelectionKey(row);
|
|
1260
2080
|
if (rowKey !== null) {
|
|
@@ -1298,10 +2118,6 @@ class Table {
|
|
|
1298
2118
|
const storageKey = this.storageKey()?.trim();
|
|
1299
2119
|
return storageKey ? storageKey : null;
|
|
1300
2120
|
}
|
|
1301
|
-
normalizeExportFilename(value) {
|
|
1302
|
-
const sanitized = value.trim().replace(/[\\/:*?"<>|]+/g, '-');
|
|
1303
|
-
return sanitized.length ? sanitized : 'download';
|
|
1304
|
-
}
|
|
1305
2121
|
getStorage() {
|
|
1306
2122
|
if (typeof window === 'undefined') {
|
|
1307
2123
|
return null;
|
|
@@ -1320,6 +2136,7 @@ class Table {
|
|
|
1320
2136
|
sortField: this.sortField(),
|
|
1321
2137
|
sortDirection: this.sortDirection(),
|
|
1322
2138
|
selectedRowKeys: this.dataKey() ? Array.from(this.selectedRowKeys()) : [],
|
|
2139
|
+
groupBy: this.groupBy(),
|
|
1323
2140
|
};
|
|
1324
2141
|
}
|
|
1325
2142
|
applyPersistedState(persistedState) {
|
|
@@ -1359,6 +2176,9 @@ class Table {
|
|
|
1359
2176
|
this.selectedRowKeys.set(new Set(Array.isArray(persistedState.selectedRowKeys)
|
|
1360
2177
|
? persistedState.selectedRowKeys
|
|
1361
2178
|
: []));
|
|
2179
|
+
this.groupBy.set(typeof persistedState.groupBy === 'string' && persistedState.groupBy
|
|
2180
|
+
? persistedState.groupBy
|
|
2181
|
+
: null);
|
|
1362
2182
|
}
|
|
1363
2183
|
shouldEmitLazyLoadAfterRestore(persistedState) {
|
|
1364
2184
|
if (!persistedState) {
|
|
@@ -1416,35 +2236,34 @@ class Table {
|
|
|
1416
2236
|
return Math.trunc(normalized);
|
|
1417
2237
|
}
|
|
1418
2238
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: Table, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1419
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: Table, isStandalone: true, selector: "mt-table", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showGridlines: { classPropertyName: "showGridlines", publicName: "showGridlines", isSignal: true, isRequired: false, transformFunction: null }, stripedRows: { classPropertyName: "stripedRows", publicName: "stripedRows", isSignal: true, isRequired: false, transformFunction: null }, selectableRows: { classPropertyName: "selectableRows", publicName: "selectableRows", isSignal: true, isRequired: false, transformFunction: null }, clickableRows: { classPropertyName: "clickableRows", publicName: "clickableRows", isSignal: true, isRequired: false, transformFunction: null }, generalSearch: { classPropertyName: "generalSearch", publicName: "generalSearch", isSignal: true, isRequired: false, transformFunction: null }, lazyLocalSearch: { classPropertyName: "lazyLocalSearch", publicName: "lazyLocalSearch", isSignal: true, isRequired: false, transformFunction: null }, showFilters: { classPropertyName: "showFilters", publicName: "showFilters", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, updating: { classPropertyName: "updating", publicName: "updating", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, lazyLocalSort: { classPropertyName: "lazyLocalSort", publicName: "lazyLocalSort", isSignal: true, isRequired: false, transformFunction: null }, lazyTotalRecords: { classPropertyName: "lazyTotalRecords", publicName: "lazyTotalRecords", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableRows: { classPropertyName: "reorderableRows", publicName: "reorderableRows", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null }, storageMode: { classPropertyName: "storageMode", publicName: "storageMode", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, exportFilename: { classPropertyName: "exportFilename", publicName: "exportFilename", isSignal: true, isRequired: false, transformFunction: null }, actionShape: { classPropertyName: "actionShape", publicName: "actionShape", isSignal: true, isRequired: false, transformFunction: null }, tableLayout: { classPropertyName: "tableLayout", publicName: "tableLayout", isSignal: true, isRequired: false, transformFunction: null }, noCard: { classPropertyName: "noCard", publicName: "noCard", isSignal: true, isRequired: false, transformFunction: null }, tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, tabsOptionLabel: { classPropertyName: "tabsOptionLabel", publicName: "tabsOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, tabsOptionValue: { classPropertyName: "tabsOptionValue", publicName: "tabsOptionValue", isSignal: true, isRequired: false, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, paginatorPosition: { classPropertyName: "paginatorPosition", publicName: "paginatorPosition", isSignal: true, isRequired: false, transformFunction: null }, alwaysShowPaginator: { classPropertyName: "alwaysShowPaginator", publicName: "alwaysShowPaginator", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, currentPage: { classPropertyName: "currentPage", publicName: "currentPage", isSignal: true, isRequired: false, transformFunction: null }, first: { classPropertyName: "first", publicName: "first", isSignal: true, isRequired: false, transformFunction: null }, filterTerm: { classPropertyName: "filterTerm", publicName: "filterTerm", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", cellChange: "cellChange", lazyLoad: "lazyLoad", columnReorder: "columnReorder", rowReorder: "rowReorder", rowClick: "rowClick", filters: "filtersChange", activeTab: "activeTabChange", onTabChange: "onTabChange", pageSize: "pageSizeChange", currentPage: "currentPageChange", first: "firstChange", filterTerm: "filterTermChange" }, queries: [{ propertyName: "captionStartContent", first: true, predicate: ["captionStart"], descendants: true, isSignal: true }, { propertyName: "captionEndContent", first: true, predicate: ["captionEnd"], descendants: true, isSignal: true }, { propertyName: "emptyContent", first: true, predicate: ["empty"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!noCard()) {\r\n <mt-card>\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </mt-card>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"space-y-4 rounded-lg\">\r\n <div>\r\n @if (\r\n captionStartContent() ||\r\n captionEndContent() ||\r\n generalSearch() ||\r\n showFilters() ||\r\n tabs()?.length > 0 ||\r\n actions()?.length > 0\r\n ) {\r\n <div class=\"p-datatable-header rounded-t-2xl\">\r\n <div\r\n class=\"flex relative\"\r\n [class]=\"!generalSearch() ? 'justify-end' : 'justify-between'\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"captionStartContent()\"\r\n ></ng-container>\r\n @if (tabs()) {\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabs()\"\r\n [optionLabel]=\"tabsOptionLabel()\"\r\n [optionValue]=\"tabsOptionValue()\"\r\n (onChange)=\"tabChanged($event)\"\r\n size=\"large\"\r\n ></mt-tabs>\r\n }\r\n @if (generalSearch()) {\r\n <mt-text-field\r\n [(ngModel)]=\"filterTerm\"\r\n (ngModelChange)=\"onSearchChange($event)\"\r\n icon=\"general.search-lg\"\r\n [placeholder]=\"'components.table.search' | transloco\"\r\n ></mt-text-field>\r\n }\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n @if (showFilters()) {\r\n <mt-table-filter\r\n [columns]=\"columns()\"\r\n [data]=\"data()\"\r\n [ngModel]=\"filters()\"\r\n (filterApplied)=\"onFilterApplied($event)\"\r\n (filterReset)=\"onFilterReset()\"\r\n />\r\n }\r\n @if (exportable()) {\r\n <mt-button\r\n icon=\"file.file-x-03\"\r\n styleClass=\"text-xl! py-1.5!\"\r\n severity=\"success\"\r\n variant=\"outlined\"\r\n [tooltip]=\"'components.table.export' | transloco\"\r\n (click)=\"exportExcel()\"\r\n />\r\n }\r\n @if (actions()?.length > 0) {\r\n <div class=\"flex items-center space-x-2\">\r\n @for (action of actions(); track action.label) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"action.size\"\r\n (click)=\"action.action(row)\"\r\n [label]=\"action.label\"\r\n [tooltip]=\"action.tooltip\"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n <ng-container\r\n *ngTemplateOutlet=\"captionEndContent()\"\r\n ></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n @if (!loading() && emptyContent() && data().length === 0) {\r\n <div\r\n class=\"p-4 bg-content rounded-md text-center text-gray-600 dark:text-gray-300\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"emptyContent()\"></ng-container>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"overflow-x-auto rounded-[10px] border border-surface-200 bg-white\"\r\n >\r\n <p-table\r\n [value]=\"displayData()\"\r\n [columns]=\"renderedColumns()\"\r\n [size]=\"size()\"\r\n [showGridlines]=\"showGridlines()\"\r\n [stripedRows]=\"stripedRows()\"\r\n [lazy]=\"lazy()\"\r\n [totalRecords]=\"totalRecords()\"\r\n [reorderableColumns]=\"reorderableColumns()\"\r\n [reorderableRows]=\"reorderableRows()\"\r\n [dataKey]=\"dataKey()\"\r\n [first]=\"first()\"\r\n [rows]=\"pageSize()\"\r\n [exportFilename]=\"exportFilename()\"\r\n (onPage)=\"onTablePage($event)\"\r\n (onLazyLoad)=\"handleLazyLoad($event)\"\r\n (onColReorder)=\"onColumnReorder($event)\"\r\n (onRowReorder)=\"onRowReorder($event)\"\r\n paginator\r\n paginatorStyleClass=\"hidden!\"\r\n class=\"mt-table min-w-full align-middle text-sm\"\r\n [class.table-auto]=\"tableLayout() === 'auto'\"\r\n [class.table-fixed]=\"tableLayout() === 'fixed'\"\r\n >\r\n <ng-template\r\n #header\r\n let-columns\r\n class=\"bg-surface-50 dark:bg-surface-950 border-b border-surface-300 dark:border-surface-500\"\r\n >\r\n <tr>\r\n @if (reorderableRows()) {\r\n <th class=\"w-10\"></th>\r\n }\r\n @if (selectableRows()) {\r\n <th class=\"w-12 text-start\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelectedOnPage()\"\r\n (ngModelChange)=\"toggleAllRowsOnPage()\"\r\n ></mt-checkbox-field>\r\n </th>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n @if (reorderableColumns()) {\r\n <th\r\n pReorderableColumn\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n {{ col.label }}\r\n <!-- <mt-icon-->\r\n <!-- icon=\"general.menu-05\"-->\r\n <!-- class=\"text-xs text-gray-400\"-->\r\n <!-- ></mt-icon>-->\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n </div>\r\n </th>\r\n } @else {\r\n <th\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n @if (isColumnSortable(col)) {\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex items-center gap-2 cursor-pointer\"\r\n (click)=\"toggleSort(col)\"\r\n >\r\n <span>{{ col.label }}</span>\r\n <mt-icon\r\n [icon]=\"getSortIcon(col)\"\r\n class=\"text-xs text-gray-400\"\r\n />\r\n </button>\r\n } @else {\r\n {{ col.label }}\r\n }\r\n </th>\r\n }\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <th class=\"text-end! text-sm font-normal text-[#323232]\">\r\n {{ \"components.table.actions\" | transloco }}\r\n </th>\r\n }\r\n </tr>\r\n @if (updating()) {\r\n <tr>\r\n <th\r\n [attr.colspan]=\"\r\n columns.length +\r\n (reorderableRows() ? 1 : 0) +\r\n (selectableRows() ? 1 : 0) +\r\n (rowActions().length > 0 ? 1 : 0)\r\n \"\r\n class=\"!p-0\"\r\n >\r\n <p-progressBar\r\n mode=\"indeterminate\"\r\n [style]=\"{ height: '4px' }\"\r\n />\r\n </th>\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template\r\n #body\r\n let-row\r\n let-columns=\"columns\"\r\n let-index=\"rowIndex\"\r\n class=\"divide-y divide-gray-200\"\r\n >\r\n @if (loading()) {\r\n <tr>\r\n @if (reorderableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (selectableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (rowActions().length > 0) {\r\n <td><p-skeleton /></td>\r\n }\r\n </tr>\r\n } @else {\r\n <tr\r\n class=\"border-surface-300 transition-colors duration-150 dark:border-surface-500\"\r\n [class.mt-table-clickable-row]=\"clickableRows()\"\r\n [class.mt-table-status-entity-row]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [style.--mt-table-status-accent]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [class.cursor-pointer]=\"clickableRows()\"\r\n [pReorderableRow]=\"index\"\r\n (click)=\"onRowClick($event, row)\"\r\n >\r\n @if (reorderableRows()) {\r\n <td class=\"w-10 text-center\">\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n pReorderableRowHandle\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n <!-- <mt-icon-->\r\n <!-- icon=\"general.menu-05\"-->\r\n <!-- class=\"cursor-move text-gray-500\"-->\r\n <!-- pReorderableRowHandle-->\r\n <!-- ></mt-icon>-->\r\n </td>\r\n }\r\n @if (selectableRows()) {\r\n <td class=\"w-12\">\r\n <mt-checkbox-field\r\n [ngModel]=\"isRowSelected(row)\"\r\n (ngModelChange)=\"toggleRow(row)\"\r\n ></mt-checkbox-field>\r\n </td>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td\r\n class=\"text-sm font-normal text-[#4b4b4b]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n @switch (col.type) {\r\n @case (\"boolean\") {\r\n <mt-toggle-field\r\n disabled=\"col.readonly\"\r\n [ngModel]=\"getBooleanProperty(row, col.key)\"\r\n (ngModelChange)=\"\r\n onCellChange(row, col.key, $event, 'boolean')\r\n \"\r\n ></mt-toggle-field>\r\n }\r\n @case (\"date\") {\r\n {{\r\n getDateProperty(row, col.key) | mtDateFormat: \"date\"\r\n }}\r\n }\r\n @case (\"dateTime\") {\r\n {{\r\n getDateProperty(row, col.key)\r\n | mtDateFormat: \"dateTime\"\r\n }}\r\n }\r\n @case (\"user\") {\r\n @if (getEntityPreviewData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n @case (\"status\") {\r\n @if (getEntityPreviewData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n @case (\"entity\") {\r\n @if (getEntityColumnData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n @case (\"custom\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n col.customCellTpl;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n }\r\n @default {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n </td>\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <td class=\"text-right\">\r\n @if (actionShape() === \"popover\") {\r\n <div class=\"flex items-center justify-end\">\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n size=\"large\"\r\n (click)=\"rowPopover.toggle($event)\"\r\n data-row-click-ignore=\"true\"\r\n ></mt-button>\r\n <p-popover #rowPopover appendTo=\"body\">\r\n <div class=\"flex flex-col min-w-40\">\r\n @for (\r\n action of getVisibleRowActions(row);\r\n track $index\r\n ) {\r\n <button\r\n class=\"flex items-center gap-2 px-2 cursor-pointer py-2 text-sm rounded transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n rowAction($event, action, row);\r\n rowPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon\r\n [icon]=\"action.icon\"\r\n class=\"text-base\"\r\n />\r\n }\r\n <span>{{\r\n action.label || action.tooltip\r\n }}</span>\r\n </button>\r\n }\r\n </div>\r\n </p-popover>\r\n </div>\r\n } @else {\r\n <div class=\"flex items-center justify-end space-x-2\">\r\n @for (action of rowActions(); track $index) {\r\n @let hidden = action.hidden?.(row);\r\n @if (!hidden) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"action.size || 'small'\"\r\n (click)=\"rowAction($event, action, row)\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, row)\"\r\n ></mt-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td\r\n [attr.colspan]=\"\r\n renderedColumns().length +\r\n (reorderableRows() ? 1 : 0) +\r\n (selectableRows() ? 1 : 0) +\r\n (rowActions().length > 0 ? 1 : 0)\r\n \"\r\n class=\"text-center\"\r\n >\r\n <div\r\n class=\"flex min-h-44 flex-col items-center justify-center gap-3 py-8 text-center\"\r\n >\r\n <svg\r\n width=\"152\"\r\n height=\"120\"\r\n viewBox=\"0 0 152 120\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"76\" cy=\"52\" r=\"52\" fill=\"#E9EAEB\" />\r\n <g filter=\"url(#filter0_ddd_2474_28277)\">\r\n <path\r\n d=\"M77.6 16C66.8273 16 57.2978 21.3233 51.4987 29.4829C49.605 29.0363 47.6301 28.8 45.6 28.8C31.4615 28.8 20 40.2615 20 54.4C20 68.5385 31.4615 80 45.6 80L109.6 80C121.971 80 132 69.9712 132 57.6C132 45.2288 121.971 35.2 109.6 35.2C108.721 35.2 107.854 35.2506 107.002 35.349C102.098 23.9677 90.7797 16 77.6 16Z\"\r\n fill=\"#FAFAFA\"\r\n />\r\n <ellipse\r\n cx=\"45.6\"\r\n cy=\"54.3998\"\r\n rx=\"25.6\"\r\n ry=\"25.6\"\r\n fill=\"url(#paint0_linear_2474_28277)\"\r\n />\r\n <circle\r\n cx=\"77.6016\"\r\n cy=\"48\"\r\n r=\"32\"\r\n fill=\"url(#paint1_linear_2474_28277)\"\r\n />\r\n <ellipse\r\n cx=\"109.599\"\r\n cy=\"57.6002\"\r\n rx=\"22.4\"\r\n ry=\"22.4\"\r\n fill=\"url(#paint2_linear_2474_28277)\"\r\n />\r\n </g>\r\n <circle cx=\"21\" cy=\"19\" r=\"5\" fill=\"#F5F5F5\" />\r\n <circle cx=\"18\" cy=\"109\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"145\" cy=\"35\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"134\" cy=\"8\" r=\"4\" fill=\"#F5F5F5\" />\r\n <foreignObject x=\"44\" y=\"54\" width=\"64\" height=\"64\">\r\n <div\r\n xmlns=\"http://www.w3.org/1999/xhtml\"\r\n style=\"\r\n backdrop-filter: blur(4px);\r\n clip-path: url(#bgblur_0_2474_28277_clip_path);\r\n height: 100%;\r\n width: 100%;\r\n \"\r\n ></div>\r\n </foreignObject>\r\n <g data-figma-bg-blur-radius=\"8\">\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n fill=\"#344054\"\r\n fill-opacity=\"0.4\"\r\n />\r\n <path\r\n d=\"M85 95L81.5001 91.5M84 85.5C84 90.1944 80.1944 94 75.5 94C70.8056 94 67 90.1944 67 85.5C67 80.8056 70.8056 77 75.5 77C80.1944 77 84 80.8056 84 85.5Z\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_ddd_2474_28277\"\r\n x=\"0\"\r\n y=\"16\"\r\n width=\"152\"\r\n height=\"104\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood\r\n flood-opacity=\"0\"\r\n result=\"BackgroundImageFix\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"1.5\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"3\" />\r\n <feGaussianBlur stdDeviation=\"1.5\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"8\" />\r\n <feGaussianBlur stdDeviation=\"4\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect1_dropShadow_2474_28277\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"20\" />\r\n <feGaussianBlur stdDeviation=\"12\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect2_dropShadow_2474_28277\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect3_dropShadow_2474_28277\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath\r\n id=\"bgblur_0_2474_28277_clip_path\"\r\n transform=\"translate(-44 -54)\"\r\n >\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n />\r\n </clipPath>\r\n <linearGradient\r\n id=\"paint0_linear_2474_28277\"\r\n x1=\"25.9429\"\r\n y1=\"37.4855\"\r\n x2=\"71.2\"\r\n y2=\"79.9998\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint1_linear_2474_28277\"\r\n x1=\"53.0301\"\r\n y1=\"26.8571\"\r\n x2=\"109.602\"\r\n y2=\"80\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint2_linear_2474_28277\"\r\n x1=\"92.3992\"\r\n y1=\"42.8002\"\r\n x2=\"131.999\"\r\n y2=\"80.0002\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n <p class=\"m-0 text-base font-medium text-surface-500\">\r\n {{ \"components.table.no-data-found\" | transloco }}\r\n </p>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"flex flex-col gap-3 pb-3 px-4\"\r\n [class]=\"'items-' + paginatorPosition()\"\r\n >\r\n <mt-paginator\r\n [(rows)]=\"pageSize\"\r\n [(first)]=\"first\"\r\n [(page)]=\"currentPage\"\r\n [totalRecords]=\"totalRecords()\"\r\n [alwaysShow]=\"alwaysShowPaginator()\"\r\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\r\n (onPageChange)=\"onPaginatorPage($event)\"\r\n ></mt-paginator>\r\n </div>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .p-datatable-header{padding:0 0 1.5rem;background:transparent;border:0}:host ::ng-deep .p-datatable-table{border-collapse:separate;border-spacing:0}:host ::ng-deep .p-datatable-thead>tr>th{padding:.9rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#323232;font-size:14px;font-weight:400;line-height:20px;white-space:nowrap}:host ::ng-deep .p-datatable-tbody>tr>td{padding:.72rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#4b4b4b;font-size:14px;font-weight:400;line-height:20px;vertical-align:middle}:host ::ng-deep .p-datatable-tbody>tr:last-child>td{border-bottom:0}:host ::ng-deep .p-datatable-thead>tr>th:first-child{border-top-left-radius:.625rem}:host ::ng-deep .p-datatable-thead>tr>th:last-child{border-top-right-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:first-child{border-bottom-left-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:last-child{border-bottom-right-radius:.625rem}.mt-table-clickable-row>td{transition:background-color .16s ease,color .16s ease,border-color .16s ease}.mt-table-clickable-row:hover>td,.mt-table-clickable-row:focus-within>td{background:#fafafa}.mt-table-clickable-row:hover>td:first-child,.mt-table-clickable-row:focus-within>td:first-child{border-inline-start:none}.mt-table-status-entity-row>td{background:#fff}.mt-table-status-entity-row>td:first-child:before{display:none}\n"], dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$1.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.ReorderableColumn, selector: "[pReorderableColumn]", inputs: ["pReorderableColumnDisabled"] }, { kind: "directive", type: i1$1.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i1$1.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Paginator, selector: "mt-paginator", inputs: ["rows", "totalRecords", "first", "page", "rowsPerPageOptions", "showFirstLastIcon", "showCurrentPageReport", "fluid", "pageLinkSize", "alwaysShow"], outputs: ["rowsChange", "firstChange", "pageChange", "onPageChange"] }, { kind: "component", type: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "size", "fluid", "disabled"], outputs: ["activeChange", "onChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i3$1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i4.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: TableFilter, selector: "mt-table-filter", inputs: ["columns", "data"], outputs: ["filterApplied", "filterReset"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "pipe", type: i3.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: MTDateFormatPipe, name: "mtDateFormat" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2239
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: Table, isStandalone: true, selector: "mt-table", inputs: { filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: true, transformFunction: null }, rowActions: { classPropertyName: "rowActions", publicName: "rowActions", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, showGridlines: { classPropertyName: "showGridlines", publicName: "showGridlines", isSignal: true, isRequired: false, transformFunction: null }, stripedRows: { classPropertyName: "stripedRows", publicName: "stripedRows", isSignal: true, isRequired: false, transformFunction: null }, selectableRows: { classPropertyName: "selectableRows", publicName: "selectableRows", isSignal: true, isRequired: false, transformFunction: null }, clickableRows: { classPropertyName: "clickableRows", publicName: "clickableRows", isSignal: true, isRequired: false, transformFunction: null }, generalSearch: { classPropertyName: "generalSearch", publicName: "generalSearch", isSignal: true, isRequired: false, transformFunction: null }, lazyLocalSearch: { classPropertyName: "lazyLocalSearch", publicName: "lazyLocalSearch", isSignal: true, isRequired: false, transformFunction: null }, showFilters: { classPropertyName: "showFilters", publicName: "showFilters", isSignal: true, isRequired: false, transformFunction: null }, filterMode: { classPropertyName: "filterMode", publicName: "filterMode", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, updating: { classPropertyName: "updating", publicName: "updating", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, lazyLocalSort: { classPropertyName: "lazyLocalSort", publicName: "lazyLocalSort", isSignal: true, isRequired: false, transformFunction: null }, lazyTotalRecords: { classPropertyName: "lazyTotalRecords", publicName: "lazyTotalRecords", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableRows: { classPropertyName: "reorderableRows", publicName: "reorderableRows", isSignal: true, isRequired: false, transformFunction: null }, dataKey: { classPropertyName: "dataKey", publicName: "dataKey", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null }, storageMode: { classPropertyName: "storageMode", publicName: "storageMode", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, printable: { classPropertyName: "printable", publicName: "printable", isSignal: true, isRequired: false, transformFunction: null }, groupable: { classPropertyName: "groupable", publicName: "groupable", isSignal: true, isRequired: false, transformFunction: null }, cellClickFilter: { classPropertyName: "cellClickFilter", publicName: "cellClickFilter", isSignal: true, isRequired: false, transformFunction: null }, printTitle: { classPropertyName: "printTitle", publicName: "printTitle", isSignal: true, isRequired: false, transformFunction: null }, exportFilename: { classPropertyName: "exportFilename", publicName: "exportFilename", isSignal: true, isRequired: false, transformFunction: null }, actionShape: { classPropertyName: "actionShape", publicName: "actionShape", isSignal: true, isRequired: false, transformFunction: null }, tableLayout: { classPropertyName: "tableLayout", publicName: "tableLayout", isSignal: true, isRequired: false, transformFunction: null }, noCard: { classPropertyName: "noCard", publicName: "noCard", isSignal: true, isRequired: false, transformFunction: null }, tabs: { classPropertyName: "tabs", publicName: "tabs", isSignal: true, isRequired: false, transformFunction: null }, tabsOptionLabel: { classPropertyName: "tabsOptionLabel", publicName: "tabsOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, tabsOptionValue: { classPropertyName: "tabsOptionValue", publicName: "tabsOptionValue", isSignal: true, isRequired: false, transformFunction: null }, activeTab: { classPropertyName: "activeTab", publicName: "activeTab", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, paginatorPosition: { classPropertyName: "paginatorPosition", publicName: "paginatorPosition", isSignal: true, isRequired: false, transformFunction: null }, alwaysShowPaginator: { classPropertyName: "alwaysShowPaginator", publicName: "alwaysShowPaginator", isSignal: true, isRequired: false, transformFunction: null }, rowsPerPageOptions: { classPropertyName: "rowsPerPageOptions", publicName: "rowsPerPageOptions", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, currentPage: { classPropertyName: "currentPage", publicName: "currentPage", isSignal: true, isRequired: false, transformFunction: null }, first: { classPropertyName: "first", publicName: "first", isSignal: true, isRequired: false, transformFunction: null }, filterTerm: { classPropertyName: "filterTerm", publicName: "filterTerm", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", cellChange: "cellChange", lazyLoad: "lazyLoad", columnReorder: "columnReorder", rowReorder: "rowReorder", rowClick: "rowClick", filters: "filtersChange", activeTab: "activeTabChange", onTabChange: "onTabChange", pageSize: "pageSizeChange", currentPage: "currentPageChange", first: "firstChange", filterTerm: "filterTermChange", groupBy: "groupByChange" }, providers: [MTDateFormatPipe], queries: [{ propertyName: "captionStartContent", first: true, predicate: ["captionStart"], descendants: true, isSignal: true }, { propertyName: "captionEndContent", first: true, predicate: ["captionEnd"], descendants: true, isSignal: true }, { propertyName: "emptyContent", first: true, predicate: ["empty"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (!noCard()) {\r\n <mt-card>\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </mt-card>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"space-y-4 rounded-lg\">\r\n <div>\r\n <mt-table-caption\r\n [generalSearch]=\"generalSearch()\"\r\n [showFilters]=\"showFilters()\"\r\n [filterMode]=\"filterMode()\"\r\n [exportable]=\"exportable()\"\r\n [printable]=\"printable()\"\r\n [groupable]=\"groupable()\"\r\n [columns]=\"columns()\"\r\n [data]=\"data()\"\r\n [groupColumns]=\"grouping.groupableColumns()\"\r\n [tabs]=\"tabs()\"\r\n [tabsOptionLabel]=\"tabsOptionLabel()\"\r\n [tabsOptionValue]=\"tabsOptionValue()\"\r\n [actions]=\"actions()\"\r\n [captionStart]=\"captionStartContent() ?? null\"\r\n [captionEnd]=\"captionEndContent() ?? null\"\r\n [(activeTab)]=\"activeTab\"\r\n [(filters)]=\"filters\"\r\n [(filterTerm)]=\"filterTerm\"\r\n [(groupBy)]=\"groupBy\"\r\n (exportRequested)=\"exportExcel()\"\r\n (printRequested)=\"printPdf()\"\r\n (onTabChange)=\"tabChanged($event)\"\r\n (searchChange)=\"onSearchChange($event)\"\r\n (filterApplied)=\"onFilterApplied($event)\"\r\n (filterReset)=\"onFilterReset()\"\r\n />\r\n\r\n @if (!loading() && emptyContent() && data().length === 0) {\r\n <div\r\n class=\"p-4 bg-content rounded-md text-center text-gray-600 dark:text-gray-300\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"emptyContent()\"></ng-container>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"overflow-x-auto rounded-[10px] border border-surface-200 bg-white\"\r\n >\r\n <p-table\r\n [value]=\"displayData()\"\r\n [columns]=\"renderedColumns()\"\r\n [size]=\"size()\"\r\n [showGridlines]=\"showGridlines()\"\r\n [stripedRows]=\"stripedRows()\"\r\n [lazy]=\"lazy()\"\r\n [totalRecords]=\"totalRecords()\"\r\n [reorderableColumns]=\"reorderableColumns()\"\r\n [reorderableRows]=\"reorderableRows()\"\r\n [dataKey]=\"dataKey()\"\r\n [first]=\"first()\"\r\n [rows]=\"pageSize()\"\r\n [exportFilename]=\"exportFilename()\"\r\n [rowGroupMode]=\"grouping.groupingActive() ? 'subheader' : null\"\r\n [groupRowsBy]=\"grouping.activeGroupColumn()?.key ?? null\"\r\n [sortField]=\"sortField()\"\r\n [sortOrder]=\"sortDirection() === 'desc' ? -1 : 1\"\r\n (onPage)=\"onTablePage($event)\"\r\n (onLazyLoad)=\"handleLazyLoad($event)\"\r\n (onColReorder)=\"onColumnReorder($event)\"\r\n (onRowReorder)=\"onRowReorder($event)\"\r\n paginator\r\n paginatorStyleClass=\"hidden!\"\r\n class=\"mt-table min-w-full align-middle text-sm\"\r\n [class.table-auto]=\"tableLayout() === 'auto'\"\r\n [class.table-fixed]=\"tableLayout() === 'fixed'\"\r\n >\r\n <ng-template\r\n #header\r\n let-columns\r\n class=\"bg-surface-50 dark:bg-surface-950 border-b border-surface-300 dark:border-surface-500\"\r\n >\r\n <tr>\r\n @if (reorderableRows()) {\r\n <th class=\"w-10\"></th>\r\n }\r\n @if (selectableRows()) {\r\n <th class=\"w-12 text-start\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelectedOnPage()\"\r\n (ngModelChange)=\"toggleAllRowsOnPage()\"\r\n ></mt-checkbox-field>\r\n </th>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n @if (reorderableColumns()) {\r\n <th\r\n pReorderableColumn\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n {{ col.label }}\r\n @if (\r\n isColumnFilterMode() && getFilterableColumn(col.key);\r\n as filterableCol\r\n ) {\r\n <mt-table-column-filter\r\n [column]=\"filterableCol\"\r\n [value]=\"filters()[col.key]\"\r\n (filterChange)=\"\r\n onColumnFilterChange(col.key, $event)\r\n \"\r\n />\r\n }\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n </div>\r\n </th>\r\n } @else {\r\n <th\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n <div class=\"inline-flex items-center gap-1\">\r\n @if (isColumnSortable(col)) {\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex items-center gap-2 cursor-pointer\"\r\n (click)=\"toggleSort(col)\"\r\n >\r\n <span>{{ col.label }}</span>\r\n <mt-icon\r\n [icon]=\"getSortIcon(col)\"\r\n class=\"text-xs text-gray-400\"\r\n />\r\n </button>\r\n } @else {\r\n {{ col.label }}\r\n }\r\n @if (\r\n isColumnFilterMode() && getFilterableColumn(col.key);\r\n as filterableCol\r\n ) {\r\n <mt-table-column-filter\r\n [column]=\"filterableCol\"\r\n [value]=\"filters()[col.key]\"\r\n (filterChange)=\"\r\n onColumnFilterChange(col.key, $event)\r\n \"\r\n />\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <th class=\"text-end! text-sm font-normal text-[#323232]\">\r\n {{ \"components.table.actions\" | transloco }}\r\n </th>\r\n }\r\n </tr>\r\n @if (updating()) {\r\n <tr>\r\n <th [attr.colspan]=\"totalColumnSpan()\" class=\"!p-0\">\r\n <p-progressBar\r\n mode=\"indeterminate\"\r\n [style]=\"{ height: '4px' }\"\r\n />\r\n </th>\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template\r\n #body\r\n let-row\r\n let-columns=\"columns\"\r\n let-index=\"rowIndex\"\r\n class=\"divide-y divide-gray-200\"\r\n >\r\n @if (loading()) {\r\n <tr>\r\n @if (reorderableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (selectableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (rowActions().length > 0) {\r\n <td><p-skeleton /></td>\r\n }\r\n </tr>\r\n } @else {\r\n <tr\r\n class=\"border-surface-300 transition-colors duration-150 dark:border-surface-500\"\r\n [class.mt-table-clickable-row]=\"clickableRows()\"\r\n [class.mt-table-status-entity-row]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [style.--mt-table-status-accent]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [class.cursor-pointer]=\"clickableRows()\"\r\n [pReorderableRow]=\"index\"\r\n (click)=\"onRowClick($event, row)\"\r\n >\r\n @if (reorderableRows()) {\r\n <td class=\"w-10 text-center\">\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n pReorderableRowHandle\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n <!-- <mt-icon-->\r\n <!-- icon=\"general.menu-05\"-->\r\n <!-- class=\"cursor-move text-gray-500\"-->\r\n <!-- pReorderableRowHandle-->\r\n <!-- ></mt-icon>-->\r\n </td>\r\n }\r\n @if (selectableRows()) {\r\n <td class=\"w-12\">\r\n <mt-checkbox-field\r\n [ngModel]=\"isRowSelected(row)\"\r\n (ngModelChange)=\"toggleRow(row)\"\r\n ></mt-checkbox-field>\r\n </td>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td\r\n class=\"text-sm font-normal text-[#4b4b4b]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n @switch (col.type) {\r\n @case (\"boolean\") {\r\n @if (isCellClickFilterable(col, row)) {\r\n <span\r\n data-row-click-ignore=\"true\"\r\n class=\"inline-flex items-center cursor-pointer px-1.5 py-0.5 rounded transition-colors\"\r\n [class.ring-2]=\"isCellFilterActive(row, col)\"\r\n [class.ring-primary-400]=\"\r\n isCellFilterActive(row, col)\r\n \"\r\n [class.hover:underline]=\"\r\n !isCellFilterActive(row, col)\r\n \"\r\n (click)=\"onCellFilterClick($event, row, col)\"\r\n >\r\n {{\r\n getBooleanProperty(row, col.key) ? \"Yes\" : \"No\"\r\n }}\r\n </span>\r\n } @else {\r\n <mt-toggle-field\r\n [disabled]=\"col.readonly\"\r\n [ngModel]=\"getBooleanProperty(row, col.key)\"\r\n (ngModelChange)=\"\r\n onCellChange(row, col.key, $event, 'boolean')\r\n \"\r\n ></mt-toggle-field>\r\n }\r\n }\r\n @case (\"date\") {\r\n {{\r\n getDateProperty(row, col.key) | mtDateFormat: \"date\"\r\n }}\r\n }\r\n @case (\"dateTime\") {\r\n {{\r\n getDateProperty(row, col.key)\r\n | mtDateFormat: \"dateTime\"\r\n }}\r\n }\r\n @case (\"user\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n filterableCell;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n }\r\n @case (\"status\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n filterableCell;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n }\r\n @case (\"entity\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n filterableCell;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n }\r\n @case (\"custom\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n col.customCellTpl;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n }\r\n @default {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n </td>\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <td class=\"text-right\">\r\n @if (actionShape() === \"popover\") {\r\n <div class=\"flex items-center justify-end\">\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n size=\"large\"\r\n (click)=\"rowPopover.toggle($event)\"\r\n data-row-click-ignore=\"true\"\r\n ></mt-button>\r\n <p-popover #rowPopover appendTo=\"body\">\r\n <div class=\"flex flex-col min-w-40\">\r\n @for (\r\n action of getVisibleRowActions(row);\r\n track $index\r\n ) {\r\n <button\r\n class=\"flex items-center gap-2 px-2 cursor-pointer py-2 text-sm rounded transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n rowAction($event, action, row);\r\n rowPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon\r\n [icon]=\"action.icon\"\r\n class=\"text-base\"\r\n />\r\n }\r\n <span>{{\r\n action.label || action.tooltip\r\n }}</span>\r\n </button>\r\n }\r\n </div>\r\n </p-popover>\r\n </div>\r\n } @else {\r\n <div class=\"flex items-center justify-end space-x-2\">\r\n @for (action of rowActions(); track $index) {\r\n @let hidden = action.hidden?.(row);\r\n @if (!hidden) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"action.size || 'small'\"\r\n (click)=\"rowAction($event, action, row)\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, row)\"\r\n ></mt-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template #filterableCell let-row=\"row\" let-col=\"col\">\r\n @let filterable = isCellClickFilterable(col, row);\r\n @let active = isCellFilterActive(row, col);\r\n @if (filterable) {\r\n <span\r\n data-row-click-ignore=\"true\"\r\n class=\"flex w-full items-center rounded transition-colors cursor-pointer\"\r\n [class.ring-2]=\"active\"\r\n [class.ring-primary-400]=\"active\"\r\n (click)=\"onCellFilterClick($event, row, col)\"\r\n >\r\n @if (resolveCellEntityData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n </span>\r\n } @else {\r\n @if (resolveCellEntityData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n </ng-template>\r\n <ng-template #groupheader let-row>\r\n @if (grouping.groupingActive()) {\r\n <tr\r\n class=\"mt-group-header\"\r\n [style.--mt-group-accent]=\"\r\n grouping.getGroupAccentColor(row) ??\r\n 'var(--p-primary-color)'\r\n \"\r\n >\r\n <td [attr.colspan]=\"totalColumnSpan()\" class=\"!p-0\">\r\n <div\r\n class=\"flex items-center gap-3 px-4 py-2 bg-surface-50 dark:bg-surface-900 border-y border-surface-200 dark:border-surface-700\"\r\n >\r\n <span\r\n class=\"mt-group-header__accent inline-block w-1 h-5 rounded-full\"\r\n ></span>\r\n <span\r\n class=\"text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\"\r\n >\r\n {{ grouping.activeGroupColumn()?.label }}\r\n </span>\r\n <span\r\n class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\"\r\n >\r\n {{ grouping.getGroupLabel(row) }}\r\n </span>\r\n <span\r\n class=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300\"\r\n >\r\n {{ grouping.getGroupCount(row) }}\r\n </span>\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumnSpan()\" class=\"text-center\">\r\n <div\r\n class=\"flex min-h-44 flex-col items-center justify-center gap-3 py-8 text-center\"\r\n >\r\n <svg\r\n width=\"152\"\r\n height=\"120\"\r\n viewBox=\"0 0 152 120\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"76\" cy=\"52\" r=\"52\" fill=\"#E9EAEB\" />\r\n <g filter=\"url(#filter0_ddd_2474_28277)\">\r\n <path\r\n d=\"M77.6 16C66.8273 16 57.2978 21.3233 51.4987 29.4829C49.605 29.0363 47.6301 28.8 45.6 28.8C31.4615 28.8 20 40.2615 20 54.4C20 68.5385 31.4615 80 45.6 80L109.6 80C121.971 80 132 69.9712 132 57.6C132 45.2288 121.971 35.2 109.6 35.2C108.721 35.2 107.854 35.2506 107.002 35.349C102.098 23.9677 90.7797 16 77.6 16Z\"\r\n fill=\"#FAFAFA\"\r\n />\r\n <ellipse\r\n cx=\"45.6\"\r\n cy=\"54.3998\"\r\n rx=\"25.6\"\r\n ry=\"25.6\"\r\n fill=\"url(#paint0_linear_2474_28277)\"\r\n />\r\n <circle\r\n cx=\"77.6016\"\r\n cy=\"48\"\r\n r=\"32\"\r\n fill=\"url(#paint1_linear_2474_28277)\"\r\n />\r\n <ellipse\r\n cx=\"109.599\"\r\n cy=\"57.6002\"\r\n rx=\"22.4\"\r\n ry=\"22.4\"\r\n fill=\"url(#paint2_linear_2474_28277)\"\r\n />\r\n </g>\r\n <circle cx=\"21\" cy=\"19\" r=\"5\" fill=\"#F5F5F5\" />\r\n <circle cx=\"18\" cy=\"109\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"145\" cy=\"35\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"134\" cy=\"8\" r=\"4\" fill=\"#F5F5F5\" />\r\n <foreignObject x=\"44\" y=\"54\" width=\"64\" height=\"64\">\r\n <div\r\n xmlns=\"http://www.w3.org/1999/xhtml\"\r\n style=\"\r\n backdrop-filter: blur(4px);\r\n clip-path: url(#bgblur_0_2474_28277_clip_path);\r\n height: 100%;\r\n width: 100%;\r\n \"\r\n ></div>\r\n </foreignObject>\r\n <g data-figma-bg-blur-radius=\"8\">\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n fill=\"#344054\"\r\n fill-opacity=\"0.4\"\r\n />\r\n <path\r\n d=\"M85 95L81.5001 91.5M84 85.5C84 90.1944 80.1944 94 75.5 94C70.8056 94 67 90.1944 67 85.5C67 80.8056 70.8056 77 75.5 77C80.1944 77 84 80.8056 84 85.5Z\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_ddd_2474_28277\"\r\n x=\"0\"\r\n y=\"16\"\r\n width=\"152\"\r\n height=\"104\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood\r\n flood-opacity=\"0\"\r\n result=\"BackgroundImageFix\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"1.5\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"3\" />\r\n <feGaussianBlur stdDeviation=\"1.5\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"8\" />\r\n <feGaussianBlur stdDeviation=\"4\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect1_dropShadow_2474_28277\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"20\" />\r\n <feGaussianBlur stdDeviation=\"12\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect2_dropShadow_2474_28277\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect3_dropShadow_2474_28277\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath\r\n id=\"bgblur_0_2474_28277_clip_path\"\r\n transform=\"translate(-44 -54)\"\r\n >\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n />\r\n </clipPath>\r\n <linearGradient\r\n id=\"paint0_linear_2474_28277\"\r\n x1=\"25.9429\"\r\n y1=\"37.4855\"\r\n x2=\"71.2\"\r\n y2=\"79.9998\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint1_linear_2474_28277\"\r\n x1=\"53.0301\"\r\n y1=\"26.8571\"\r\n x2=\"109.602\"\r\n y2=\"80\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint2_linear_2474_28277\"\r\n x1=\"92.3992\"\r\n y1=\"42.8002\"\r\n x2=\"131.999\"\r\n y2=\"80.0002\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n <p class=\"m-0 text-base font-medium text-surface-500\">\r\n {{ \"components.table.no-data-found\" | transloco }}\r\n </p>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"flex flex-col gap-3 pb-3 px-4\"\r\n [class]=\"'items-' + paginatorPosition()\"\r\n >\r\n <mt-paginator\r\n [(rows)]=\"pageSize\"\r\n [(first)]=\"first\"\r\n [(page)]=\"currentPage\"\r\n [totalRecords]=\"totalRecords()\"\r\n [alwaysShow]=\"alwaysShowPaginator()\"\r\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\r\n (onPageChange)=\"onPaginatorPage($event)\"\r\n ></mt-paginator>\r\n </div>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .p-datatable-header{padding:0 0 1.5rem;background:transparent;border:0}:host ::ng-deep .p-datatable-table{border-collapse:separate;border-spacing:0}:host ::ng-deep .p-datatable-thead>tr>th{padding:.9rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#323232;font-size:14px;font-weight:400;line-height:20px;white-space:nowrap}:host ::ng-deep .p-datatable-tbody>tr>td{padding:.72rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#4b4b4b;font-size:14px;font-weight:400;line-height:20px;vertical-align:middle}:host ::ng-deep .p-datatable-tbody>tr:last-child>td{border-bottom:0}:host ::ng-deep .p-datatable-thead>tr>th:first-child{border-top-left-radius:.625rem}:host ::ng-deep .p-datatable-thead>tr>th:last-child{border-top-right-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:first-child{border-bottom-left-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:last-child{border-bottom-right-radius:.625rem}.mt-table-clickable-row>td{transition:background-color .16s ease,color .16s ease,border-color .16s ease}.mt-table-clickable-row:hover>td,.mt-table-clickable-row:focus-within>td{background:#fafafa}.mt-table-clickable-row:hover>td:first-child,.mt-table-clickable-row:focus-within>td:first-child{border-inline-start:none}.mt-table-status-entity-row>td{background:#fff}.mt-table-status-entity-row>td:first-child:before{display:none}:host ::ng-deep tr.mt-group-header>td{padding:0!important;background:transparent}tr.mt-group-header .mt-group-header__accent{background:var(--mt-group-accent, var(--p-primary-color))}\n"], dependencies: [{ kind: "ngmodule", type: TableModule }, { kind: "component", type: i1$3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$3.ReorderableColumn, selector: "[pReorderableColumn]", inputs: ["pReorderableColumnDisabled"] }, { kind: "directive", type: i1$3.ReorderableRowHandle, selector: "[pReorderableRowHandle]" }, { kind: "directive", type: i1$3.ReorderableRow, selector: "[pReorderableRow]", inputs: ["pReorderableRow", "pReorderableRowDisabled"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Paginator, selector: "mt-paginator", inputs: ["rows", "totalRecords", "first", "page", "rowsPerPageOptions", "showFirstLastIcon", "showCurrentPageReport", "fluid", "pageLinkSize", "alwaysShow"], outputs: ["rowsChange", "firstChange", "pageChange", "onPageChange"] }, { kind: "component", type: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i3.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "ngmodule", type: ProgressBarModule }, { kind: "component", type: i4.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "component", type: TableCaption, selector: "mt-table-caption", inputs: ["generalSearch", "showFilters", "filterMode", "exportable", "printable", "groupable", "columns", "data", "groupColumns", "tabs", "tabsOptionLabel", "tabsOptionValue", "actions", "captionStart", "captionEnd", "activeTab", "filters", "filterTerm", "groupBy"], outputs: ["activeTabChange", "filtersChange", "filterTermChange", "groupByChange", "exportRequested", "printRequested", "onTabChange", "searchChange", "filterApplied", "filterReset"] }, { kind: "component", type: TableColumnFilter, selector: "mt-table-column-filter", inputs: ["column", "value"], outputs: ["filterChange"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i1$2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: MTDateFormatPipe, name: "mtDateFormat" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1420
2240
|
}
|
|
1421
2241
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: Table, decorators: [{
|
|
1422
2242
|
type: Component,
|
|
1423
|
-
args: [{ selector: 'mt-table', standalone: true, imports: [
|
|
2243
|
+
args: [{ selector: 'mt-table', standalone: true, providers: [MTDateFormatPipe], imports: [
|
|
1424
2244
|
TableModule,
|
|
1425
2245
|
NgTemplateOutlet,
|
|
1426
2246
|
ToggleField,
|
|
1427
2247
|
FormsModule,
|
|
1428
2248
|
Button,
|
|
1429
|
-
TextField,
|
|
1430
2249
|
Paginator,
|
|
1431
2250
|
CheckboxField,
|
|
1432
|
-
Tabs,
|
|
1433
2251
|
SkeletonModule,
|
|
1434
2252
|
ProgressBarModule,
|
|
1435
2253
|
TranslocoModule,
|
|
1436
|
-
|
|
2254
|
+
TableCaption,
|
|
2255
|
+
TableColumnFilter,
|
|
1437
2256
|
EntityPreview,
|
|
1438
2257
|
PopoverModule,
|
|
1439
2258
|
Icon,
|
|
1440
2259
|
Card,
|
|
1441
2260
|
MTDateFormatPipe,
|
|
1442
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!noCard()) {\r\n <mt-card>\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </mt-card>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"space-y-4 rounded-lg\">\r\n <div>\r\n @if (\r\n captionStartContent() ||\r\n captionEndContent() ||\r\n generalSearch() ||\r\n showFilters() ||\r\n tabs()?.length > 0 ||\r\n actions()?.length > 0\r\n ) {\r\n <div class=\"p-datatable-header rounded-t-2xl\">\r\n <div\r\n class=\"flex relative\"\r\n [class]=\"!generalSearch() ? 'justify-end' : 'justify-between'\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"captionStartContent()\"\r\n ></ng-container>\r\n @if (tabs()) {\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabs()\"\r\n [optionLabel]=\"tabsOptionLabel()\"\r\n [optionValue]=\"tabsOptionValue()\"\r\n (onChange)=\"tabChanged($event)\"\r\n size=\"large\"\r\n ></mt-tabs>\r\n }\r\n @if (generalSearch()) {\r\n <mt-text-field\r\n [(ngModel)]=\"filterTerm\"\r\n (ngModelChange)=\"onSearchChange($event)\"\r\n icon=\"general.search-lg\"\r\n [placeholder]=\"'components.table.search' | transloco\"\r\n ></mt-text-field>\r\n }\r\n </div>\r\n <div class=\"flex items-center gap-2\">\r\n @if (showFilters()) {\r\n <mt-table-filter\r\n [columns]=\"columns()\"\r\n [data]=\"data()\"\r\n [ngModel]=\"filters()\"\r\n (filterApplied)=\"onFilterApplied($event)\"\r\n (filterReset)=\"onFilterReset()\"\r\n />\r\n }\r\n @if (exportable()) {\r\n <mt-button\r\n icon=\"file.file-x-03\"\r\n styleClass=\"text-xl! py-1.5!\"\r\n severity=\"success\"\r\n variant=\"outlined\"\r\n [tooltip]=\"'components.table.export' | transloco\"\r\n (click)=\"exportExcel()\"\r\n />\r\n }\r\n @if (actions()?.length > 0) {\r\n <div class=\"flex items-center space-x-2\">\r\n @for (action of actions(); track action.label) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"action.size\"\r\n (click)=\"action.action(row)\"\r\n [label]=\"action.label\"\r\n [tooltip]=\"action.tooltip\"\r\n ></mt-button>\r\n }\r\n </div>\r\n }\r\n <ng-container\r\n *ngTemplateOutlet=\"captionEndContent()\"\r\n ></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n @if (!loading() && emptyContent() && data().length === 0) {\r\n <div\r\n class=\"p-4 bg-content rounded-md text-center text-gray-600 dark:text-gray-300\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"emptyContent()\"></ng-container>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"overflow-x-auto rounded-[10px] border border-surface-200 bg-white\"\r\n >\r\n <p-table\r\n [value]=\"displayData()\"\r\n [columns]=\"renderedColumns()\"\r\n [size]=\"size()\"\r\n [showGridlines]=\"showGridlines()\"\r\n [stripedRows]=\"stripedRows()\"\r\n [lazy]=\"lazy()\"\r\n [totalRecords]=\"totalRecords()\"\r\n [reorderableColumns]=\"reorderableColumns()\"\r\n [reorderableRows]=\"reorderableRows()\"\r\n [dataKey]=\"dataKey()\"\r\n [first]=\"first()\"\r\n [rows]=\"pageSize()\"\r\n [exportFilename]=\"exportFilename()\"\r\n (onPage)=\"onTablePage($event)\"\r\n (onLazyLoad)=\"handleLazyLoad($event)\"\r\n (onColReorder)=\"onColumnReorder($event)\"\r\n (onRowReorder)=\"onRowReorder($event)\"\r\n paginator\r\n paginatorStyleClass=\"hidden!\"\r\n class=\"mt-table min-w-full align-middle text-sm\"\r\n [class.table-auto]=\"tableLayout() === 'auto'\"\r\n [class.table-fixed]=\"tableLayout() === 'fixed'\"\r\n >\r\n <ng-template\r\n #header\r\n let-columns\r\n class=\"bg-surface-50 dark:bg-surface-950 border-b border-surface-300 dark:border-surface-500\"\r\n >\r\n <tr>\r\n @if (reorderableRows()) {\r\n <th class=\"w-10\"></th>\r\n }\r\n @if (selectableRows()) {\r\n <th class=\"w-12 text-start\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelectedOnPage()\"\r\n (ngModelChange)=\"toggleAllRowsOnPage()\"\r\n ></mt-checkbox-field>\r\n </th>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n @if (reorderableColumns()) {\r\n <th\r\n pReorderableColumn\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n {{ col.label }}\r\n <!-- <mt-icon-->\r\n <!-- icon=\"general.menu-05\"-->\r\n <!-- class=\"text-xs text-gray-400\"-->\r\n <!-- ></mt-icon>-->\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n </div>\r\n </th>\r\n } @else {\r\n <th\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n @if (isColumnSortable(col)) {\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex items-center gap-2 cursor-pointer\"\r\n (click)=\"toggleSort(col)\"\r\n >\r\n <span>{{ col.label }}</span>\r\n <mt-icon\r\n [icon]=\"getSortIcon(col)\"\r\n class=\"text-xs text-gray-400\"\r\n />\r\n </button>\r\n } @else {\r\n {{ col.label }}\r\n }\r\n </th>\r\n }\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <th class=\"text-end! text-sm font-normal text-[#323232]\">\r\n {{ \"components.table.actions\" | transloco }}\r\n </th>\r\n }\r\n </tr>\r\n @if (updating()) {\r\n <tr>\r\n <th\r\n [attr.colspan]=\"\r\n columns.length +\r\n (reorderableRows() ? 1 : 0) +\r\n (selectableRows() ? 1 : 0) +\r\n (rowActions().length > 0 ? 1 : 0)\r\n \"\r\n class=\"!p-0\"\r\n >\r\n <p-progressBar\r\n mode=\"indeterminate\"\r\n [style]=\"{ height: '4px' }\"\r\n />\r\n </th>\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template\r\n #body\r\n let-row\r\n let-columns=\"columns\"\r\n let-index=\"rowIndex\"\r\n class=\"divide-y divide-gray-200\"\r\n >\r\n @if (loading()) {\r\n <tr>\r\n @if (reorderableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (selectableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (rowActions().length > 0) {\r\n <td><p-skeleton /></td>\r\n }\r\n </tr>\r\n } @else {\r\n <tr\r\n class=\"border-surface-300 transition-colors duration-150 dark:border-surface-500\"\r\n [class.mt-table-clickable-row]=\"clickableRows()\"\r\n [class.mt-table-status-entity-row]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [style.--mt-table-status-accent]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [class.cursor-pointer]=\"clickableRows()\"\r\n [pReorderableRow]=\"index\"\r\n (click)=\"onRowClick($event, row)\"\r\n >\r\n @if (reorderableRows()) {\r\n <td class=\"w-10 text-center\">\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n pReorderableRowHandle\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n <!-- <mt-icon-->\r\n <!-- icon=\"general.menu-05\"-->\r\n <!-- class=\"cursor-move text-gray-500\"-->\r\n <!-- pReorderableRowHandle-->\r\n <!-- ></mt-icon>-->\r\n </td>\r\n }\r\n @if (selectableRows()) {\r\n <td class=\"w-12\">\r\n <mt-checkbox-field\r\n [ngModel]=\"isRowSelected(row)\"\r\n (ngModelChange)=\"toggleRow(row)\"\r\n ></mt-checkbox-field>\r\n </td>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td\r\n class=\"text-sm font-normal text-[#4b4b4b]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n @switch (col.type) {\r\n @case (\"boolean\") {\r\n <mt-toggle-field\r\n disabled=\"col.readonly\"\r\n [ngModel]=\"getBooleanProperty(row, col.key)\"\r\n (ngModelChange)=\"\r\n onCellChange(row, col.key, $event, 'boolean')\r\n \"\r\n ></mt-toggle-field>\r\n }\r\n @case (\"date\") {\r\n {{\r\n getDateProperty(row, col.key) | mtDateFormat: \"date\"\r\n }}\r\n }\r\n @case (\"dateTime\") {\r\n {{\r\n getDateProperty(row, col.key)\r\n | mtDateFormat: \"dateTime\"\r\n }}\r\n }\r\n @case (\"user\") {\r\n @if (getEntityPreviewData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n @case (\"status\") {\r\n @if (getEntityPreviewData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n @case (\"entity\") {\r\n @if (getEntityColumnData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n @case (\"custom\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n col.customCellTpl;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n }\r\n @default {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n </td>\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <td class=\"text-right\">\r\n @if (actionShape() === \"popover\") {\r\n <div class=\"flex items-center justify-end\">\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n size=\"large\"\r\n (click)=\"rowPopover.toggle($event)\"\r\n data-row-click-ignore=\"true\"\r\n ></mt-button>\r\n <p-popover #rowPopover appendTo=\"body\">\r\n <div class=\"flex flex-col min-w-40\">\r\n @for (\r\n action of getVisibleRowActions(row);\r\n track $index\r\n ) {\r\n <button\r\n class=\"flex items-center gap-2 px-2 cursor-pointer py-2 text-sm rounded transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n rowAction($event, action, row);\r\n rowPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon\r\n [icon]=\"action.icon\"\r\n class=\"text-base\"\r\n />\r\n }\r\n <span>{{\r\n action.label || action.tooltip\r\n }}</span>\r\n </button>\r\n }\r\n </div>\r\n </p-popover>\r\n </div>\r\n } @else {\r\n <div class=\"flex items-center justify-end space-x-2\">\r\n @for (action of rowActions(); track $index) {\r\n @let hidden = action.hidden?.(row);\r\n @if (!hidden) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"action.size || 'small'\"\r\n (click)=\"rowAction($event, action, row)\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, row)\"\r\n ></mt-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td\r\n [attr.colspan]=\"\r\n renderedColumns().length +\r\n (reorderableRows() ? 1 : 0) +\r\n (selectableRows() ? 1 : 0) +\r\n (rowActions().length > 0 ? 1 : 0)\r\n \"\r\n class=\"text-center\"\r\n >\r\n <div\r\n class=\"flex min-h-44 flex-col items-center justify-center gap-3 py-8 text-center\"\r\n >\r\n <svg\r\n width=\"152\"\r\n height=\"120\"\r\n viewBox=\"0 0 152 120\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"76\" cy=\"52\" r=\"52\" fill=\"#E9EAEB\" />\r\n <g filter=\"url(#filter0_ddd_2474_28277)\">\r\n <path\r\n d=\"M77.6 16C66.8273 16 57.2978 21.3233 51.4987 29.4829C49.605 29.0363 47.6301 28.8 45.6 28.8C31.4615 28.8 20 40.2615 20 54.4C20 68.5385 31.4615 80 45.6 80L109.6 80C121.971 80 132 69.9712 132 57.6C132 45.2288 121.971 35.2 109.6 35.2C108.721 35.2 107.854 35.2506 107.002 35.349C102.098 23.9677 90.7797 16 77.6 16Z\"\r\n fill=\"#FAFAFA\"\r\n />\r\n <ellipse\r\n cx=\"45.6\"\r\n cy=\"54.3998\"\r\n rx=\"25.6\"\r\n ry=\"25.6\"\r\n fill=\"url(#paint0_linear_2474_28277)\"\r\n />\r\n <circle\r\n cx=\"77.6016\"\r\n cy=\"48\"\r\n r=\"32\"\r\n fill=\"url(#paint1_linear_2474_28277)\"\r\n />\r\n <ellipse\r\n cx=\"109.599\"\r\n cy=\"57.6002\"\r\n rx=\"22.4\"\r\n ry=\"22.4\"\r\n fill=\"url(#paint2_linear_2474_28277)\"\r\n />\r\n </g>\r\n <circle cx=\"21\" cy=\"19\" r=\"5\" fill=\"#F5F5F5\" />\r\n <circle cx=\"18\" cy=\"109\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"145\" cy=\"35\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"134\" cy=\"8\" r=\"4\" fill=\"#F5F5F5\" />\r\n <foreignObject x=\"44\" y=\"54\" width=\"64\" height=\"64\">\r\n <div\r\n xmlns=\"http://www.w3.org/1999/xhtml\"\r\n style=\"\r\n backdrop-filter: blur(4px);\r\n clip-path: url(#bgblur_0_2474_28277_clip_path);\r\n height: 100%;\r\n width: 100%;\r\n \"\r\n ></div>\r\n </foreignObject>\r\n <g data-figma-bg-blur-radius=\"8\">\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n fill=\"#344054\"\r\n fill-opacity=\"0.4\"\r\n />\r\n <path\r\n d=\"M85 95L81.5001 91.5M84 85.5C84 90.1944 80.1944 94 75.5 94C70.8056 94 67 90.1944 67 85.5C67 80.8056 70.8056 77 75.5 77C80.1944 77 84 80.8056 84 85.5Z\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_ddd_2474_28277\"\r\n x=\"0\"\r\n y=\"16\"\r\n width=\"152\"\r\n height=\"104\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood\r\n flood-opacity=\"0\"\r\n result=\"BackgroundImageFix\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"1.5\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"3\" />\r\n <feGaussianBlur stdDeviation=\"1.5\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"8\" />\r\n <feGaussianBlur stdDeviation=\"4\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect1_dropShadow_2474_28277\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"20\" />\r\n <feGaussianBlur stdDeviation=\"12\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect2_dropShadow_2474_28277\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect3_dropShadow_2474_28277\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath\r\n id=\"bgblur_0_2474_28277_clip_path\"\r\n transform=\"translate(-44 -54)\"\r\n >\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n />\r\n </clipPath>\r\n <linearGradient\r\n id=\"paint0_linear_2474_28277\"\r\n x1=\"25.9429\"\r\n y1=\"37.4855\"\r\n x2=\"71.2\"\r\n y2=\"79.9998\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint1_linear_2474_28277\"\r\n x1=\"53.0301\"\r\n y1=\"26.8571\"\r\n x2=\"109.602\"\r\n y2=\"80\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint2_linear_2474_28277\"\r\n x1=\"92.3992\"\r\n y1=\"42.8002\"\r\n x2=\"131.999\"\r\n y2=\"80.0002\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n <p class=\"m-0 text-base font-medium text-surface-500\">\r\n {{ \"components.table.no-data-found\" | transloco }}\r\n </p>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"flex flex-col gap-3 pb-3 px-4\"\r\n [class]=\"'items-' + paginatorPosition()\"\r\n >\r\n <mt-paginator\r\n [(rows)]=\"pageSize\"\r\n [(first)]=\"first\"\r\n [(page)]=\"currentPage\"\r\n [totalRecords]=\"totalRecords()\"\r\n [alwaysShow]=\"alwaysShowPaginator()\"\r\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\r\n (onPageChange)=\"onPaginatorPage($event)\"\r\n ></mt-paginator>\r\n </div>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .p-datatable-header{padding:0 0 1.5rem;background:transparent;border:0}:host ::ng-deep .p-datatable-table{border-collapse:separate;border-spacing:0}:host ::ng-deep .p-datatable-thead>tr>th{padding:.9rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#323232;font-size:14px;font-weight:400;line-height:20px;white-space:nowrap}:host ::ng-deep .p-datatable-tbody>tr>td{padding:.72rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#4b4b4b;font-size:14px;font-weight:400;line-height:20px;vertical-align:middle}:host ::ng-deep .p-datatable-tbody>tr:last-child>td{border-bottom:0}:host ::ng-deep .p-datatable-thead>tr>th:first-child{border-top-left-radius:.625rem}:host ::ng-deep .p-datatable-thead>tr>th:last-child{border-top-right-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:first-child{border-bottom-left-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:last-child{border-bottom-right-radius:.625rem}.mt-table-clickable-row>td{transition:background-color .16s ease,color .16s ease,border-color .16s ease}.mt-table-clickable-row:hover>td,.mt-table-clickable-row:focus-within>td{background:#fafafa}.mt-table-clickable-row:hover>td:first-child,.mt-table-clickable-row:focus-within>td:first-child{border-inline-start:none}.mt-table-status-entity-row>td{background:#fff}.mt-table-status-entity-row>td:first-child:before{display:none}\n"] }]
|
|
1443
|
-
}], ctorParameters: () => [], propDecorators: { selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], columnReorder: [{ type: i0.Output, args: ["columnReorder"] }], rowReorder: [{ type: i0.Output, args: ["rowReorder"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showGridlines: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGridlines", required: false }] }], stripedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "stripedRows", required: false }] }], selectableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectableRows", required: false }] }], clickableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickableRows", required: false }] }], generalSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalSearch", required: false }] }], lazyLocalSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyLocalSearch", required: false }] }], showFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilters", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], updating: [{ type: i0.Input, args: [{ isSignal: true, alias: "updating", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], lazyLocalSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyLocalSort", required: false }] }], lazyTotalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyTotalRecords", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], reorderableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableRows", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], storageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageKey", required: false }] }], storageMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageMode", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], exportFilename: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFilename", required: false }] }], actionShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionShape", required: false }] }], tableLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableLayout", required: false }] }], noCard: [{ type: i0.Input, args: [{ isSignal: true, alias: "noCard", required: false }] }], tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], tabsOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabsOptionLabel", required: false }] }], tabsOptionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabsOptionValue", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], captionStartContent: [{ type: i0.ContentChild, args: ['captionStart', { isSignal: true }] }], captionEndContent: [{ type: i0.ContentChild, args: ['captionEnd', { isSignal: true }] }], emptyContent: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], paginatorPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginatorPosition", required: false }] }], alwaysShowPaginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "alwaysShowPaginator", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], first: [{ type: i0.Input, args: [{ isSignal: true, alias: "first", required: false }] }, { type: i0.Output, args: ["firstChange"] }], filterTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTerm", required: false }] }, { type: i0.Output, args: ["filterTermChange"] }] } });
|
|
2261
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!noCard()) {\r\n <mt-card>\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n </mt-card>\r\n} @else {\r\n <ng-container *ngTemplateOutlet=\"tableContent\" />\r\n}\r\n\r\n<ng-template #tableContent>\r\n <div class=\"space-y-4 rounded-lg\">\r\n <div>\r\n <mt-table-caption\r\n [generalSearch]=\"generalSearch()\"\r\n [showFilters]=\"showFilters()\"\r\n [filterMode]=\"filterMode()\"\r\n [exportable]=\"exportable()\"\r\n [printable]=\"printable()\"\r\n [groupable]=\"groupable()\"\r\n [columns]=\"columns()\"\r\n [data]=\"data()\"\r\n [groupColumns]=\"grouping.groupableColumns()\"\r\n [tabs]=\"tabs()\"\r\n [tabsOptionLabel]=\"tabsOptionLabel()\"\r\n [tabsOptionValue]=\"tabsOptionValue()\"\r\n [actions]=\"actions()\"\r\n [captionStart]=\"captionStartContent() ?? null\"\r\n [captionEnd]=\"captionEndContent() ?? null\"\r\n [(activeTab)]=\"activeTab\"\r\n [(filters)]=\"filters\"\r\n [(filterTerm)]=\"filterTerm\"\r\n [(groupBy)]=\"groupBy\"\r\n (exportRequested)=\"exportExcel()\"\r\n (printRequested)=\"printPdf()\"\r\n (onTabChange)=\"tabChanged($event)\"\r\n (searchChange)=\"onSearchChange($event)\"\r\n (filterApplied)=\"onFilterApplied($event)\"\r\n (filterReset)=\"onFilterReset()\"\r\n />\r\n\r\n @if (!loading() && emptyContent() && data().length === 0) {\r\n <div\r\n class=\"p-4 bg-content rounded-md text-center text-gray-600 dark:text-gray-300\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"emptyContent()\"></ng-container>\r\n </div>\r\n } @else {\r\n <div\r\n class=\"overflow-x-auto rounded-[10px] border border-surface-200 bg-white\"\r\n >\r\n <p-table\r\n [value]=\"displayData()\"\r\n [columns]=\"renderedColumns()\"\r\n [size]=\"size()\"\r\n [showGridlines]=\"showGridlines()\"\r\n [stripedRows]=\"stripedRows()\"\r\n [lazy]=\"lazy()\"\r\n [totalRecords]=\"totalRecords()\"\r\n [reorderableColumns]=\"reorderableColumns()\"\r\n [reorderableRows]=\"reorderableRows()\"\r\n [dataKey]=\"dataKey()\"\r\n [first]=\"first()\"\r\n [rows]=\"pageSize()\"\r\n [exportFilename]=\"exportFilename()\"\r\n [rowGroupMode]=\"grouping.groupingActive() ? 'subheader' : null\"\r\n [groupRowsBy]=\"grouping.activeGroupColumn()?.key ?? null\"\r\n [sortField]=\"sortField()\"\r\n [sortOrder]=\"sortDirection() === 'desc' ? -1 : 1\"\r\n (onPage)=\"onTablePage($event)\"\r\n (onLazyLoad)=\"handleLazyLoad($event)\"\r\n (onColReorder)=\"onColumnReorder($event)\"\r\n (onRowReorder)=\"onRowReorder($event)\"\r\n paginator\r\n paginatorStyleClass=\"hidden!\"\r\n class=\"mt-table min-w-full align-middle text-sm\"\r\n [class.table-auto]=\"tableLayout() === 'auto'\"\r\n [class.table-fixed]=\"tableLayout() === 'fixed'\"\r\n >\r\n <ng-template\r\n #header\r\n let-columns\r\n class=\"bg-surface-50 dark:bg-surface-950 border-b border-surface-300 dark:border-surface-500\"\r\n >\r\n <tr>\r\n @if (reorderableRows()) {\r\n <th class=\"w-10\"></th>\r\n }\r\n @if (selectableRows()) {\r\n <th class=\"w-12 text-start\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelectedOnPage()\"\r\n (ngModelChange)=\"toggleAllRowsOnPage()\"\r\n ></mt-checkbox-field>\r\n </th>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n @if (reorderableColumns()) {\r\n <th\r\n pReorderableColumn\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n {{ col.label }}\r\n @if (\r\n isColumnFilterMode() && getFilterableColumn(col.key);\r\n as filterableCol\r\n ) {\r\n <mt-table-column-filter\r\n [column]=\"filterableCol\"\r\n [value]=\"filters()[col.key]\"\r\n (filterChange)=\"\r\n onColumnFilterChange(col.key, $event)\r\n \"\r\n />\r\n }\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n </div>\r\n </th>\r\n } @else {\r\n <th\r\n class=\"text-start text-sm font-normal text-[#323232]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n <div class=\"inline-flex items-center gap-1\">\r\n @if (isColumnSortable(col)) {\r\n <button\r\n type=\"button\"\r\n class=\"inline-flex items-center gap-2 cursor-pointer\"\r\n (click)=\"toggleSort(col)\"\r\n >\r\n <span>{{ col.label }}</span>\r\n <mt-icon\r\n [icon]=\"getSortIcon(col)\"\r\n class=\"text-xs text-gray-400\"\r\n />\r\n </button>\r\n } @else {\r\n {{ col.label }}\r\n }\r\n @if (\r\n isColumnFilterMode() && getFilterableColumn(col.key);\r\n as filterableCol\r\n ) {\r\n <mt-table-column-filter\r\n [column]=\"filterableCol\"\r\n [value]=\"filters()[col.key]\"\r\n (filterChange)=\"\r\n onColumnFilterChange(col.key, $event)\r\n \"\r\n />\r\n }\r\n </div>\r\n </th>\r\n }\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <th class=\"text-end! text-sm font-normal text-[#323232]\">\r\n {{ \"components.table.actions\" | transloco }}\r\n </th>\r\n }\r\n </tr>\r\n @if (updating()) {\r\n <tr>\r\n <th [attr.colspan]=\"totalColumnSpan()\" class=\"!p-0\">\r\n <p-progressBar\r\n mode=\"indeterminate\"\r\n [style]=\"{ height: '4px' }\"\r\n />\r\n </th>\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template\r\n #body\r\n let-row\r\n let-columns=\"columns\"\r\n let-index=\"rowIndex\"\r\n class=\"divide-y divide-gray-200\"\r\n >\r\n @if (loading()) {\r\n <tr>\r\n @if (reorderableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (selectableRows()) {\r\n <td><p-skeleton /></td>\r\n }\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td><p-skeleton /></td>\r\n }\r\n @if (rowActions().length > 0) {\r\n <td><p-skeleton /></td>\r\n }\r\n </tr>\r\n } @else {\r\n <tr\r\n class=\"border-surface-300 transition-colors duration-150 dark:border-surface-500\"\r\n [class.mt-table-clickable-row]=\"clickableRows()\"\r\n [class.mt-table-status-entity-row]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [style.--mt-table-status-accent]=\"\r\n getStatusEntityAccentColor(row)\r\n \"\r\n [class.cursor-pointer]=\"clickableRows()\"\r\n [pReorderableRow]=\"index\"\r\n (click)=\"onRowClick($event, row)\"\r\n >\r\n @if (reorderableRows()) {\r\n <td class=\"w-10 text-center\">\r\n <mt-button\r\n styleClass=\"cursor-move!\"\r\n pReorderableRowHandle\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n size=\"small\"\r\n icon=\"general.menu-05\"\r\n ></mt-button>\r\n <!-- <mt-icon-->\r\n <!-- icon=\"general.menu-05\"-->\r\n <!-- class=\"cursor-move text-gray-500\"-->\r\n <!-- pReorderableRowHandle-->\r\n <!-- ></mt-icon>-->\r\n </td>\r\n }\r\n @if (selectableRows()) {\r\n <td class=\"w-12\">\r\n <mt-checkbox-field\r\n [ngModel]=\"isRowSelected(row)\"\r\n (ngModelChange)=\"toggleRow(row)\"\r\n ></mt-checkbox-field>\r\n </td>\r\n }\r\n\r\n @for (col of columns; track col.key || col.label || $index) {\r\n <td\r\n class=\"text-sm font-normal text-[#4b4b4b]\"\r\n [style.width]=\"col.width ?? null\"\r\n [style.minWidth]=\"getColumnMinWidth(col)\"\r\n >\r\n @switch (col.type) {\r\n @case (\"boolean\") {\r\n @if (isCellClickFilterable(col, row)) {\r\n <span\r\n data-row-click-ignore=\"true\"\r\n class=\"inline-flex items-center cursor-pointer px-1.5 py-0.5 rounded transition-colors\"\r\n [class.ring-2]=\"isCellFilterActive(row, col)\"\r\n [class.ring-primary-400]=\"\r\n isCellFilterActive(row, col)\r\n \"\r\n [class.hover:underline]=\"\r\n !isCellFilterActive(row, col)\r\n \"\r\n (click)=\"onCellFilterClick($event, row, col)\"\r\n >\r\n {{\r\n getBooleanProperty(row, col.key) ? \"Yes\" : \"No\"\r\n }}\r\n </span>\r\n } @else {\r\n <mt-toggle-field\r\n [disabled]=\"col.readonly\"\r\n [ngModel]=\"getBooleanProperty(row, col.key)\"\r\n (ngModelChange)=\"\r\n onCellChange(row, col.key, $event, 'boolean')\r\n \"\r\n ></mt-toggle-field>\r\n }\r\n }\r\n @case (\"date\") {\r\n {{\r\n getDateProperty(row, col.key) | mtDateFormat: \"date\"\r\n }}\r\n }\r\n @case (\"dateTime\") {\r\n {{\r\n getDateProperty(row, col.key)\r\n | mtDateFormat: \"dateTime\"\r\n }}\r\n }\r\n @case (\"user\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n filterableCell;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n }\r\n @case (\"status\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n filterableCell;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n }\r\n @case (\"entity\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n filterableCell;\r\n context: { row: row, col: col }\r\n \"\r\n ></ng-container>\r\n }\r\n @case (\"custom\") {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n col.customCellTpl;\r\n context: { $implicit: row }\r\n \"\r\n >\r\n </ng-container>\r\n }\r\n @default {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n </td>\r\n }\r\n\r\n @if (rowActions().length > 0) {\r\n <td class=\"text-right\">\r\n @if (actionShape() === \"popover\") {\r\n <div class=\"flex items-center justify-end\">\r\n <mt-button\r\n icon=\"general.dots-vertical\"\r\n severity=\"secondary\"\r\n variant=\"text\"\r\n size=\"large\"\r\n (click)=\"rowPopover.toggle($event)\"\r\n data-row-click-ignore=\"true\"\r\n ></mt-button>\r\n <p-popover #rowPopover appendTo=\"body\">\r\n <div class=\"flex flex-col min-w-40\">\r\n @for (\r\n action of getVisibleRowActions(row);\r\n track $index\r\n ) {\r\n <button\r\n class=\"flex items-center gap-2 px-2 cursor-pointer py-2 text-sm rounded transition-colors\"\r\n [class]=\"\r\n action.color === 'danger'\r\n ? 'text-red-600 hover:bg-red-50 dark:hover:bg-red-950'\r\n : 'text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-surface-700'\r\n \"\r\n (click)=\"\r\n rowAction($event, action, row);\r\n rowPopover.hide()\r\n \"\r\n >\r\n @if (action.icon) {\r\n <mt-icon\r\n [icon]=\"action.icon\"\r\n class=\"text-base\"\r\n />\r\n }\r\n <span>{{\r\n action.label || action.tooltip\r\n }}</span>\r\n </button>\r\n }\r\n </div>\r\n </p-popover>\r\n </div>\r\n } @else {\r\n <div class=\"flex items-center justify-end space-x-2\">\r\n @for (action of rowActions(); track $index) {\r\n @let hidden = action.hidden?.(row);\r\n @if (!hidden) {\r\n <mt-button\r\n [icon]=\"action.icon\"\r\n [severity]=\"action.color\"\r\n [variant]=\"action.variant\"\r\n [size]=\"action.size || 'small'\"\r\n (click)=\"rowAction($event, action, row)\"\r\n [tooltip]=\"action.tooltip\"\r\n [label]=\"action.label\"\r\n [loading]=\"resolveActionLoading(action, row)\"\r\n ></mt-button>\r\n }\r\n }\r\n </div>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template #filterableCell let-row=\"row\" let-col=\"col\">\r\n @let filterable = isCellClickFilterable(col, row);\r\n @let active = isCellFilterActive(row, col);\r\n @if (filterable) {\r\n <span\r\n data-row-click-ignore=\"true\"\r\n class=\"flex w-full items-center rounded transition-colors cursor-pointer\"\r\n [class.ring-2]=\"active\"\r\n [class.ring-primary-400]=\"active\"\r\n (click)=\"onCellFilterClick($event, row, col)\"\r\n >\r\n @if (resolveCellEntityData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n </span>\r\n } @else {\r\n @if (resolveCellEntityData(row, col); as entityData) {\r\n <mt-entity-preview\r\n [data]=\"entityData\"\r\n attachmentShape=\"compact\"\r\n ></mt-entity-preview>\r\n } @else {\r\n {{ getProperty(row, col.key) }}\r\n }\r\n }\r\n </ng-template>\r\n <ng-template #groupheader let-row>\r\n @if (grouping.groupingActive()) {\r\n <tr\r\n class=\"mt-group-header\"\r\n [style.--mt-group-accent]=\"\r\n grouping.getGroupAccentColor(row) ??\r\n 'var(--p-primary-color)'\r\n \"\r\n >\r\n <td [attr.colspan]=\"totalColumnSpan()\" class=\"!p-0\">\r\n <div\r\n class=\"flex items-center gap-3 px-4 py-2 bg-surface-50 dark:bg-surface-900 border-y border-surface-200 dark:border-surface-700\"\r\n >\r\n <span\r\n class=\"mt-group-header__accent inline-block w-1 h-5 rounded-full\"\r\n ></span>\r\n <span\r\n class=\"text-xs uppercase tracking-wide text-gray-500 dark:text-gray-400\"\r\n >\r\n {{ grouping.activeGroupColumn()?.label }}\r\n </span>\r\n <span\r\n class=\"text-sm font-semibold text-gray-900 dark:text-gray-100\"\r\n >\r\n {{ grouping.getGroupLabel(row) }}\r\n </span>\r\n <span\r\n class=\"ml-auto inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 dark:bg-primary-950 dark:text-primary-300\"\r\n >\r\n {{ grouping.getGroupCount(row) }}\r\n </span>\r\n </div>\r\n </td>\r\n </tr>\r\n }\r\n </ng-template>\r\n <ng-template #emptymessage>\r\n <tr>\r\n <td [attr.colspan]=\"totalColumnSpan()\" class=\"text-center\">\r\n <div\r\n class=\"flex min-h-44 flex-col items-center justify-center gap-3 py-8 text-center\"\r\n >\r\n <svg\r\n width=\"152\"\r\n height=\"120\"\r\n viewBox=\"0 0 152 120\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <circle cx=\"76\" cy=\"52\" r=\"52\" fill=\"#E9EAEB\" />\r\n <g filter=\"url(#filter0_ddd_2474_28277)\">\r\n <path\r\n d=\"M77.6 16C66.8273 16 57.2978 21.3233 51.4987 29.4829C49.605 29.0363 47.6301 28.8 45.6 28.8C31.4615 28.8 20 40.2615 20 54.4C20 68.5385 31.4615 80 45.6 80L109.6 80C121.971 80 132 69.9712 132 57.6C132 45.2288 121.971 35.2 109.6 35.2C108.721 35.2 107.854 35.2506 107.002 35.349C102.098 23.9677 90.7797 16 77.6 16Z\"\r\n fill=\"#FAFAFA\"\r\n />\r\n <ellipse\r\n cx=\"45.6\"\r\n cy=\"54.3998\"\r\n rx=\"25.6\"\r\n ry=\"25.6\"\r\n fill=\"url(#paint0_linear_2474_28277)\"\r\n />\r\n <circle\r\n cx=\"77.6016\"\r\n cy=\"48\"\r\n r=\"32\"\r\n fill=\"url(#paint1_linear_2474_28277)\"\r\n />\r\n <ellipse\r\n cx=\"109.599\"\r\n cy=\"57.6002\"\r\n rx=\"22.4\"\r\n ry=\"22.4\"\r\n fill=\"url(#paint2_linear_2474_28277)\"\r\n />\r\n </g>\r\n <circle cx=\"21\" cy=\"19\" r=\"5\" fill=\"#F5F5F5\" />\r\n <circle cx=\"18\" cy=\"109\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"145\" cy=\"35\" r=\"7\" fill=\"#F5F5F5\" />\r\n <circle cx=\"134\" cy=\"8\" r=\"4\" fill=\"#F5F5F5\" />\r\n <foreignObject x=\"44\" y=\"54\" width=\"64\" height=\"64\">\r\n <div\r\n xmlns=\"http://www.w3.org/1999/xhtml\"\r\n style=\"\r\n backdrop-filter: blur(4px);\r\n clip-path: url(#bgblur_0_2474_28277_clip_path);\r\n height: 100%;\r\n width: 100%;\r\n \"\r\n ></div>\r\n </foreignObject>\r\n <g data-figma-bg-blur-radius=\"8\">\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n fill=\"#344054\"\r\n fill-opacity=\"0.4\"\r\n />\r\n <path\r\n d=\"M85 95L81.5001 91.5M84 85.5C84 90.1944 80.1944 94 75.5 94C70.8056 94 67 90.1944 67 85.5C67 80.8056 70.8056 77 75.5 77C80.1944 77 84 80.8056 84 85.5Z\"\r\n stroke=\"white\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </g>\r\n <defs>\r\n <filter\r\n id=\"filter0_ddd_2474_28277\"\r\n x=\"0\"\r\n y=\"16\"\r\n width=\"152\"\r\n height=\"104\"\r\n filterUnits=\"userSpaceOnUse\"\r\n color-interpolation-filters=\"sRGB\"\r\n >\r\n <feFlood\r\n flood-opacity=\"0\"\r\n result=\"BackgroundImageFix\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"1.5\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"3\" />\r\n <feGaussianBlur stdDeviation=\"1.5\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.04 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"BackgroundImageFix\"\r\n result=\"effect1_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"8\" />\r\n <feGaussianBlur stdDeviation=\"4\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.03 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect1_dropShadow_2474_28277\"\r\n result=\"effect2_dropShadow_2474_28277\"\r\n />\r\n <feColorMatrix\r\n in=\"SourceAlpha\"\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"\r\n result=\"hardAlpha\"\r\n />\r\n <feMorphology\r\n radius=\"4\"\r\n operator=\"erode\"\r\n in=\"SourceAlpha\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feOffset dy=\"20\" />\r\n <feGaussianBlur stdDeviation=\"12\" />\r\n <feComposite in2=\"hardAlpha\" operator=\"out\" />\r\n <feColorMatrix\r\n type=\"matrix\"\r\n values=\"0 0 0 0 0.0392157 0 0 0 0 0.0496732 0 0 0 0 0.0705882 0 0 0 0.08 0\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in2=\"effect2_dropShadow_2474_28277\"\r\n result=\"effect3_dropShadow_2474_28277\"\r\n />\r\n <feBlend\r\n mode=\"normal\"\r\n in=\"SourceGraphic\"\r\n in2=\"effect3_dropShadow_2474_28277\"\r\n result=\"shape\"\r\n />\r\n </filter>\r\n <clipPath\r\n id=\"bgblur_0_2474_28277_clip_path\"\r\n transform=\"translate(-44 -54)\"\r\n >\r\n <path\r\n d=\"M52 86C52 72.7452 62.7452 62 76 62C89.2548 62 100 72.7452 100 86C100 99.2548 89.2548 110 76 110C62.7452 110 52 99.2548 52 86Z\"\r\n />\r\n </clipPath>\r\n <linearGradient\r\n id=\"paint0_linear_2474_28277\"\r\n x1=\"25.9429\"\r\n y1=\"37.4855\"\r\n x2=\"71.2\"\r\n y2=\"79.9998\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint1_linear_2474_28277\"\r\n x1=\"53.0301\"\r\n y1=\"26.8571\"\r\n x2=\"109.602\"\r\n y2=\"80\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n <linearGradient\r\n id=\"paint2_linear_2474_28277\"\r\n x1=\"92.3992\"\r\n y1=\"42.8002\"\r\n x2=\"131.999\"\r\n y2=\"80.0002\"\r\n gradientUnits=\"userSpaceOnUse\"\r\n >\r\n <stop stop-color=\"#D0D5DD\" />\r\n <stop\r\n offset=\"0.350715\"\r\n stop-color=\"white\"\r\n stop-opacity=\"0\"\r\n />\r\n </linearGradient>\r\n </defs>\r\n </svg>\r\n <p class=\"m-0 text-base font-medium text-surface-500\">\r\n {{ \"components.table.no-data-found\" | transloco }}\r\n </p>\r\n </div>\r\n </td>\r\n </tr>\r\n </ng-template>\r\n </p-table>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"flex flex-col gap-3 pb-3 px-4\"\r\n [class]=\"'items-' + paginatorPosition()\"\r\n >\r\n <mt-paginator\r\n [(rows)]=\"pageSize\"\r\n [(first)]=\"first\"\r\n [(page)]=\"currentPage\"\r\n [totalRecords]=\"totalRecords()\"\r\n [alwaysShow]=\"alwaysShowPaginator()\"\r\n [rowsPerPageOptions]=\"rowsPerPageOptions()\"\r\n (onPageChange)=\"onPaginatorPage($event)\"\r\n ></mt-paginator>\r\n </div>\r\n </div>\r\n</ng-template>\r\n", styles: [":host ::ng-deep .p-datatable-header{padding:0 0 1.5rem;background:transparent;border:0}:host ::ng-deep .p-datatable-table{border-collapse:separate;border-spacing:0}:host ::ng-deep .p-datatable-thead>tr>th{padding:.9rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#323232;font-size:14px;font-weight:400;line-height:20px;white-space:nowrap}:host ::ng-deep .p-datatable-tbody>tr>td{padding:.72rem 1rem;background:#fff;border-bottom:1px solid #ebebf0;color:#4b4b4b;font-size:14px;font-weight:400;line-height:20px;vertical-align:middle}:host ::ng-deep .p-datatable-tbody>tr:last-child>td{border-bottom:0}:host ::ng-deep .p-datatable-thead>tr>th:first-child{border-top-left-radius:.625rem}:host ::ng-deep .p-datatable-thead>tr>th:last-child{border-top-right-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:first-child{border-bottom-left-radius:.625rem}:host ::ng-deep .p-datatable-tbody>tr:last-child>td:last-child{border-bottom-right-radius:.625rem}.mt-table-clickable-row>td{transition:background-color .16s ease,color .16s ease,border-color .16s ease}.mt-table-clickable-row:hover>td,.mt-table-clickable-row:focus-within>td{background:#fafafa}.mt-table-clickable-row:hover>td:first-child,.mt-table-clickable-row:focus-within>td:first-child{border-inline-start:none}.mt-table-status-entity-row>td{background:#fff}.mt-table-status-entity-row>td:first-child:before{display:none}:host ::ng-deep tr.mt-group-header>td{padding:0!important;background:transparent}tr.mt-group-header .mt-group-header__accent{background:var(--mt-group-accent, var(--p-primary-color))}\n"] }]
|
|
2262
|
+
}], ctorParameters: () => [], propDecorators: { selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], lazyLoad: [{ type: i0.Output, args: ["lazyLoad"] }], columnReorder: [{ type: i0.Output, args: ["columnReorder"] }], rowReorder: [{ type: i0.Output, args: ["rowReorder"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }, { type: i0.Output, args: ["filtersChange"] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: true }] }], rowActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowActions", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showGridlines: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGridlines", required: false }] }], stripedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "stripedRows", required: false }] }], selectableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectableRows", required: false }] }], clickableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickableRows", required: false }] }], generalSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalSearch", required: false }] }], lazyLocalSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyLocalSearch", required: false }] }], showFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFilters", required: false }] }], filterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterMode", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], updating: [{ type: i0.Input, args: [{ isSignal: true, alias: "updating", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], lazyLocalSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyLocalSort", required: false }] }], lazyTotalRecords: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazyTotalRecords", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], reorderableRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableRows", required: false }] }], dataKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataKey", required: false }] }], storageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageKey", required: false }] }], storageMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageMode", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], printable: [{ type: i0.Input, args: [{ isSignal: true, alias: "printable", required: false }] }], groupable: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupable", required: false }] }], cellClickFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellClickFilter", required: false }] }], printTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "printTitle", required: false }] }], exportFilename: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFilename", required: false }] }], actionShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionShape", required: false }] }], tableLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableLayout", required: false }] }], noCard: [{ type: i0.Input, args: [{ isSignal: true, alias: "noCard", required: false }] }], tabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabs", required: false }] }], tabsOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabsOptionLabel", required: false }] }], tabsOptionValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabsOptionValue", required: false }] }], activeTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTab", required: false }] }, { type: i0.Output, args: ["activeTabChange"] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], captionStartContent: [{ type: i0.ContentChild, args: ['captionStart', { isSignal: true }] }], captionEndContent: [{ type: i0.ContentChild, args: ['captionEnd', { isSignal: true }] }], emptyContent: [{ type: i0.ContentChild, args: ['empty', { isSignal: true }] }], paginatorPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginatorPosition", required: false }] }], alwaysShowPaginator: [{ type: i0.Input, args: [{ isSignal: true, alias: "alwaysShowPaginator", required: false }] }], rowsPerPageOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowsPerPageOptions", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], first: [{ type: i0.Input, args: [{ isSignal: true, alias: "first", required: false }] }, { type: i0.Output, args: ["firstChange"] }], filterTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterTerm", required: false }] }, { type: i0.Output, args: ["filterTermChange"] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }, { type: i0.Output, args: ["groupByChange"] }] } });
|
|
1444
2263
|
|
|
1445
2264
|
/**
|
|
1446
2265
|
* Generated bundle index. Do not edit.
|
|
1447
2266
|
*/
|
|
1448
2267
|
|
|
1449
|
-
export { Table, TableFilter };
|
|
2268
|
+
export { Table, TableActionsMenu, TableCaption, TableColumnFilter, TableExportService, TableFilter, TableFilterField, TableGroupingController, TableValueResolver };
|
|
1450
2269
|
//# sourceMappingURL=masterteam-components-table.mjs.map
|