spiderly 19.9.2 → 19.9.4
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/agent/docs/angular-customization/index.md +10 -2
- package/agent/docs/backend-hooks/index.md +12 -1
- package/fesm2022/spiderly.mjs +243 -6
- package/fesm2022/spiderly.mjs.map +1 -1
- package/lib/components/spiderly-data-table/spiderly-data-table.component.d.ts +95 -3
- package/package.json +1 -1
- package/styles/components/spiderly-data-table/spiderly-data-table.component.scss +26 -0
|
@@ -153,6 +153,8 @@ Library components/controls also expose their own `show*` `@Input()`s (e.g. `sho
|
|
|
153
153
|
</spiderly-data-table>
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
+
Lazy tables are always deterministically ordered: when no sort is active the backend falls back to `Id` DESC (newest first). Declare `defaultSortField` (+ `defaultSortOrder`) when a page wants a different, user-visible default — it renders as a normal header sort arrow, persisted user sort wins over it, and un-sorting (tri-state header click, Clear filters) returns to it instead of "unsorted".
|
|
157
|
+
|
|
156
158
|
### Client-Side Mode
|
|
157
159
|
|
|
158
160
|
```html
|
|
@@ -164,9 +166,9 @@ Library components/controls also expose their own `show*` `@Input()`s (e.g. `sho
|
|
|
164
166
|
|
|
165
167
|
```typescript
|
|
166
168
|
cols: Column<ProductDTO>[] = [
|
|
167
|
-
new Column({ field: 'title', name: 'Title', filterType: 'text' }),
|
|
169
|
+
new Column({ field: 'title', name: 'Title', filterType: 'text', lockVisible: true }),
|
|
168
170
|
new Column({ field: 'price', name: 'Price', filterType: 'numeric', showMatchModes: true, decimalPlaces: 2 }),
|
|
169
|
-
new Column({ field: 'createdAt', name: 'Created', filterType: 'date', showTime: true }),
|
|
171
|
+
new Column({ field: 'createdAt', name: 'Created', filterType: 'date', showTime: true, visible: false }),
|
|
170
172
|
new Column({ field: 'isActive', name: 'Active', filterType: 'boolean' }),
|
|
171
173
|
new Column({ field: 'categoryDisplayName', name: 'Category', filterType: 'multiselect',
|
|
172
174
|
dropdownOrMultiselectValues: this.categoryOptions }),
|
|
@@ -180,6 +182,10 @@ cols: Column<ProductDTO>[] = [
|
|
|
180
182
|
];
|
|
181
183
|
```
|
|
182
184
|
|
|
185
|
+
### Column chooser (show/hide columns)
|
|
186
|
+
|
|
187
|
+
Lazy tables render a **Columns** toolbar button opening a checkbox list of all data columns. Because a column's header is the table's only filter surface, showing a column is what makes it filterable — declare rarely-needed but filter-worthy columns with `visible: false` (available in the chooser, hidden by default) and pin the row's identifying column with `lockVisible: true`. Rules the table enforces: hiding a column clears its active filter + sort (one reload; plain hides don't hit the server), choices persist per table in `localStorage` under `` `${stateKey}:columns` `` (durable even with `stateStorage: 'session'`; only explicit toggles are stored, so later declared-default changes flow through), the last visible data column can't be hidden, and *Reset to default* restores the declared configuration.
|
|
188
|
+
|
|
183
189
|
The `onClick` callback receives an `ActionClickEvent` — `{ id, row, element, originalEvent }`. Use `element` (or `originalEvent`) to anchor an overlay/popover to the clicked action; `row` gives you the full row object. It fires only for custom `field` values (never `'Details'` / `'Delete'`).
|
|
184
190
|
|
|
185
191
|
For a click on the cell value itself (not an action icon), set a column's `onCellClick` callback — the mirror of `Action.onClick`, but for plain value cells:
|
|
@@ -228,6 +234,8 @@ Project an `<ng-template spiderlyDataTableActions>` to add your own buttons (or
|
|
|
228
234
|
| `selectionMode` | `'single' \| 'multiple'` | — | Selection mode |
|
|
229
235
|
| `navigateOnRowClick` | `boolean` | `false` | Click row → details |
|
|
230
236
|
| `rowNavigationPath` | `string` | — | Base path for row click |
|
|
237
|
+
| `defaultSortField` | `string` | — | Sort applied while the user has none |
|
|
238
|
+
| `defaultSortOrder` | `1 \| -1` | `1` | Direction for `defaultSortField` |
|
|
231
239
|
| `showAddButton` | `boolean` | `true` | Show "New" button |
|
|
232
240
|
| `showExportToExcelButton` | `boolean` | `true` | Show Excel export |
|
|
233
241
|
| `readonly` | `boolean` | `false` | Disable mutations |
|
|
@@ -66,15 +66,26 @@ protected virtual async Task OnAfterSave{Entity}AndReturnMainUIFormDTO(
|
|
|
66
66
|
### Delete Hooks
|
|
67
67
|
|
|
68
68
|
```csharp
|
|
69
|
+
// Before the delete — rows still exist; validation / capturing data that dies with the rows.
|
|
69
70
|
// Default forwards to OnBefore{Entity}ListDelete with a single-element list.
|
|
70
71
|
public virtual Task OnBefore{Entity}Delete({IdType} id) =>
|
|
71
72
|
OnBefore{Entity}ListDelete(id.StructToList());
|
|
72
73
|
|
|
73
74
|
public virtual async Task OnBefore{Entity}ListDelete(List<{IdType}> ids) { }
|
|
75
|
+
|
|
76
|
+
// After the delete (cascades included), still inside the transaction — queries observe
|
|
77
|
+
// the post-delete state; writes commit or roll back atomically with the delete.
|
|
78
|
+
// Default forwards to OnAfter{Entity}ListDelete with a single-element list.
|
|
79
|
+
public virtual Task OnAfter{Entity}Delete({IdType} id) =>
|
|
80
|
+
OnAfter{Entity}ListDelete(id.StructToList());
|
|
81
|
+
|
|
82
|
+
public virtual async Task OnAfter{Entity}ListDelete(List<{IdType}> deletedIds) { }
|
|
74
83
|
```
|
|
75
84
|
|
|
76
85
|
**When single and batch deletes need the same logic, override only the list hook** — the single-id path forwards to it automatically. Override the single hook only when the per-id behaviour genuinely diverges from the batch case.
|
|
77
86
|
|
|
87
|
+
**Recomputing denormalized aggregates belongs in the After hook**, where a plain query reads the real post-delete state. In the Before hook the doomed rows still exist, so an aggregate query there would have to exclude them by hand to simulate the future state.
|
|
88
|
+
|
|
78
89
|
### Get Hooks
|
|
79
90
|
|
|
80
91
|
```csharp
|
|
@@ -127,7 +138,7 @@ protected virtual async Task<IQueryable<{Related}>> GetAll{Property}QueryFor{Ent
|
|
|
127
138
|
|
|
128
139
|
Every generated method wraps its logic in `_context.WithTransactionAsync(...)`. Nested calls reuse the existing transaction. You do **not** need to start your own transaction in hooks.
|
|
129
140
|
|
|
130
|
-
**Generated CRUD operations flush the change tracker before commit**, so you can stage tracked writes — an entity `Add`/`Update`, or `IOutbox.Enqueue` — inside any `OnBefore...` hook
|
|
141
|
+
**Generated CRUD operations flush the change tracker before commit**, so you can stage tracked writes — an entity `Add`/`Update`, or `IOutbox.Enqueue` — inside any `OnBefore...` hook or the delete-side `OnAfter...Delete` hooks, and they persist atomically with the operation; no manual `SaveChangesAsync`. This holds even though the delete path deletes via untracked bulk `ExecuteDeleteAsync` — the operation still flushes whatever the hook staged. Two exceptions: the save-side `OnAfterSave...` hook runs after the save's own flush, so a tracked write staged there needs its own `SaveChangesAsync`; and in a **custom** (non-hook) `WithTransactionAsync` block you must `SaveChangesAsync` yourself — `WithTransactionAsync`'s clean-tracker-at-commit guard throws otherwise.
|
|
131
142
|
|
|
132
143
|
If you need a transaction in **custom** (non-hook) methods:
|
|
133
144
|
|
package/fesm2022/spiderly.mjs
CHANGED
|
@@ -65,6 +65,8 @@ import { AvatarModule } from 'primeng/avatar';
|
|
|
65
65
|
import { BadgeModule } from 'primeng/badge';
|
|
66
66
|
import * as i4$a from 'primeng/menubar';
|
|
67
67
|
import { MenubarModule } from 'primeng/menubar';
|
|
68
|
+
import * as i14 from 'primeng/popover';
|
|
69
|
+
import { PopoverModule } from 'primeng/popover';
|
|
68
70
|
import * as i10 from 'primeng/table';
|
|
69
71
|
import { TableModule } from 'primeng/table';
|
|
70
72
|
import * as i2$2 from 'primeng/confirmdialog';
|
|
@@ -3952,6 +3954,15 @@ class SpiderlyDataTableComponent {
|
|
|
3952
3954
|
this.hasLazyLoad = true;
|
|
3953
3955
|
/** 'session' persists across refresh only; 'local' persists indefinitely. */
|
|
3954
3956
|
this.stateStorage = 'session';
|
|
3957
|
+
/** Direction for `defaultSortField`: 1 ascending (default), -1 descending. */
|
|
3958
|
+
this.defaultSortOrder = 1;
|
|
3959
|
+
this.initialMultiSortMeta = null;
|
|
3960
|
+
/** Columns currently rendered — `cols` minus the hidden ones. Actions columns always render. */
|
|
3961
|
+
this.visibleCols = [];
|
|
3962
|
+
/** Cached count of visible data columns, so template bindings don't re-derive it per CD cycle. */
|
|
3963
|
+
this.visibleDataColsCount = 0;
|
|
3964
|
+
/** Data columns offered in the column chooser (actions columns are excluded). */
|
|
3965
|
+
this.chooserCols = [];
|
|
3955
3966
|
this.resolvedStateKey = null;
|
|
3956
3967
|
this.selectedItemIds = []; // Pass only when hasLazyLoad === false, it's enough if the M2M association hasn't additional fields
|
|
3957
3968
|
this.selectedItems = []; // Pass only when hasLazyLoad === false
|
|
@@ -3963,13 +3974,27 @@ class SpiderlyDataTableComponent {
|
|
|
3963
3974
|
* Default is false.
|
|
3964
3975
|
*/
|
|
3965
3976
|
this.navigateOnRowClick = false;
|
|
3977
|
+
//#region Column visibility
|
|
3978
|
+
/**
|
|
3979
|
+
* User visibility choices (field → visible), holding only fields the user explicitly
|
|
3980
|
+
* toggled away from their declared default — so a page changing a column's declared
|
|
3981
|
+
* default later flows through to every user who never touched that column.
|
|
3982
|
+
*/
|
|
3983
|
+
this.columnVisibilityOverrides = {};
|
|
3984
|
+
/**
|
|
3985
|
+
* Columns revealed by the load-time reconciliation. Kept apart from
|
|
3986
|
+
* `columnVisibilityOverrides` so persisting a later unrelated toggle can't promote a
|
|
3987
|
+
* transient safety reveal into a durable choice.
|
|
3988
|
+
*/
|
|
3989
|
+
this.revealedByConstraint = new Set();
|
|
3966
3990
|
this.clientFilterCount = 0;
|
|
3967
3991
|
}
|
|
3968
3992
|
ngAfterViewInit() {
|
|
3969
3993
|
this.setupRemovableSort();
|
|
3970
3994
|
}
|
|
3971
3995
|
// PrimeNG v19 removed the removableSort property. This overrides the table's
|
|
3972
|
-
// sort() method to add tri-state cycling: ascending → descending → unsorted
|
|
3996
|
+
// sort() method to add tri-state cycling: ascending → descending → unsorted
|
|
3997
|
+
// (or back to the declared default sort when one is set).
|
|
3973
3998
|
setupRemovableSort() {
|
|
3974
3999
|
const originalSort = this.table.sort.bind(this.table);
|
|
3975
4000
|
this.table.sort = (event) => {
|
|
@@ -3977,11 +4002,16 @@ class SpiderlyDataTableComponent {
|
|
|
3977
4002
|
if (sortMeta && sortMeta.order === -1) {
|
|
3978
4003
|
const mouseEvent = event.originalEvent;
|
|
3979
4004
|
const isMultiSortClick = mouseEvent.metaKey || mouseEvent.ctrlKey;
|
|
4005
|
+
// Un-sorting substitutes the declared default (when there is one) right here,
|
|
4006
|
+
// so sortMultiple() broadcasts and emits the final meta in one shot.
|
|
3980
4007
|
if (isMultiSortClick) {
|
|
3981
|
-
|
|
4008
|
+
const remaining = this.table._multiSortMeta.filter((m) => m.field !== event.field);
|
|
4009
|
+
this.table._multiSortMeta = remaining.length
|
|
4010
|
+
? remaining
|
|
4011
|
+
: (this.defaultMultiSortMeta() ?? remaining);
|
|
3982
4012
|
}
|
|
3983
4013
|
else {
|
|
3984
|
-
this.table._multiSortMeta = [];
|
|
4014
|
+
this.table._multiSortMeta = this.defaultMultiSortMeta() ?? [];
|
|
3985
4015
|
if (this.table.resetPageOnSort) {
|
|
3986
4016
|
this.table._first = 0;
|
|
3987
4017
|
this.table.firstChange.emit(0);
|
|
@@ -4041,8 +4071,208 @@ class SpiderlyDataTableComponent {
|
|
|
4041
4071
|
else {
|
|
4042
4072
|
this.clientLoad();
|
|
4043
4073
|
}
|
|
4074
|
+
this.restoreColumnVisibility();
|
|
4075
|
+
this.reconcileVisibilityWithPersistedConstraints();
|
|
4076
|
+
this.chooserCols = this.cols.filter(SpiderlyDataTableComponent.isDataColumn);
|
|
4077
|
+
this.refreshVisibleCols();
|
|
4078
|
+
// Bound to p-table's [multiSortMeta] so the FIRST request already carries the right
|
|
4079
|
+
// sort. Persisted user sort wins over the declared default; we read it ourselves
|
|
4080
|
+
// because PrimeNG's restoreState() runs on the first [value] change — after the
|
|
4081
|
+
// initial lazy emit has already left.
|
|
4082
|
+
this.initialMultiSortMeta =
|
|
4083
|
+
this.persistedMultiSortMeta() ?? this.defaultMultiSortMeta();
|
|
4084
|
+
}
|
|
4085
|
+
/** A data column shows values for a `field`; anything else (the actions column) always renders. */
|
|
4086
|
+
static isDataColumn(col) {
|
|
4087
|
+
return !!col.field;
|
|
4088
|
+
}
|
|
4089
|
+
/**
|
|
4090
|
+
* Storage slot for the visibility overrides. Deliberately ALWAYS localStorage, even when
|
|
4091
|
+
* `stateStorage` is 'session': the column layout is a durable preference, while filters
|
|
4092
|
+
* are a transient working set — different natural lifetimes.
|
|
4093
|
+
*/
|
|
4094
|
+
get columnsStateKey() {
|
|
4095
|
+
return this.resolvedStateKey ? `${this.resolvedStateKey}:columns` : null;
|
|
4096
|
+
}
|
|
4097
|
+
/** Actions columns always render; data columns follow reveal/override, then declared default. */
|
|
4098
|
+
isColumnVisible(col) {
|
|
4099
|
+
if (!SpiderlyDataTableComponent.isDataColumn(col))
|
|
4100
|
+
return true;
|
|
4101
|
+
if (col.lockVisible)
|
|
4102
|
+
return true; // pinned — wins over any (possibly stale) override
|
|
4103
|
+
if (this.revealedByConstraint.has(col.field))
|
|
4104
|
+
return true;
|
|
4105
|
+
return this.columnVisibilityOverrides[col.field] ?? col.visible !== false;
|
|
4106
|
+
}
|
|
4107
|
+
refreshVisibleCols() {
|
|
4108
|
+
this.visibleCols = this.cols.filter((col) => this.isColumnVisible(col));
|
|
4109
|
+
this.visibleDataColsCount = this.visibleCols.filter(SpiderlyDataTableComponent.isDataColumn).length;
|
|
4110
|
+
}
|
|
4111
|
+
/**
|
|
4112
|
+
* Locked columns can't be toggled; the last visible data column can't be hidden — the
|
|
4113
|
+
* table must never collapse to just an actions column. Revealing is always allowed.
|
|
4114
|
+
*/
|
|
4115
|
+
canToggleColumn(col) {
|
|
4116
|
+
if (col.lockVisible)
|
|
4117
|
+
return false;
|
|
4118
|
+
if (!this.isColumnVisible(col))
|
|
4119
|
+
return true;
|
|
4120
|
+
return this.visibleDataColsCount > 1;
|
|
4121
|
+
}
|
|
4122
|
+
toggleColumn(col, visible) {
|
|
4123
|
+
this.revealedByConstraint.delete(col.field); // an explicit choice supersedes a safety reveal
|
|
4124
|
+
if (visible === (col.visible !== false)) {
|
|
4125
|
+
delete this.columnVisibilityOverrides[col.field]; // back at the declared default
|
|
4126
|
+
}
|
|
4127
|
+
else {
|
|
4128
|
+
this.columnVisibilityOverrides[col.field] = visible;
|
|
4129
|
+
}
|
|
4130
|
+
this.persistColumnVisibility();
|
|
4131
|
+
this.refreshVisibleCols();
|
|
4132
|
+
if (!visible)
|
|
4133
|
+
this.clearHiddenColumnConstraints([col]);
|
|
4134
|
+
}
|
|
4135
|
+
/** Restores every column to its declared default and forgets the stored override. */
|
|
4136
|
+
resetColumnVisibility() {
|
|
4137
|
+
const wasVisible = this.visibleCols.filter(SpiderlyDataTableComponent.isDataColumn);
|
|
4138
|
+
this.revealedByConstraint.clear();
|
|
4139
|
+
this.columnVisibilityOverrides = {};
|
|
4140
|
+
this.persistColumnVisibility();
|
|
4141
|
+
this.refreshVisibleCols();
|
|
4142
|
+
// Columns the reset just hid follow the same rule as a manual hide.
|
|
4143
|
+
this.clearHiddenColumnConstraints(wasVisible.filter((col) => !this.isColumnVisible(col)));
|
|
4144
|
+
}
|
|
4145
|
+
/**
|
|
4146
|
+
* A hidden column contributes nothing to filtering or sorting: the header is the only
|
|
4147
|
+
* filter surface, so a kept constraint would restrict the data invisibly. Reloads (once)
|
|
4148
|
+
* only when a constraint was actually cleared — plain hides don't need a server round-trip.
|
|
4149
|
+
*/
|
|
4150
|
+
clearHiddenColumnConstraints(cols) {
|
|
4151
|
+
if (!this.table)
|
|
4152
|
+
return;
|
|
4153
|
+
let cleared = false;
|
|
4154
|
+
for (const col of cols) {
|
|
4155
|
+
const filterKey = col.filterField ?? col.field;
|
|
4156
|
+
if (SpiderlyDataTableComponent.isActiveFilterMeta(this.table.filters?.[filterKey])) {
|
|
4157
|
+
delete this.table.filters[filterKey];
|
|
4158
|
+
cleared = true;
|
|
4159
|
+
}
|
|
4160
|
+
if (this.table._multiSortMeta?.some((m) => m.field === col.field)) {
|
|
4161
|
+
this.table._multiSortMeta = this.table._multiSortMeta.filter((m) => m.field !== col.field);
|
|
4162
|
+
this.table.tableService.onSort(this.table._multiSortMeta);
|
|
4163
|
+
cleared = true;
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
if (cleared)
|
|
4167
|
+
this.table._filter(); // re-emits the lazy load and saves the cleaned state
|
|
4168
|
+
}
|
|
4169
|
+
/** Whether filter metadata (single or array) carries a real constraint, not just an empty slot. */
|
|
4170
|
+
static isActiveFilterMeta(meta) {
|
|
4171
|
+
return (Array.isArray(meta) ? meta : [meta]).some((m) => m?.value != null &&
|
|
4172
|
+
m.value !== '' &&
|
|
4173
|
+
(!Array.isArray(m.value) || m.value.length > 0));
|
|
4174
|
+
}
|
|
4175
|
+
persistColumnVisibility() {
|
|
4176
|
+
if (!this.columnsStateKey)
|
|
4177
|
+
return;
|
|
4178
|
+
if (Object.keys(this.columnVisibilityOverrides).length === 0) {
|
|
4179
|
+
localStorage.removeItem(this.columnsStateKey);
|
|
4180
|
+
}
|
|
4181
|
+
else {
|
|
4182
|
+
localStorage.setItem(this.columnsStateKey, JSON.stringify(this.columnVisibilityOverrides));
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
restoreColumnVisibility() {
|
|
4186
|
+
if (!this.columnsStateKey)
|
|
4187
|
+
return;
|
|
4188
|
+
this.columnVisibilityOverrides =
|
|
4189
|
+
SpiderlyDataTableComponent.readStoredJson(localStorage, this.columnsStateKey) ?? {};
|
|
4190
|
+
}
|
|
4191
|
+
/** Parses a JSON entry from web storage; missing or corrupted entries read as null. */
|
|
4192
|
+
static readStoredJson(storage, key) {
|
|
4193
|
+
try {
|
|
4194
|
+
return JSON.parse(storage.getItem(key) ?? 'null');
|
|
4195
|
+
}
|
|
4196
|
+
catch {
|
|
4197
|
+
return null;
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
/**
|
|
4201
|
+
* PrimeNG's persisted table state (filters/sort/pagination), read directly from storage
|
|
4202
|
+
* because we need it before PrimeNG's restoreState() runs on the first [value] change.
|
|
4203
|
+
*/
|
|
4204
|
+
persistedTableState() {
|
|
4205
|
+
if (!this.resolvedStateKey)
|
|
4206
|
+
return null;
|
|
4207
|
+
return SpiderlyDataTableComponent.readStoredJson(this.stateStorage === 'local' ? localStorage : sessionStorage, this.resolvedStateKey);
|
|
4208
|
+
}
|
|
4209
|
+
/**
|
|
4210
|
+
* Guards the "hidden contributes nothing" invariant against state this component didn't
|
|
4211
|
+
* write (older blobs, hand-edited storage): a hidden column the persisted table state
|
|
4212
|
+
* still filters or sorts by is revealed rather than constraining the data invisibly.
|
|
4213
|
+
* In-memory only — once the constraint is gone, the user's stored choice reapplies.
|
|
4214
|
+
*/
|
|
4215
|
+
reconcileVisibilityWithPersistedConstraints() {
|
|
4216
|
+
const state = this.persistedTableState();
|
|
4217
|
+
if (!state)
|
|
4218
|
+
return;
|
|
4219
|
+
const constrained = new Set();
|
|
4220
|
+
for (const [field, meta] of Object.entries(state.filters ?? {})) {
|
|
4221
|
+
if (SpiderlyDataTableComponent.isActiveFilterMeta(meta))
|
|
4222
|
+
constrained.add(field);
|
|
4223
|
+
}
|
|
4224
|
+
for (const sortMeta of state.multiSortMeta ?? []) {
|
|
4225
|
+
if (sortMeta?.field)
|
|
4226
|
+
constrained.add(sortMeta.field);
|
|
4227
|
+
}
|
|
4228
|
+
for (const col of this.cols) {
|
|
4229
|
+
if (!SpiderlyDataTableComponent.isDataColumn(col))
|
|
4230
|
+
continue;
|
|
4231
|
+
if (this.isColumnVisible(col))
|
|
4232
|
+
continue;
|
|
4233
|
+
if (constrained.has(col.field) || constrained.has(col.filterField)) {
|
|
4234
|
+
this.revealedByConstraint.add(col.field);
|
|
4235
|
+
}
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
//#endregion
|
|
4239
|
+
/**
|
|
4240
|
+
* The declared default as PrimeNG sort meta, or null when none is declared — or when its
|
|
4241
|
+
* column is hidden ("hidden contributes nothing"): the table then falls back to the
|
|
4242
|
+
* backend's implicit Id DESC, exactly as if no default were declared.
|
|
4243
|
+
*/
|
|
4244
|
+
defaultMultiSortMeta() {
|
|
4245
|
+
if (!this.defaultSortField)
|
|
4246
|
+
return null;
|
|
4247
|
+
const defaultSortCol = this.cols?.find((col) => col.field === this.defaultSortField);
|
|
4248
|
+
if (defaultSortCol && !this.isColumnVisible(defaultSortCol))
|
|
4249
|
+
return null;
|
|
4250
|
+
return [{ field: this.defaultSortField, order: this.defaultSortOrder }];
|
|
4251
|
+
}
|
|
4252
|
+
persistedMultiSortMeta() {
|
|
4253
|
+
const state = this.persistedTableState();
|
|
4254
|
+
return state?.multiSortMeta?.length ? state.multiSortMeta : null;
|
|
4255
|
+
}
|
|
4256
|
+
// Safety net: any lazy load still leaving unsorted (Clear filters — PrimeNG's clear()
|
|
4257
|
+
// nulls the sort and emits in one call — or stale persisted state) falls back to the
|
|
4258
|
+
// declared default. Patching the event before it becomes the backend Filter avoids a
|
|
4259
|
+
// second fetch; clear() broadcasts sort state to the header icons before emitting,
|
|
4260
|
+
// hence the explicit re-broadcast. The tri-state un-sort path never gets here — it
|
|
4261
|
+
// substitutes the default at its source in setupRemovableSort().
|
|
4262
|
+
applyDefaultSortIfUnsorted(event) {
|
|
4263
|
+
if (event.multiSortMeta?.length)
|
|
4264
|
+
return;
|
|
4265
|
+
const defaultSort = this.defaultMultiSortMeta();
|
|
4266
|
+
if (defaultSort == null)
|
|
4267
|
+
return;
|
|
4268
|
+
event.multiSortMeta = defaultSort;
|
|
4269
|
+
if (this.table) {
|
|
4270
|
+
this.table._multiSortMeta = defaultSort;
|
|
4271
|
+
this.table.tableService.onSort(defaultSort);
|
|
4272
|
+
}
|
|
4044
4273
|
}
|
|
4045
4274
|
lazyLoad(event) {
|
|
4275
|
+
this.applyDefaultSortIfUnsorted(event);
|
|
4046
4276
|
this.lastLazyLoadEvent = event;
|
|
4047
4277
|
let tableFilter = event;
|
|
4048
4278
|
tableFilter.additionalFilterIdLong = this.additionalFilterIdLong;
|
|
@@ -4482,7 +4712,7 @@ class SpiderlyDataTableComponent {
|
|
|
4482
4712
|
}
|
|
4483
4713
|
}
|
|
4484
4714
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: SpiderlyDataTableComponent, deps: [{ token: i3$2.Router }, { token: i1$5.DialogService }, { token: i3$2.ActivatedRoute }, { token: SpiderlyMessageService }, { token: i1.TranslocoService }, { token: ConfigServiceBase }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4485
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.13", type: SpiderlyDataTableComponent, isStandalone: true, selector: "spiderly-data-table", inputs: { tableTitle: "tableTitle", tableIcon: "tableIcon", items: "items", rows: "rows", cols: "cols", showPaginator: "showPaginator", showCardWrapper: "showCardWrapper", readonly: "readonly", idField: "idField", getPaginatedListObservableMethod: "getPaginatedListObservableMethod", exportListToExcelObservableMethod: "exportListToExcelObservableMethod", deleteItemFromTableObservableMethod: "deleteItemFromTableObservableMethod", deleteListFromTableObservableMethod: "deleteListFromTableObservableMethod", newlySelectedItems: "newlySelectedItems", unselectedItems: "unselectedItems", selectionMode: "selectionMode", selectedLazyLoadObservableMethod: "selectedLazyLoadObservableMethod", additionalFilterIdLong: "additionalFilterIdLong", showAddButton: "showAddButton", showExportToExcelButton: "showExportToExcelButton", showReloadTableButton: "showReloadTableButton", getFormArrayItems: "getFormArrayItems", hasLazyLoad: "hasLazyLoad", stateKey: "stateKey", stateStorage: "stateStorage", getAlreadySelectedItemIds: "getAlreadySelectedItemIds", getAlreadySelectedItems: "getAlreadySelectedItems", getFormControl: "getFormControl", additionalIndexes: "additionalIndexes", navigateOnRowClick: "navigateOnRowClick", rowNavigationPath: "rowNavigationPath" }, outputs: { onTotalRecordsChange: "onTotalRecordsChange", onLazyLoad: "onLazyLoad", onIsAllSelectedChange: "onIsAllSelectedChange", onRowSelect: "onRowSelect", onRowUnselect: "onRowUnselect" }, queries: [{ propertyName: "actionsTemplate", first: true, predicate: SpiderlyDataTableActionsDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "table", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n showCardWrapper ? 'card responsive-card-padding overflow-auto' : ''\n \"\n >\n <p-table\n #dt\n [value]=\"items\"\n [rows]=\"rows\"\n [rowHover]=\"true\"\n [paginator]=\"showPaginator\"\n responsiveLayout=\"scroll\"\n [lazy]=\"hasLazyLoad\"\n (onLazyLoad)=\"lazyLoad($event)\"\n [totalRecords]=\"totalRecords\"\n class=\"spiderly-table\"\n [loading]=\"items === undefined || loading === true\"\n [selectionMode]=\"selectionMode\"\n dataKey=\"id\"\n (onFilter)=\"filter($event)\"\n sortMode=\"multiple\"\n [stateKey]=\"resolvedStateKey\"\n [stateStorage]=\"stateStorage\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"table-header overflow-auto\">\n <div style=\"display: flex; align-items: center; gap: 8px\">\n <i class=\"{{ tableIcon }}\" style=\"font-size: 20px\"></i>\n <div style=\"margin: 0px; font-size: 17.5px\">{{ tableTitle }}</div>\n </div>\n <div style=\"display: flex; gap: 8px\">\n <ng-container\n *ngIf=\"actionsTemplate\"\n [ngTemplateOutlet]=\"actionsTemplate\"\n ></ng-container>\n <button\n pButton\n [label]=\"t('ClearFilters')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-filter-slash\"\n (click)=\"clear(dt)\"\n ></button>\n <button\n pButton\n *ngIf=\"showExportToExcelButton\"\n [label]=\"t('ExportToExcel')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-download\"\n (click)=\"exportListToExcel()\"\n ></button>\n <button\n pButton\n *ngIf=\"showReloadTableButton\"\n [label]=\"t('Reload')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-refresh\"\n (click)=\"reload()\"\n ></button>\n <button\n pButton\n *ngIf=\"deleteListFromTableObservableMethod && rowsSelectedNumber > 0\"\n [label]=\"t('DeleteSelected') + ' (' + rowsSelectedNumber + ')'\"\n class=\"p-button-danger\"\n style=\"flex: none\"\n icon=\"pi pi-trash\"\n (click)=\"deleteSelectedObjects()\"\n ></button>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th style=\"width: 0rem\" *ngIf=\"selectionMode == 'multiple'\">\n <div style=\"display: flex; gap: 8px\">\n <p-checkbox\n *ngIf=\"showSelectAllCheckbox\"\n [disabled]=\"readonly\"\n (onChange)=\"selectAll($event.checked)\"\n [(ngModel)]=\"fakeIsAllSelected\"\n [binary]=\"true\"\n ></p-checkbox>\n ({{ rowsSelectedNumber }})\n </div>\n </th>\n <ng-container *ngFor=\"let col of cols; trackBy: colTrackByFn\">\n <th\n [pSortableColumn]=\"col.field\"\n [pSortableColumnDisabled]=\"col.sortable === false || !col.field\"\n [style]=\"getColHeaderWidth(col.filterType)\"\n >\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n \"\n >\n <span style=\"display: flex; align-items: center; gap: 4px\">\n {{ col.name }}\n <p-sortIcon\n *ngIf=\"col.sortable !== false && col.field\"\n [field]=\"col.field!\"\n ></p-sortIcon>\n </span>\n <p-columnFilter\n *ngIf=\"col.filterType != null && col.filterType !== 'blob'\"\n [type]=\"col.filterType\"\n [field]=\"col.filterField ?? col.field\"\n display=\"menu\"\n [placeholder]=\"col.filterPlaceholder\"\n [showOperator]=\"false\"\n [showMatchModes]=\"col.showMatchModes\"\n [showAddButton]=\"col.showAddButton\"\n [matchModeOptions]=\"getColMatchModeOptions(col.filterType)\"\n [matchMode]=\"getColMatchMode(col.filterType)\"\n >\n <ng-template\n *ngIf=\"isDropOrMulti(col.filterType)\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-multiSelect\n [ngModel]=\"value\"\n [options]=\"col.dropdownOrMultiselectValues\"\n [placeholder]=\"t('All')\"\n (onChange)=\"filter($event.value)\"\n optionLabel=\"label\"\n optionValue=\"code\"\n [style]=\"{ width: '240px' }\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"p-multiselect-representative-option\">\n <span class=\"ml-2\">{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-template>\n <ng-template\n *ngIf=\"col.filterType == 'date'\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-datepicker\n [ngModel]=\"value\"\n [showTime]=\"col.showTime\"\n (onSelect)=\"filter($event)\"\n ></p-datepicker>\n </ng-template>\n </p-columnFilter>\n </div>\n </th>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template\n pTemplate=\"body\"\n let-rowData\n let-index=\"rowIndex\"\n let-editing=\"editing\"\n >\n <tr\n [class.clickable]=\"navigateOnRowClick\"\n (click)=\"onRowClick(rowData)\"\n >\n <td *ngIf=\"selectionMode == 'multiple'\">\n <p-checkbox\n [disabled]=\"readonly\"\n (onChange)=\"selectRow(rowData[idField], rowData.index)\"\n [ngModel]=\"isRowSelected(rowData[idField])\"\n [binary]=\"true\"\n ></p-checkbox>\n </td>\n <ng-container *ngFor=\"let col of cols; trackBy: colTrackByFn\">\n <td\n [style]=\"getStyleForBodyColumn(col)\"\n [class.clickable]=\"col.onCellClick\"\n (click)=\"onCellClick(col, rowData, $event)\"\n *ngIf=\"!col.editable\"\n >\n <div\n style=\"\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 18px;\n \"\n >\n <ng-container\n *ngFor=\"let action of col.actions; trackBy: actionTrackByFn\"\n >\n <span\n [pTooltip]=\"action.name\"\n [class]=\"getClassForAction(action)\"\n [style]=\"getStyleForAction(action)\"\n (click)=\"getMethodForAction(action, rowData, $event)\"\n ></span>\n </ng-container>\n </div>\n <ng-container *ngIf=\"col.filterType === 'blob'\">\n <img width=\"45\" [src]=\"getRowData(rowData, col)\" alt=\"\" />\n </ng-container>\n <ng-container *ngIf=\"col.filterType !== 'blob'\">\n {{ getRowData(rowData, col) }}\n </ng-container>\n </td>\n <td *ngIf=\"col.editable\">\n <spiderly-number\n [control]=\"getFormArrayControlByIndex(col.field, rowData.index)\"\n [showLabel]=\"false\"\n ></spiderly-number>\n </td>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td\n [attr.colspan]=\"\n cols?.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"NoRecordsFound\") }}\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td\n [attr.colspan]=\"\n cols?.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"Loading\") }}...\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"paginatorleft\">\n {{ t(\"TotalRecords\") }}: {{ totalRecords }}\n </ng-template>\n <ng-template pTemplate=\"paginatorright\">\n <div style=\"display: flex; justify-content: end; gap: 10px\">\n <spiderly-button\n *ngIf=\"showAddButton\"\n [label]=\"t('AddNew')\"\n icon=\"pi pi-plus\"\n (onClick)=\"navigateToDetails(0)\"\n ></spiderly-button>\n </div>\n </ng-template>\n </p-table>\n </div>\n</ng-container>\n", styles: [".table-header{display:flex;justify-content:space-between;align-items:center}@media (max-width: 640px){.table-header{display:flex;flex-direction:column;align-items:start;gap:14px}}.spiderly-table .p-paginator{padding:1rem}@media (min-width: 1400px){.spiderly-table .p-paginator-left-content{position:absolute;padding:14px;left:0}}@media (min-width: 1400px){.spiderly-table .p-paginator-right-content{position:absolute;padding:14px;right:0}}:host ::ng-deep .clickable{cursor:pointer}:host ::ng-deep td.clickable:hover{text-decoration:underline}:host ::ng-deep .p-datatable-thead{position:unset!important}:host ::ng-deep .p-datatable-header{border-radius:6px 6px 0 0}:host ::ng-deep .p-datatable{border-radius:var(--p-content-border-radius);border:1px solid var(--p-datatable-border-color)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: SpiderlyControlsModule }, { kind: "component", type: SpiderlyButtonComponent, selector: "spiderly-button", inputs: ["type"] }, { kind: "component", type: SpiderlyNumberComponent, selector: "spiderly-number", inputs: ["prefix", "showButtons", "decimal", "maxFractionDigits"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i10.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "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", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "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.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i10.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i10.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i10.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i12.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i4$5.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i4$1.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "fluid", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "size", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$2.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "name", "disabled", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "inputStyle", "styleClass", "inputClass", "indeterminate", "size", "formControl", "checkboxIcon", "readonly", "required", "autofocus", "trueValue", "falseValue", "variant"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }] }); }
|
|
4715
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.13", type: SpiderlyDataTableComponent, isStandalone: true, selector: "spiderly-data-table", inputs: { tableTitle: "tableTitle", tableIcon: "tableIcon", items: "items", rows: "rows", cols: "cols", showPaginator: "showPaginator", showCardWrapper: "showCardWrapper", readonly: "readonly", idField: "idField", getPaginatedListObservableMethod: "getPaginatedListObservableMethod", exportListToExcelObservableMethod: "exportListToExcelObservableMethod", deleteItemFromTableObservableMethod: "deleteItemFromTableObservableMethod", deleteListFromTableObservableMethod: "deleteListFromTableObservableMethod", newlySelectedItems: "newlySelectedItems", unselectedItems: "unselectedItems", selectionMode: "selectionMode", selectedLazyLoadObservableMethod: "selectedLazyLoadObservableMethod", additionalFilterIdLong: "additionalFilterIdLong", showAddButton: "showAddButton", showExportToExcelButton: "showExportToExcelButton", showReloadTableButton: "showReloadTableButton", getFormArrayItems: "getFormArrayItems", hasLazyLoad: "hasLazyLoad", stateKey: "stateKey", stateStorage: "stateStorage", defaultSortField: "defaultSortField", defaultSortOrder: "defaultSortOrder", getAlreadySelectedItemIds: "getAlreadySelectedItemIds", getAlreadySelectedItems: "getAlreadySelectedItems", getFormControl: "getFormControl", additionalIndexes: "additionalIndexes", navigateOnRowClick: "navigateOnRowClick", rowNavigationPath: "rowNavigationPath" }, outputs: { onTotalRecordsChange: "onTotalRecordsChange", onLazyLoad: "onLazyLoad", onIsAllSelectedChange: "onIsAllSelectedChange", onRowSelect: "onRowSelect", onRowUnselect: "onRowUnselect" }, queries: [{ propertyName: "actionsTemplate", first: true, predicate: SpiderlyDataTableActionsDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "table", first: true, predicate: ["dt"], descendants: true }], ngImport: i0, template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n showCardWrapper ? 'card responsive-card-padding overflow-auto' : ''\n \"\n >\n <p-table\n #dt\n [value]=\"items\"\n [rows]=\"rows\"\n [rowHover]=\"true\"\n [paginator]=\"showPaginator\"\n responsiveLayout=\"scroll\"\n [lazy]=\"hasLazyLoad\"\n (onLazyLoad)=\"lazyLoad($event)\"\n [totalRecords]=\"totalRecords\"\n class=\"spiderly-table\"\n [loading]=\"items === undefined || loading === true\"\n [selectionMode]=\"selectionMode\"\n dataKey=\"id\"\n (onFilter)=\"filter($event)\"\n sortMode=\"multiple\"\n [multiSortMeta]=\"initialMultiSortMeta\"\n [stateKey]=\"resolvedStateKey\"\n [stateStorage]=\"stateStorage\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"table-header overflow-auto\">\n <div style=\"display: flex; align-items: center; gap: 8px\">\n <i class=\"{{ tableIcon }}\" style=\"font-size: 20px\"></i>\n <div style=\"margin: 0px; font-size: 17.5px\">{{ tableTitle }}</div>\n </div>\n <div style=\"display: flex; gap: 8px\">\n <ng-container\n *ngIf=\"actionsTemplate\"\n [ngTemplateOutlet]=\"actionsTemplate\"\n ></ng-container>\n <button\n pButton\n *ngIf=\"hasLazyLoad\"\n data-testid=\"column-chooser-button\"\n [label]=\"t('Columns')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-sliders-h\"\n (click)=\"columnChooser.toggle($event)\"\n ></button>\n <button\n pButton\n [label]=\"t('ClearFilters')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-filter-slash\"\n (click)=\"clear(dt)\"\n ></button>\n <button\n pButton\n *ngIf=\"showExportToExcelButton\"\n [label]=\"t('ExportToExcel')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-download\"\n (click)=\"exportListToExcel()\"\n ></button>\n <button\n pButton\n *ngIf=\"showReloadTableButton\"\n [label]=\"t('Reload')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-refresh\"\n (click)=\"reload()\"\n ></button>\n <button\n pButton\n *ngIf=\"deleteListFromTableObservableMethod && rowsSelectedNumber > 0\"\n [label]=\"t('DeleteSelected') + ' (' + rowsSelectedNumber + ')'\"\n class=\"p-button-danger\"\n style=\"flex: none\"\n icon=\"pi pi-trash\"\n (click)=\"deleteSelectedObjects()\"\n ></button>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th style=\"width: 0rem\" *ngIf=\"selectionMode == 'multiple'\">\n <div style=\"display: flex; gap: 8px\">\n <p-checkbox\n *ngIf=\"showSelectAllCheckbox\"\n [disabled]=\"readonly\"\n (onChange)=\"selectAll($event.checked)\"\n [(ngModel)]=\"fakeIsAllSelected\"\n [binary]=\"true\"\n ></p-checkbox>\n ({{ rowsSelectedNumber }})\n </div>\n </th>\n <ng-container *ngFor=\"let col of visibleCols; trackBy: colTrackByFn\">\n <th\n [pSortableColumn]=\"col.field\"\n [pSortableColumnDisabled]=\"col.sortable === false || !col.field\"\n [style]=\"getColHeaderWidth(col.filterType)\"\n >\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n \"\n >\n <span style=\"display: flex; align-items: center; gap: 4px\">\n {{ col.name }}\n <p-sortIcon\n *ngIf=\"col.sortable !== false && col.field\"\n [field]=\"col.field!\"\n ></p-sortIcon>\n </span>\n <p-columnFilter\n *ngIf=\"col.filterType != null && col.filterType !== 'blob'\"\n [type]=\"col.filterType\"\n [field]=\"col.filterField ?? col.field\"\n display=\"menu\"\n [placeholder]=\"col.filterPlaceholder\"\n [showOperator]=\"false\"\n [showMatchModes]=\"col.showMatchModes\"\n [showAddButton]=\"col.showAddButton\"\n [matchModeOptions]=\"getColMatchModeOptions(col.filterType)\"\n [matchMode]=\"getColMatchMode(col.filterType)\"\n >\n <ng-template\n *ngIf=\"isDropOrMulti(col.filterType)\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-multiSelect\n [ngModel]=\"value\"\n [options]=\"col.dropdownOrMultiselectValues\"\n [placeholder]=\"t('All')\"\n (onChange)=\"filter($event.value)\"\n optionLabel=\"label\"\n optionValue=\"code\"\n [style]=\"{ width: '240px' }\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"p-multiselect-representative-option\">\n <span class=\"ml-2\">{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-template>\n <ng-template\n *ngIf=\"col.filterType == 'date'\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-datepicker\n [ngModel]=\"value\"\n [showTime]=\"col.showTime\"\n (onSelect)=\"filter($event)\"\n ></p-datepicker>\n </ng-template>\n </p-columnFilter>\n </div>\n </th>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template\n pTemplate=\"body\"\n let-rowData\n let-index=\"rowIndex\"\n let-editing=\"editing\"\n >\n <tr\n [class.clickable]=\"navigateOnRowClick\"\n (click)=\"onRowClick(rowData)\"\n >\n <td *ngIf=\"selectionMode == 'multiple'\">\n <p-checkbox\n [disabled]=\"readonly\"\n (onChange)=\"selectRow(rowData[idField], rowData.index)\"\n [ngModel]=\"isRowSelected(rowData[idField])\"\n [binary]=\"true\"\n ></p-checkbox>\n </td>\n <ng-container *ngFor=\"let col of visibleCols; trackBy: colTrackByFn\">\n <td\n [style]=\"getStyleForBodyColumn(col)\"\n [class.clickable]=\"col.onCellClick\"\n (click)=\"onCellClick(col, rowData, $event)\"\n *ngIf=\"!col.editable\"\n >\n <div\n style=\"\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 18px;\n \"\n >\n <ng-container\n *ngFor=\"let action of col.actions; trackBy: actionTrackByFn\"\n >\n <span\n [pTooltip]=\"action.name\"\n [class]=\"getClassForAction(action)\"\n [style]=\"getStyleForAction(action)\"\n (click)=\"getMethodForAction(action, rowData, $event)\"\n ></span>\n </ng-container>\n </div>\n <ng-container *ngIf=\"col.filterType === 'blob'\">\n <img width=\"45\" [src]=\"getRowData(rowData, col)\" alt=\"\" />\n </ng-container>\n <ng-container *ngIf=\"col.filterType !== 'blob'\">\n {{ getRowData(rowData, col) }}\n </ng-container>\n </td>\n <td *ngIf=\"col.editable\">\n <spiderly-number\n [control]=\"getFormArrayControlByIndex(col.field, rowData.index)\"\n [showLabel]=\"false\"\n ></spiderly-number>\n </td>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td\n [attr.colspan]=\"\n visibleCols.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"NoRecordsFound\") }}\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td\n [attr.colspan]=\"\n visibleCols.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"Loading\") }}...\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"paginatorleft\">\n {{ t(\"TotalRecords\") }}: {{ totalRecords }}\n </ng-template>\n <ng-template pTemplate=\"paginatorright\">\n <div style=\"display: flex; justify-content: end; gap: 10px\">\n <spiderly-button\n *ngIf=\"showAddButton\"\n [label]=\"t('AddNew')\"\n icon=\"pi pi-plus\"\n (onClick)=\"navigateToDetails(0)\"\n ></spiderly-button>\n </div>\n </ng-template>\n </p-table>\n <p-popover #columnChooser>\n <div class=\"column-chooser\">\n <label\n *ngFor=\"let col of chooserCols; trackBy: colTrackByFn\"\n data-testid=\"column-chooser-option\"\n class=\"column-chooser-option\"\n >\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"isColumnVisible(col)\"\n [disabled]=\"!canToggleColumn(col)\"\n (onChange)=\"toggleColumn(col, $event.checked)\"\n ></p-checkbox>\n <span>{{ col.name }}</span>\n </label>\n <button\n type=\"button\"\n data-testid=\"column-chooser-reset\"\n class=\"column-chooser-reset\"\n (click)=\"resetColumnVisibility()\"\n >\n {{ t('ResetToDefault') }}\n </button>\n </div>\n </p-popover>\n </div>\n</ng-container>\n", styles: [".table-header{display:flex;justify-content:space-between;align-items:center}@media (max-width: 640px){.table-header{display:flex;flex-direction:column;align-items:start;gap:14px}}.spiderly-table .p-paginator{padding:1rem}@media (min-width: 1400px){.spiderly-table .p-paginator-left-content{position:absolute;padding:14px;left:0}}@media (min-width: 1400px){.spiderly-table .p-paginator-right-content{position:absolute;padding:14px;right:0}}:host ::ng-deep .clickable{cursor:pointer}:host ::ng-deep td.clickable:hover{text-decoration:underline}:host .column-chooser{display:flex;flex-direction:column;gap:8px}:host .column-chooser-option{display:flex;align-items:center;gap:8px;cursor:pointer}:host .column-chooser-reset{margin-top:4px;padding:0;border:none;background:none;color:var(--p-primary-color);cursor:pointer;align-self:flex-start;font-size:.875rem}:host .column-chooser-reset:hover{text-decoration:underline}:host ::ng-deep .p-datatable-thead{position:unset!important}:host ::ng-deep .p-datatable-header{border-radius:6px 6px 0 0}:host ::ng-deep .p-datatable{border-radius:var(--p-content-border-radius);border:1px solid var(--p-datatable-border-color)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: SpiderlyControlsModule }, { kind: "component", type: SpiderlyButtonComponent, selector: "spiderly-button", inputs: ["type"] }, { kind: "component", type: SpiderlyNumberComponent, selector: "spiderly-number", inputs: ["prefix", "showButtons", "decimal", "maxFractionDigits"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i10.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "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", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "virtualRowHeight", "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.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i10.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i10.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i10.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i12.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "loading", "severity", "raised", "rounded", "text", "outlined", "size", "plain", "fluid", "label", "icon", "buttonProps"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i4$5.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "fluid", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "variant", "appendTo", "dataKey", "name", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "size", "showClear", "autofocus", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i14.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: DatePickerModule }, { kind: "component", type: i4$1.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "style", "styleClass", "inputStyle", "inputId", "name", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "disabled", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "fluid", "icon", "appendTo", "readonlyInput", "shortYearCutoff", "monthNavigator", "yearNavigator", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "required", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "variant", "size", "minDate", "maxDate", "disabledDates", "disabledDays", "yearRange", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "locale", "view", "defaultDate"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i4$2.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["value", "name", "disabled", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "inputStyle", "styleClass", "inputClass", "indeterminate", "size", "formControl", "checkboxIcon", "readonly", "required", "autofocus", "trueValue", "falseValue", "variant"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i5.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions"] }] }); }
|
|
4486
4716
|
}
|
|
4487
4717
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImport: i0, type: SpiderlyDataTableComponent, decorators: [{
|
|
4488
4718
|
type: Component,
|
|
@@ -4494,10 +4724,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImpo
|
|
|
4494
4724
|
TableModule,
|
|
4495
4725
|
ButtonModule,
|
|
4496
4726
|
MultiSelectModule,
|
|
4727
|
+
PopoverModule,
|
|
4497
4728
|
DatePickerModule,
|
|
4498
4729
|
CheckboxModule,
|
|
4499
4730
|
TooltipModule,
|
|
4500
|
-
], template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n showCardWrapper ? 'card responsive-card-padding overflow-auto' : ''\n \"\n >\n <p-table\n #dt\n [value]=\"items\"\n [rows]=\"rows\"\n [rowHover]=\"true\"\n [paginator]=\"showPaginator\"\n responsiveLayout=\"scroll\"\n [lazy]=\"hasLazyLoad\"\n (onLazyLoad)=\"lazyLoad($event)\"\n [totalRecords]=\"totalRecords\"\n class=\"spiderly-table\"\n [loading]=\"items === undefined || loading === true\"\n [selectionMode]=\"selectionMode\"\n dataKey=\"id\"\n (onFilter)=\"filter($event)\"\n sortMode=\"multiple\"\n [stateKey]=\"resolvedStateKey\"\n [stateStorage]=\"stateStorage\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"table-header overflow-auto\">\n <div style=\"display: flex; align-items: center; gap: 8px\">\n <i class=\"{{ tableIcon }}\" style=\"font-size: 20px\"></i>\n <div style=\"margin: 0px; font-size: 17.5px\">{{ tableTitle }}</div>\n </div>\n <div style=\"display: flex; gap: 8px\">\n <ng-container\n *ngIf=\"actionsTemplate\"\n [ngTemplateOutlet]=\"actionsTemplate\"\n ></ng-container>\n <button\n pButton\n [label]=\"t('ClearFilters')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-filter-slash\"\n (click)=\"clear(dt)\"\n ></button>\n <button\n pButton\n *ngIf=\"showExportToExcelButton\"\n [label]=\"t('ExportToExcel')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-download\"\n (click)=\"exportListToExcel()\"\n ></button>\n <button\n pButton\n *ngIf=\"showReloadTableButton\"\n [label]=\"t('Reload')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-refresh\"\n (click)=\"reload()\"\n ></button>\n <button\n pButton\n *ngIf=\"deleteListFromTableObservableMethod && rowsSelectedNumber > 0\"\n [label]=\"t('DeleteSelected') + ' (' + rowsSelectedNumber + ')'\"\n class=\"p-button-danger\"\n style=\"flex: none\"\n icon=\"pi pi-trash\"\n (click)=\"deleteSelectedObjects()\"\n ></button>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th style=\"width: 0rem\" *ngIf=\"selectionMode == 'multiple'\">\n <div style=\"display: flex; gap: 8px\">\n <p-checkbox\n *ngIf=\"showSelectAllCheckbox\"\n [disabled]=\"readonly\"\n (onChange)=\"selectAll($event.checked)\"\n [(ngModel)]=\"fakeIsAllSelected\"\n [binary]=\"true\"\n ></p-checkbox>\n ({{ rowsSelectedNumber }})\n </div>\n </th>\n <ng-container *ngFor=\"let col of cols; trackBy: colTrackByFn\">\n <th\n [pSortableColumn]=\"col.field\"\n [pSortableColumnDisabled]=\"col.sortable === false || !col.field\"\n [style]=\"getColHeaderWidth(col.filterType)\"\n >\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n \"\n >\n <span style=\"display: flex; align-items: center; gap: 4px\">\n {{ col.name }}\n <p-sortIcon\n *ngIf=\"col.sortable !== false && col.field\"\n [field]=\"col.field!\"\n ></p-sortIcon>\n </span>\n <p-columnFilter\n *ngIf=\"col.filterType != null && col.filterType !== 'blob'\"\n [type]=\"col.filterType\"\n [field]=\"col.filterField ?? col.field\"\n display=\"menu\"\n [placeholder]=\"col.filterPlaceholder\"\n [showOperator]=\"false\"\n [showMatchModes]=\"col.showMatchModes\"\n [showAddButton]=\"col.showAddButton\"\n [matchModeOptions]=\"getColMatchModeOptions(col.filterType)\"\n [matchMode]=\"getColMatchMode(col.filterType)\"\n >\n <ng-template\n *ngIf=\"isDropOrMulti(col.filterType)\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-multiSelect\n [ngModel]=\"value\"\n [options]=\"col.dropdownOrMultiselectValues\"\n [placeholder]=\"t('All')\"\n (onChange)=\"filter($event.value)\"\n optionLabel=\"label\"\n optionValue=\"code\"\n [style]=\"{ width: '240px' }\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"p-multiselect-representative-option\">\n <span class=\"ml-2\">{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-template>\n <ng-template\n *ngIf=\"col.filterType == 'date'\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-datepicker\n [ngModel]=\"value\"\n [showTime]=\"col.showTime\"\n (onSelect)=\"filter($event)\"\n ></p-datepicker>\n </ng-template>\n </p-columnFilter>\n </div>\n </th>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template\n pTemplate=\"body\"\n let-rowData\n let-index=\"rowIndex\"\n let-editing=\"editing\"\n >\n <tr\n [class.clickable]=\"navigateOnRowClick\"\n (click)=\"onRowClick(rowData)\"\n >\n <td *ngIf=\"selectionMode == 'multiple'\">\n <p-checkbox\n [disabled]=\"readonly\"\n (onChange)=\"selectRow(rowData[idField], rowData.index)\"\n [ngModel]=\"isRowSelected(rowData[idField])\"\n [binary]=\"true\"\n ></p-checkbox>\n </td>\n <ng-container *ngFor=\"let col of cols; trackBy: colTrackByFn\">\n <td\n [style]=\"getStyleForBodyColumn(col)\"\n [class.clickable]=\"col.onCellClick\"\n (click)=\"onCellClick(col, rowData, $event)\"\n *ngIf=\"!col.editable\"\n >\n <div\n style=\"\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 18px;\n \"\n >\n <ng-container\n *ngFor=\"let action of col.actions; trackBy: actionTrackByFn\"\n >\n <span\n [pTooltip]=\"action.name\"\n [class]=\"getClassForAction(action)\"\n [style]=\"getStyleForAction(action)\"\n (click)=\"getMethodForAction(action, rowData, $event)\"\n ></span>\n </ng-container>\n </div>\n <ng-container *ngIf=\"col.filterType === 'blob'\">\n <img width=\"45\" [src]=\"getRowData(rowData, col)\" alt=\"\" />\n </ng-container>\n <ng-container *ngIf=\"col.filterType !== 'blob'\">\n {{ getRowData(rowData, col) }}\n </ng-container>\n </td>\n <td *ngIf=\"col.editable\">\n <spiderly-number\n [control]=\"getFormArrayControlByIndex(col.field, rowData.index)\"\n [showLabel]=\"false\"\n ></spiderly-number>\n </td>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td\n [attr.colspan]=\"\n cols?.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"NoRecordsFound\") }}\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td\n [attr.colspan]=\"\n cols?.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"Loading\") }}...\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"paginatorleft\">\n {{ t(\"TotalRecords\") }}: {{ totalRecords }}\n </ng-template>\n <ng-template pTemplate=\"paginatorright\">\n <div style=\"display: flex; justify-content: end; gap: 10px\">\n <spiderly-button\n *ngIf=\"showAddButton\"\n [label]=\"t('AddNew')\"\n icon=\"pi pi-plus\"\n (onClick)=\"navigateToDetails(0)\"\n ></spiderly-button>\n </div>\n </ng-template>\n </p-table>\n </div>\n</ng-container>\n", styles: [".table-header{display:flex;justify-content:space-between;align-items:center}@media (max-width: 640px){.table-header{display:flex;flex-direction:column;align-items:start;gap:14px}}.spiderly-table .p-paginator{padding:1rem}@media (min-width: 1400px){.spiderly-table .p-paginator-left-content{position:absolute;padding:14px;left:0}}@media (min-width: 1400px){.spiderly-table .p-paginator-right-content{position:absolute;padding:14px;right:0}}:host ::ng-deep .clickable{cursor:pointer}:host ::ng-deep td.clickable:hover{text-decoration:underline}:host ::ng-deep .p-datatable-thead{position:unset!important}:host ::ng-deep .p-datatable-header{border-radius:6px 6px 0 0}:host ::ng-deep .p-datatable{border-radius:var(--p-content-border-radius);border:1px solid var(--p-datatable-border-color)}\n"] }]
|
|
4731
|
+
], template: "<ng-container *transloco=\"let t\">\n <div\n [class]=\"\n showCardWrapper ? 'card responsive-card-padding overflow-auto' : ''\n \"\n >\n <p-table\n #dt\n [value]=\"items\"\n [rows]=\"rows\"\n [rowHover]=\"true\"\n [paginator]=\"showPaginator\"\n responsiveLayout=\"scroll\"\n [lazy]=\"hasLazyLoad\"\n (onLazyLoad)=\"lazyLoad($event)\"\n [totalRecords]=\"totalRecords\"\n class=\"spiderly-table\"\n [loading]=\"items === undefined || loading === true\"\n [selectionMode]=\"selectionMode\"\n dataKey=\"id\"\n (onFilter)=\"filter($event)\"\n sortMode=\"multiple\"\n [multiSortMeta]=\"initialMultiSortMeta\"\n [stateKey]=\"resolvedStateKey\"\n [stateStorage]=\"stateStorage\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"table-header overflow-auto\">\n <div style=\"display: flex; align-items: center; gap: 8px\">\n <i class=\"{{ tableIcon }}\" style=\"font-size: 20px\"></i>\n <div style=\"margin: 0px; font-size: 17.5px\">{{ tableTitle }}</div>\n </div>\n <div style=\"display: flex; gap: 8px\">\n <ng-container\n *ngIf=\"actionsTemplate\"\n [ngTemplateOutlet]=\"actionsTemplate\"\n ></ng-container>\n <button\n pButton\n *ngIf=\"hasLazyLoad\"\n data-testid=\"column-chooser-button\"\n [label]=\"t('Columns')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-sliders-h\"\n (click)=\"columnChooser.toggle($event)\"\n ></button>\n <button\n pButton\n [label]=\"t('ClearFilters')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-filter-slash\"\n (click)=\"clear(dt)\"\n ></button>\n <button\n pButton\n *ngIf=\"showExportToExcelButton\"\n [label]=\"t('ExportToExcel')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-download\"\n (click)=\"exportListToExcel()\"\n ></button>\n <button\n pButton\n *ngIf=\"showReloadTableButton\"\n [label]=\"t('Reload')\"\n class=\"p-button-outlined\"\n style=\"flex: none\"\n icon=\"pi pi-refresh\"\n (click)=\"reload()\"\n ></button>\n <button\n pButton\n *ngIf=\"deleteListFromTableObservableMethod && rowsSelectedNumber > 0\"\n [label]=\"t('DeleteSelected') + ' (' + rowsSelectedNumber + ')'\"\n class=\"p-button-danger\"\n style=\"flex: none\"\n icon=\"pi pi-trash\"\n (click)=\"deleteSelectedObjects()\"\n ></button>\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th style=\"width: 0rem\" *ngIf=\"selectionMode == 'multiple'\">\n <div style=\"display: flex; gap: 8px\">\n <p-checkbox\n *ngIf=\"showSelectAllCheckbox\"\n [disabled]=\"readonly\"\n (onChange)=\"selectAll($event.checked)\"\n [(ngModel)]=\"fakeIsAllSelected\"\n [binary]=\"true\"\n ></p-checkbox>\n ({{ rowsSelectedNumber }})\n </div>\n </th>\n <ng-container *ngFor=\"let col of visibleCols; trackBy: colTrackByFn\">\n <th\n [pSortableColumn]=\"col.field\"\n [pSortableColumnDisabled]=\"col.sortable === false || !col.field\"\n [style]=\"getColHeaderWidth(col.filterType)\"\n >\n <div\n style=\"\n display: flex;\n justify-content: space-between;\n align-items: center;\n \"\n >\n <span style=\"display: flex; align-items: center; gap: 4px\">\n {{ col.name }}\n <p-sortIcon\n *ngIf=\"col.sortable !== false && col.field\"\n [field]=\"col.field!\"\n ></p-sortIcon>\n </span>\n <p-columnFilter\n *ngIf=\"col.filterType != null && col.filterType !== 'blob'\"\n [type]=\"col.filterType\"\n [field]=\"col.filterField ?? col.field\"\n display=\"menu\"\n [placeholder]=\"col.filterPlaceholder\"\n [showOperator]=\"false\"\n [showMatchModes]=\"col.showMatchModes\"\n [showAddButton]=\"col.showAddButton\"\n [matchModeOptions]=\"getColMatchModeOptions(col.filterType)\"\n [matchMode]=\"getColMatchMode(col.filterType)\"\n >\n <ng-template\n *ngIf=\"isDropOrMulti(col.filterType)\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-multiSelect\n [ngModel]=\"value\"\n [options]=\"col.dropdownOrMultiselectValues\"\n [placeholder]=\"t('All')\"\n (onChange)=\"filter($event.value)\"\n optionLabel=\"label\"\n optionValue=\"code\"\n [style]=\"{ width: '240px' }\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"p-multiselect-representative-option\">\n <span class=\"ml-2\">{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </ng-template>\n <ng-template\n *ngIf=\"col.filterType == 'date'\"\n pTemplate=\"filter\"\n let-value\n let-filter=\"filterCallback\"\n >\n <p-datepicker\n [ngModel]=\"value\"\n [showTime]=\"col.showTime\"\n (onSelect)=\"filter($event)\"\n ></p-datepicker>\n </ng-template>\n </p-columnFilter>\n </div>\n </th>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template\n pTemplate=\"body\"\n let-rowData\n let-index=\"rowIndex\"\n let-editing=\"editing\"\n >\n <tr\n [class.clickable]=\"navigateOnRowClick\"\n (click)=\"onRowClick(rowData)\"\n >\n <td *ngIf=\"selectionMode == 'multiple'\">\n <p-checkbox\n [disabled]=\"readonly\"\n (onChange)=\"selectRow(rowData[idField], rowData.index)\"\n [ngModel]=\"isRowSelected(rowData[idField])\"\n [binary]=\"true\"\n ></p-checkbox>\n </td>\n <ng-container *ngFor=\"let col of visibleCols; trackBy: colTrackByFn\">\n <td\n [style]=\"getStyleForBodyColumn(col)\"\n [class.clickable]=\"col.onCellClick\"\n (click)=\"onCellClick(col, rowData, $event)\"\n *ngIf=\"!col.editable\"\n >\n <div\n style=\"\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 18px;\n \"\n >\n <ng-container\n *ngFor=\"let action of col.actions; trackBy: actionTrackByFn\"\n >\n <span\n [pTooltip]=\"action.name\"\n [class]=\"getClassForAction(action)\"\n [style]=\"getStyleForAction(action)\"\n (click)=\"getMethodForAction(action, rowData, $event)\"\n ></span>\n </ng-container>\n </div>\n <ng-container *ngIf=\"col.filterType === 'blob'\">\n <img width=\"45\" [src]=\"getRowData(rowData, col)\" alt=\"\" />\n </ng-container>\n <ng-container *ngIf=\"col.filterType !== 'blob'\">\n {{ getRowData(rowData, col) }}\n </ng-container>\n </td>\n <td *ngIf=\"col.editable\">\n <spiderly-number\n [control]=\"getFormArrayControlByIndex(col.field, rowData.index)\"\n [showLabel]=\"false\"\n ></spiderly-number>\n </td>\n </ng-container>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"emptymessage\">\n <tr>\n <td\n [attr.colspan]=\"\n visibleCols.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"NoRecordsFound\") }}\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"loadingbody\">\n <tr>\n <td\n [attr.colspan]=\"\n visibleCols.length + (selectionMode === 'multiple' ? 1 : 0)\n \"\n >\n {{ t(\"Loading\") }}...\n </td>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"paginatorleft\">\n {{ t(\"TotalRecords\") }}: {{ totalRecords }}\n </ng-template>\n <ng-template pTemplate=\"paginatorright\">\n <div style=\"display: flex; justify-content: end; gap: 10px\">\n <spiderly-button\n *ngIf=\"showAddButton\"\n [label]=\"t('AddNew')\"\n icon=\"pi pi-plus\"\n (onClick)=\"navigateToDetails(0)\"\n ></spiderly-button>\n </div>\n </ng-template>\n </p-table>\n <p-popover #columnChooser>\n <div class=\"column-chooser\">\n <label\n *ngFor=\"let col of chooserCols; trackBy: colTrackByFn\"\n data-testid=\"column-chooser-option\"\n class=\"column-chooser-option\"\n >\n <p-checkbox\n [binary]=\"true\"\n [ngModel]=\"isColumnVisible(col)\"\n [disabled]=\"!canToggleColumn(col)\"\n (onChange)=\"toggleColumn(col, $event.checked)\"\n ></p-checkbox>\n <span>{{ col.name }}</span>\n </label>\n <button\n type=\"button\"\n data-testid=\"column-chooser-reset\"\n class=\"column-chooser-reset\"\n (click)=\"resetColumnVisibility()\"\n >\n {{ t('ResetToDefault') }}\n </button>\n </div>\n </p-popover>\n </div>\n</ng-container>\n", styles: [".table-header{display:flex;justify-content:space-between;align-items:center}@media (max-width: 640px){.table-header{display:flex;flex-direction:column;align-items:start;gap:14px}}.spiderly-table .p-paginator{padding:1rem}@media (min-width: 1400px){.spiderly-table .p-paginator-left-content{position:absolute;padding:14px;left:0}}@media (min-width: 1400px){.spiderly-table .p-paginator-right-content{position:absolute;padding:14px;right:0}}:host ::ng-deep .clickable{cursor:pointer}:host ::ng-deep td.clickable:hover{text-decoration:underline}:host .column-chooser{display:flex;flex-direction:column;gap:8px}:host .column-chooser-option{display:flex;align-items:center;gap:8px;cursor:pointer}:host .column-chooser-reset{margin-top:4px;padding:0;border:none;background:none;color:var(--p-primary-color);cursor:pointer;align-self:flex-start;font-size:.875rem}:host .column-chooser-reset:hover{text-decoration:underline}:host ::ng-deep .p-datatable-thead{position:unset!important}:host ::ng-deep .p-datatable-header{border-radius:6px 6px 0 0}:host ::ng-deep .p-datatable{border-radius:var(--p-content-border-radius);border:1px solid var(--p-datatable-border-color)}\n"] }]
|
|
4501
4732
|
}], ctorParameters: () => [{ type: i3$2.Router }, { type: i1$5.DialogService }, { type: i3$2.ActivatedRoute }, { type: SpiderlyMessageService }, { type: i1.TranslocoService }, { type: ConfigServiceBase }, { type: undefined, decorators: [{
|
|
4502
4733
|
type: Inject,
|
|
4503
4734
|
args: [LOCALE_ID]
|
|
@@ -4563,6 +4794,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.13", ngImpo
|
|
|
4563
4794
|
type: Input
|
|
4564
4795
|
}], stateStorage: [{
|
|
4565
4796
|
type: Input
|
|
4797
|
+
}], defaultSortField: [{
|
|
4798
|
+
type: Input
|
|
4799
|
+
}], defaultSortOrder: [{
|
|
4800
|
+
type: Input
|
|
4566
4801
|
}], getAlreadySelectedItemIds: [{
|
|
4567
4802
|
type: Input
|
|
4568
4803
|
}], getAlreadySelectedItems: [{
|
|
@@ -4591,7 +4826,7 @@ class Action {
|
|
|
4591
4826
|
}
|
|
4592
4827
|
}
|
|
4593
4828
|
class Column {
|
|
4594
|
-
constructor({ name, field, filterField, filterType, filterPlaceholder, showMatchModes, showAddButton, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, onCellClick, } = {}) {
|
|
4829
|
+
constructor({ name, field, filterField, filterType, filterPlaceholder, showMatchModes, showAddButton, dropdownOrMultiselectValues, actions, editable, showTime, decimalPlaces, sortable, visible, lockVisible, onCellClick, } = {}) {
|
|
4595
4830
|
this.name = name;
|
|
4596
4831
|
this.field = field;
|
|
4597
4832
|
this.filterField = filterField;
|
|
@@ -4605,6 +4840,8 @@ class Column {
|
|
|
4605
4840
|
this.showTime = showTime;
|
|
4606
4841
|
this.decimalPlaces = decimalPlaces;
|
|
4607
4842
|
this.sortable = sortable;
|
|
4843
|
+
this.visible = visible;
|
|
4844
|
+
this.lockVisible = lockVisible;
|
|
4608
4845
|
this.onCellClick = onCellClick;
|
|
4609
4846
|
}
|
|
4610
4847
|
}
|