@mintplayer/ng-spark 0.3.0 → 22.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +180 -0
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-icon.mjs +9 -6
- package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs +84 -1
- package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pipes.mjs +91 -74
- package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-create.mjs +55 -22
- package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +97 -92
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs +63 -11
- package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-po-form.mjs +71 -36
- package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-query-list.mjs +138 -126
- package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +172 -18
- package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs +99 -50
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/package.json +12 -7
- package/types/mintplayer-ng-spark-client-operations.d.ts +170 -0
- package/types/mintplayer-ng-spark-icon.d.ts +1 -1
- package/types/mintplayer-ng-spark-models.d.ts +54 -10
- package/types/mintplayer-ng-spark-pipes.d.ts +8 -0
- package/types/mintplayer-ng-spark-po-create.d.ts +2 -1
- package/types/mintplayer-ng-spark-po-detail.d.ts +14 -16
- package/types/mintplayer-ng-spark-po-edit.d.ts +4 -2
- package/types/mintplayer-ng-spark-po-form.d.ts +10 -9
- package/types/mintplayer-ng-spark-query-list.d.ts +26 -16
- package/types/mintplayer-ng-spark-retry-action-modal.d.ts +33 -4
- package/types/mintplayer-ng-spark-services.d.ts +32 -6
|
@@ -10,13 +10,12 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router';
|
|
|
10
10
|
import { Color } from '@mintplayer/ng-bootstrap';
|
|
11
11
|
import { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';
|
|
12
12
|
import { DatatableSettings, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective } from '@mintplayer/ng-bootstrap/datatable';
|
|
13
|
-
import { VirtualDatatableDataSource, BsVirtualDatatableComponent, BsVirtualRowTemplateDirective } from '@mintplayer/ng-bootstrap/virtual-datatable';
|
|
14
13
|
import { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';
|
|
15
|
-
import { BsContainerComponent } from '@mintplayer/ng-bootstrap/container';
|
|
16
14
|
import { BsGridComponent, BsGridRowDirective, BsGridColumnDirective } from '@mintplayer/ng-bootstrap/grid';
|
|
17
15
|
import { BsInputGroupComponent } from '@mintplayer/ng-bootstrap/input-group';
|
|
16
|
+
import { BsPriorityNavComponent, BsPriorityNavItemDirective } from '@mintplayer/ng-bootstrap/priority-nav';
|
|
18
17
|
import { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';
|
|
19
|
-
import { SparkService, SparkStreamingService } from '@mintplayer/ng-spark/services';
|
|
18
|
+
import { SparkService, SparkStreamingService, SparkLanguageService } from '@mintplayer/ng-spark/services';
|
|
20
19
|
import { ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe } from '@mintplayer/ng-spark/pipes';
|
|
21
20
|
import { SparkIconComponent } from '@mintplayer/ng-spark/icon';
|
|
22
21
|
import { SPARK_ATTRIBUTE_RENDERERS } from '@mintplayer/ng-spark/renderers';
|
|
@@ -27,39 +26,64 @@ class SparkQueryListComponent {
|
|
|
27
26
|
router = inject(Router);
|
|
28
27
|
sparkService = inject(SparkService);
|
|
29
28
|
streamingService = inject(SparkStreamingService);
|
|
29
|
+
lang = inject(SparkLanguageService);
|
|
30
30
|
rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
|
|
31
31
|
destroyRef = inject(DestroyRef);
|
|
32
|
-
extraActionsTemplate = input(null,
|
|
32
|
+
extraActionsTemplate = input(null, /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "extraActionsTemplate" }] : /* istanbul ignore next */ []));
|
|
34
|
+
showCustomActions = input(true, /* @ts-ignore */
|
|
35
|
+
...(ngDevMode ? [{ debugName: "showCustomActions" }] : /* istanbul ignore next */ []));
|
|
33
36
|
rowClicked = output();
|
|
34
37
|
createClicked = output();
|
|
38
|
+
customActionExecuted = output();
|
|
35
39
|
colors = Color;
|
|
36
|
-
errorMessage = signal(null,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
errorMessage = signal(null, /* @ts-ignore */
|
|
41
|
+
...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
42
|
+
query = signal(null, /* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
44
|
+
entityType = signal(null, /* @ts-ignore */
|
|
45
|
+
...(ngDevMode ? [{ debugName: "entityType" }] : /* istanbul ignore next */ []));
|
|
46
|
+
allEntityTypes = signal([], /* @ts-ignore */
|
|
47
|
+
...(ngDevMode ? [{ debugName: "allEntityTypes" }] : /* istanbul ignore next */ []));
|
|
48
|
+
lookupReferenceOptions = signal({}, /* @ts-ignore */
|
|
49
|
+
...(ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : /* istanbul ignore next */ []));
|
|
50
|
+
resultCount = signal(null, /* @ts-ignore */
|
|
51
|
+
...(ngDevMode ? [{ debugName: "resultCount" }] : /* istanbul ignore next */ []));
|
|
42
52
|
searchTerm = '';
|
|
43
|
-
canRead = signal(false,
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
canRead = signal(false, /* @ts-ignore */
|
|
54
|
+
...(ngDevMode ? [{ debugName: "canRead" }] : /* istanbul ignore next */ []));
|
|
55
|
+
canCreate = signal(false, /* @ts-ignore */
|
|
56
|
+
...(ngDevMode ? [{ debugName: "canCreate" }] : /* istanbul ignore next */ []));
|
|
57
|
+
customActions = signal([], /* @ts-ignore */
|
|
58
|
+
...(ngDevMode ? [{ debugName: "customActions" }] : /* istanbul ignore next */ []));
|
|
59
|
+
isStreaming = signal(false, /* @ts-ignore */
|
|
60
|
+
...(ngDevMode ? [{ debugName: "isStreaming" }] : /* istanbul ignore next */ []));
|
|
46
61
|
streamingSub = null;
|
|
47
|
-
allItems = signal([],
|
|
48
|
-
|
|
62
|
+
allItems = signal([], /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "allItems" }] : /* istanbul ignore next */ []));
|
|
64
|
+
streamItems = signal([], /* @ts-ignore */
|
|
65
|
+
...(ngDevMode ? [{ debugName: "streamItems" }] : /* istanbul ignore next */ []));
|
|
66
|
+
fetchFn = signal(null, /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "fetchFn" }] : /* istanbul ignore next */ []));
|
|
49
68
|
settings = signal(new DatatableSettings({
|
|
50
69
|
perPage: { values: [10, 25, 50], selected: 10 },
|
|
51
70
|
page: { values: [1], selected: 1 },
|
|
52
71
|
sortColumns: []
|
|
53
|
-
}),
|
|
54
|
-
|
|
55
|
-
virtualSettings = signal(new DatatableSettings({
|
|
56
|
-
sortColumns: []
|
|
57
|
-
}), ...(ngDevMode ? [{ debugName: "virtualSettings" }] : []));
|
|
72
|
+
}), /* @ts-ignore */
|
|
73
|
+
...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
|
|
58
74
|
constructor() {
|
|
59
75
|
this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));
|
|
60
76
|
this.destroyRef.onDestroy(() => this.disconnectStreaming());
|
|
61
77
|
}
|
|
62
78
|
async onParamsChange(params) {
|
|
79
|
+
// Reset prior-route state so we render the spinner (not stale rows from
|
|
80
|
+
// the previous query) while the new query/entityType resolve.
|
|
81
|
+
this.entityType.set(null);
|
|
82
|
+
this.fetchFn.set(null);
|
|
83
|
+
this.resultCount.set(null);
|
|
84
|
+
this.allItems.set([]);
|
|
85
|
+
this.streamItems.set([]);
|
|
86
|
+
this.disconnectStreaming();
|
|
63
87
|
const queryId = params.get('queryId');
|
|
64
88
|
const typeParam = params.get('type');
|
|
65
89
|
let resolvedQuery = null;
|
|
@@ -101,32 +125,47 @@ class SparkQueryListComponent {
|
|
|
101
125
|
property: sc.property,
|
|
102
126
|
direction: sc.direction === 'desc' ? 'descending' : 'ascending'
|
|
103
127
|
}));
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
this.connectStreaming(resolvedQuery.id);
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
this.initVirtualDataSource();
|
|
116
|
-
}
|
|
128
|
+
this.settings.set(new DatatableSettings({
|
|
129
|
+
perPage: { values: [10, 25, 50], selected: 10 },
|
|
130
|
+
page: { values: [1], selected: 1 },
|
|
131
|
+
sortColumns: initialSortColumns
|
|
132
|
+
}));
|
|
133
|
+
if (resolvedQuery?.isStreamingQuery) {
|
|
134
|
+
// Streaming: WebSocket feeds allItems; the datatable binds [data]="streamItems()".
|
|
135
|
+
this.connectStreaming(resolvedQuery.id);
|
|
117
136
|
}
|
|
118
|
-
else {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}));
|
|
124
|
-
await this.loadItems();
|
|
137
|
+
else if (resolvedQuery) {
|
|
138
|
+
// Non-streaming: the datatable drives paging/sorting via [(settings)] and calls
|
|
139
|
+
// fetchFn per page. Virtual scrolling is just the [virtualScroll] template flag —
|
|
140
|
+
// the datatable front-loads all pages from fetchFn when virtual.
|
|
141
|
+
this.fetchFn.set(this.makeFetch(resolvedQuery));
|
|
125
142
|
}
|
|
126
143
|
this.loadLookupReferenceOptions();
|
|
127
|
-
const permissions = await
|
|
144
|
+
const [permissions, actions] = await Promise.all([
|
|
145
|
+
this.sparkService.getPermissions(resolvedEntityType.id),
|
|
146
|
+
this.sparkService.getCustomActions(resolvedEntityType.id),
|
|
147
|
+
]);
|
|
128
148
|
this.canRead.set(permissions.canRead);
|
|
129
149
|
this.canCreate.set(permissions.canCreate);
|
|
150
|
+
this.customActions.set(actions.filter(a => a.showedOn === 'list' || a.showedOn === 'both'));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async onCustomAction(action) {
|
|
154
|
+
if (action.confirmationMessageKey) {
|
|
155
|
+
const message = this.lang.t(action.confirmationMessageKey) || 'Are you sure?';
|
|
156
|
+
if (!confirm(message))
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
try {
|
|
160
|
+
await this.sparkService.executeCustomAction(this.entityType().id, action.name);
|
|
161
|
+
this.customActionExecuted.emit({ action });
|
|
162
|
+
if (action.refreshOnCompleted) {
|
|
163
|
+
this.refresh();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch (e) {
|
|
167
|
+
const err = e;
|
|
168
|
+
this.errorMessage.set(err.error?.error || err.message || 'Action failed');
|
|
130
169
|
}
|
|
131
170
|
}
|
|
132
171
|
async resolveEntityTypeForQuery(query) {
|
|
@@ -168,89 +207,76 @@ class SparkQueryListComponent {
|
|
|
168
207
|
}
|
|
169
208
|
return plural;
|
|
170
209
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
210
|
+
/**
|
|
211
|
+
* Builds the server-side fetch callback the datatable invokes per page/sort.
|
|
212
|
+
* Reads `searchTerm` live, so a settings change (or a new fetchFn identity)
|
|
213
|
+
* refetches with the current search term.
|
|
214
|
+
*/
|
|
215
|
+
makeFetch(query) {
|
|
216
|
+
return (req) => this.sparkService.executeQuery(query.id, {
|
|
217
|
+
sortColumns: req.sortColumns,
|
|
218
|
+
skip: (req.page - 1) * req.perPage,
|
|
219
|
+
take: req.perPage,
|
|
178
220
|
search: this.searchTerm || undefined,
|
|
179
|
-
}).then(r =>
|
|
180
|
-
}
|
|
181
|
-
async loadItems() {
|
|
182
|
-
const currentQuery = this.query();
|
|
183
|
-
if (!currentQuery)
|
|
184
|
-
return;
|
|
185
|
-
// Streaming queries use WebSocket instead of HTTP
|
|
186
|
-
if (currentQuery.isStreamingQuery) {
|
|
187
|
-
this.connectStreaming(currentQuery.id);
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
// Non-streaming: disconnect any previous streaming connection
|
|
191
|
-
this.disconnectStreaming();
|
|
192
|
-
try {
|
|
193
|
-
const s = this.settings();
|
|
194
|
-
const result = await this.sparkService.executeQuery(currentQuery.id, {
|
|
195
|
-
sortColumns: s.sortColumns,
|
|
196
|
-
skip: (s.page.selected - 1) * s.perPage.selected,
|
|
197
|
-
take: s.perPage.selected,
|
|
198
|
-
search: this.searchTerm || undefined,
|
|
199
|
-
});
|
|
221
|
+
}).then(r => {
|
|
200
222
|
this.errorMessage.set(null);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
data:
|
|
204
|
-
totalRecords:
|
|
205
|
-
totalPages:
|
|
206
|
-
perPage:
|
|
207
|
-
page:
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
catch (e) {
|
|
223
|
+
this.resultCount.set(r.totalRecords);
|
|
224
|
+
return {
|
|
225
|
+
data: r.data,
|
|
226
|
+
totalRecords: r.totalRecords,
|
|
227
|
+
totalPages: Math.ceil(r.totalRecords / req.perPage) || 1,
|
|
228
|
+
perPage: req.perPage,
|
|
229
|
+
page: req.page,
|
|
230
|
+
};
|
|
231
|
+
}).catch((e) => {
|
|
212
232
|
this.errorMessage.set(e.error?.error || e.message || 'An unexpected error occurred');
|
|
213
|
-
this.
|
|
214
|
-
|
|
233
|
+
this.resultCount.set(0);
|
|
234
|
+
return { data: [], totalRecords: 0, totalPages: 1, perPage: req.perPage, page: req.page };
|
|
235
|
+
});
|
|
215
236
|
}
|
|
216
|
-
|
|
237
|
+
/** Force a refetch (e.g. after a custom action) without changing page/sort. */
|
|
238
|
+
refresh() {
|
|
217
239
|
if (this.isStreaming()) {
|
|
218
|
-
// Streaming: sort/filter is client-side only
|
|
219
240
|
this.applyFilter();
|
|
220
241
|
return;
|
|
221
242
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
this.
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
this.loadItems();
|
|
228
|
-
}
|
|
243
|
+
const q = this.query();
|
|
244
|
+
if (q)
|
|
245
|
+
this.fetchFn.set(this.makeFetch(q));
|
|
229
246
|
}
|
|
230
247
|
onSearchChange() {
|
|
231
248
|
if (this.isStreaming()) {
|
|
232
249
|
this.applyFilter();
|
|
233
250
|
return;
|
|
234
251
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
252
|
+
// Reset to page 1 for the new search.
|
|
253
|
+
const s = this.settings();
|
|
254
|
+
this.settings.set(new DatatableSettings({
|
|
255
|
+
perPage: { values: s.perPage.values, selected: s.perPage.selected },
|
|
256
|
+
page: { values: [1], selected: 1 },
|
|
257
|
+
sortColumns: s.sortColumns,
|
|
258
|
+
}));
|
|
259
|
+
// Re-assign the fetch callback so the datatable refetches even when
|
|
260
|
+
// page/perPage/sort are unchanged. ng-bootstrap 22.4's web component dedupes
|
|
261
|
+
// reloads by {sortColumns, perPage, page}; setting a new fetch identity resets
|
|
262
|
+
// that key (set fetch → _lastReloadKey = null) and forces the reload. makeFetch
|
|
263
|
+
// reads searchTerm live (mirrors refresh()).
|
|
264
|
+
const q = this.query();
|
|
265
|
+
if (q)
|
|
266
|
+
this.fetchFn.set(this.makeFetch(q));
|
|
243
267
|
}
|
|
244
268
|
clearSearch() {
|
|
245
269
|
this.searchTerm = '';
|
|
246
270
|
this.onSearchChange();
|
|
247
271
|
}
|
|
248
|
-
isVirtualScrolling = computed(() => this.query()?.renderMode === 'VirtualScrolling',
|
|
272
|
+
isVirtualScrolling = computed(() => this.query()?.renderMode === 'VirtualScrolling', /* @ts-ignore */
|
|
273
|
+
...(ngDevMode ? [{ debugName: "isVirtualScrolling" }] : /* istanbul ignore next */ []));
|
|
249
274
|
visibleAttributes = computed(() => {
|
|
250
275
|
return this.entityType()?.attributes
|
|
251
276
|
.filter(a => a.isVisible && hasShowedOnFlag(a.showedOn, ShowedOn.Query))
|
|
252
277
|
.sort((a, b) => a.order - b.order) || [];
|
|
253
|
-
},
|
|
278
|
+
}, /* @ts-ignore */
|
|
279
|
+
...(ngDevMode ? [{ debugName: "visibleAttributes" }] : /* istanbul ignore next */ []));
|
|
254
280
|
getColumnRendererComponent(attr) {
|
|
255
281
|
if (!attr.renderer)
|
|
256
282
|
return null;
|
|
@@ -342,9 +368,9 @@ class SparkQueryListComponent {
|
|
|
342
368
|
const term = this.searchTerm.toLowerCase();
|
|
343
369
|
items = items.filter(item => item.attributes.some(a => String(a.value ?? '').toLowerCase().includes(term)));
|
|
344
370
|
}
|
|
345
|
-
// Apply sorting
|
|
346
|
-
|
|
347
|
-
const sortCols =
|
|
371
|
+
// Apply sorting (client-side for the streaming snapshot; the datatable in
|
|
372
|
+
// [data] mode also auto-sorts on header clicks).
|
|
373
|
+
const sortCols = this.settings().sortColumns;
|
|
348
374
|
if (sortCols.length > 0) {
|
|
349
375
|
items = [...items].sort((a, b) => {
|
|
350
376
|
for (const col of sortCols) {
|
|
@@ -357,32 +383,18 @@ class SparkQueryListComponent {
|
|
|
357
383
|
return 0;
|
|
358
384
|
});
|
|
359
385
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
// The stable data source's fetchFn closure reads from this.filteredItems,
|
|
363
|
-
// so clearing its cache and emitting empty triggers the CDK viewport to re-fetch.
|
|
364
|
-
this.filteredItems = items;
|
|
365
|
-
this.virtualDataSource()?.reset();
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
this.paginationData.set({
|
|
369
|
-
data: items,
|
|
370
|
-
totalRecords: items.length,
|
|
371
|
-
totalPages: 1,
|
|
372
|
-
perPage: items.length,
|
|
373
|
-
page: 1
|
|
374
|
-
});
|
|
375
|
-
}
|
|
386
|
+
this.streamItems.set(items);
|
|
387
|
+
this.resultCount.set(items.length);
|
|
376
388
|
}
|
|
377
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
378
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkQueryListComponent, isStandalone: true, selector: "spark-query-list", inputs: { extraActionsTemplate: { classPropertyName: "extraActionsTemplate", publicName: "extraActionsTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClicked: "rowClicked", createClicked: "createClicked" }, host: { properties: { "class.virtual-scrolling": "isVirtualScrolling()" } }, ngImport: i0, template: "<div class=\"d-flex flex-column h-100\">\n <!-- Title + Actions row -->\n <div class=\"d-flex justify-content-between align-items-center mb-4 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <h2>\n {{ (query()?.description | resolveTranslation) || query()?.name || ('common.loading' | t) }}\n @if (isStreaming()) {\n <span class=\"badge bg-success ms-2\" style=\"font-size: 0.5em; vertical-align: middle;\">LIVE</span>\n }\n </h2>\n <div class=\"d-flex gap-2\">\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (canCreate()) {\n <button class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'common.new' | t }}\n </button>\n }\n </div>\n </div>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && paginationData()) {\n <span class=\"text-muted\">\n {{ paginationData()!.totalRecords }} {{ paginationData()!.totalRecords === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (query()?.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <bs-virtual-datatable class=\"flex-grow-1 overflow-hidden\"\n [(settings)]=\"virtualSettings\"\n [dataSource]=\"vds\"\n [isResponsive]=\"true\"\n (settingsChange)=\"onSettingsChange()\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-template bsVirtualRowTemplate let-item>\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (item) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, item.id]\" (click)=\"rowClicked.emit(item)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-template>\n </bs-virtual-datatable>\n }\n } @else {\n <bs-datatable class=\"flex-grow-1\" [(settings)]=\"settings\" (settingsChange)=\"onSettingsChange()\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <tr *bsRowTemplate=\"let item of paginationData()\">\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, item.id]\" (click)=\"rowClicked.emit(item)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n }\n </td>\n }\n </tr>\n </bs-datatable>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n\n<ng-template #cellContent let-item let-attr=\"attr\">\n @if (getColumnRendererComponent(attr); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: getColumnRendererInputs(item, attr)\"></ng-container>\n } @else if (attr.dataType === 'boolean') {\n <input type=\"checkbox\"\n [checked]=\"(attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) === true\"\n [indeterminate]=\"(attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) == null\"\n disabled\n onclick=\"return false;\">\n } @else if (attr.dataType === 'color') {\n @let colorVal = (attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes());\n @if (colorVal) {\n <span class=\"d-inline-block align-middle border rounded\" [style.background-color]=\"colorVal\" style=\"width: 1.5em; height: 1.5em;\"></span>\n }\n } @else {\n {{ (attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0}:host.virtual-scrolling{margin:0 -1.5rem -1.5rem}tr:hover{background-color:#0000000d}td input[type=checkbox]:disabled{opacity:1;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsDatatableComponent, selector: "bs-datatable", inputs: ["data"], outputs: ["dataChange"] }, { kind: "directive", type: BsDatatableColumnDirective, selector: "[bsDatatableColumn]", inputs: ["bsDatatableColumn", "bsDatatableColumnSortable"] }, { kind: "directive", type: BsRowTemplateDirective, selector: "[bsRowTemplate]", inputs: ["bsRowTemplateOf"] }, { kind: "component", type: BsVirtualDatatableComponent, selector: "bs-virtual-datatable", inputs: ["dataSource", "isResponsive", "itemSize"] }, { kind: "directive", type: BsVirtualRowTemplateDirective, selector: "[bsVirtualRowTemplate]" }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsGridComponent, selector: "bs-grid", inputs: ["stopFullWidthAt"] }, { kind: "directive", type: BsGridRowDirective, selector: "[bsRow]" }, { kind: "directive", type: BsGridColumnDirective, selector: "[xxs],[xs],[sm],[md],[lg],[xl],[xxl]", inputs: ["xxs", "xs", "sm", "md", "lg", "xl", "xxl"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
389
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SparkQueryListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
390
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: SparkQueryListComponent, isStandalone: true, selector: "spark-query-list", inputs: { extraActionsTemplate: { classPropertyName: "extraActionsTemplate", publicName: "extraActionsTemplate", isSignal: true, isRequired: false, transformFunction: null }, showCustomActions: { classPropertyName: "showCustomActions", publicName: "showCustomActions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClicked: "rowClicked", createClicked: "createClicked", customActionExecuted: "customActionExecuted" }, host: { properties: { "class.virtual-scrolling": "isVirtualScrolling()" } }, ngImport: i0, template: "<div class=\"d-flex flex-column h-100\">\n <div class=\"spark-actionbar py-2 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\" [class.px-3]=\"!isVirtualScrolling()\">\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n @if (canCreate()) {\n <button *bsPriorityNavItem=\"1\" class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'common.new' | t }}\n </button>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *bsPriorityNavItem=\"50\">\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n </ng-container>\n }\n </bs-priority-nav>\n </div>\n <h2 class=\"mb-4 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n {{ (query()?.description | resolveTranslation) || query()?.name || ('common.loading' | t) }}\n @if (isStreaming()) {\n <span class=\"badge bg-success ms-2\" style=\"font-size: 0.5em; vertical-align: middle;\">LIVE</span>\n }\n </h2>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && resultCount() !== null) {\n <span class=\"text-muted\">\n {{ resultCount() }} {{ resultCount() === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (isStreaming()) {\n <bs-datatable class=\"flex-grow-1\"\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [data]=\"streamItems()\"\n [(settings)]=\"settings\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (row) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, row.id]\" (click)=\"rowClicked.emit(row)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-container>\n </bs-datatable>\n } @else {\n <bs-datatable class=\"flex-grow-1\"\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [fetch]=\"fetchFn()\"\n [(settings)]=\"settings\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (row) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, row.id]\" (click)=\"rowClicked.emit(row)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-container>\n </bs-datatable>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n\n<ng-template #cellContent let-item let-attr=\"attr\">\n @if (getColumnRendererComponent(attr); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: getColumnRendererInputs(item, attr)\"></ng-container>\n } @else if (attr.dataType === 'boolean') {\n <input type=\"checkbox\"\n [checked]=\"(attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) === true\"\n [indeterminate]=\"(attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) == null\"\n disabled\n onclick=\"return false;\">\n } @else if (attr.dataType === 'color') {\n @let colorVal = (attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes());\n @if (colorVal) {\n <span class=\"d-inline-block align-middle border rounded\" [style.background-color]=\"colorVal\" style=\"width: 1.5em; height: 1.5em;\"></span>\n }\n } @else {\n {{ (attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) }}\n }\n</ng-template>\n", styles: [".spark-actionbar{position:sticky;top:0;z-index:400;background-color:var(--bs-tertiary-bg);border-bottom:1px solid var(--bs-border-color);margin-bottom:1rem}.spark-actionbar .btn{border-radius:0}:host{display:flex;flex-direction:column;flex:1;min-height:0}:host.virtual-scrolling{margin:0 -1.5rem -1.5rem}:host.virtual-scrolling ::ng-deep bs-datatable{display:flex;flex-direction:column;min-height:0;--mp-datatable-virtual-max-height: 100%}:host.virtual-scrolling ::ng-deep bs-datatable mp-datatable{flex:1 1 auto;min-height:0}tr:hover{background-color:#0000000d}td input[type=checkbox]:disabled{opacity:1;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsDatatableComponent, selector: "bs-datatable", inputs: ["columns", "data", "fetch", "settings", "selectionMode", "selectable", "selection", "rowKey", "resizableColumns", "pagination", "virtualScroll", "itemSize", "virtualBuffer", "isResponsive", "compareWith", "tree", "idKey", "childCountKey", "treeIndent", "expandedIds", "selectionStrategy"], outputs: ["settingsChange", "selectionChange", "rowClick", "rowDblClick", "rowContextMenu", "expandedIdsChange", "rowExpand", "rowCollapse"] }, { kind: "directive", type: BsDatatableColumnDirective, selector: "[bsDatatableColumn]", inputs: ["bsDatatableColumn", "bsDatatableColumnSortable"] }, { kind: "directive", type: BsRowTemplateDirective, selector: "[bsRowTemplate]" }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsGridComponent, selector: "bs-grid", inputs: ["stopFullWidthAt"] }, { kind: "directive", type: BsGridRowDirective, selector: "[bsRow]" }, { kind: "directive", type: BsGridColumnDirective, selector: "[xxs],[xs],[sm],[md],[lg],[xl],[xxl]", inputs: ["xxs", "xs", "sm", "md", "lg", "xl", "xxl"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group" }, { kind: "component", type: BsPriorityNavComponent, selector: "bs-priority-nav", inputs: ["moreLabel", "moreLabelTemplate", "collapseAt", "overflowFrom", "hideEmptyMore", "ariaLabel"], outputs: ["overflowChange"] }, { kind: "directive", type: BsPriorityNavItemDirective, selector: "[bsPriorityNavItem]", inputs: ["bsPriorityNavItem", "bsPriorityNavItemHideBelow"] }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
379
391
|
}
|
|
380
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
392
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SparkQueryListComponent, decorators: [{
|
|
381
393
|
type: Component,
|
|
382
|
-
args: [{ selector: 'spark-query-list', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, FormsModule, RouterModule, BsAlertComponent,
|
|
394
|
+
args: [{ selector: 'spark-query-list', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, FormsModule, RouterModule, BsAlertComponent, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsFormComponent, BsFormControlDirective, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsInputGroupComponent, BsPriorityNavComponent, BsPriorityNavItemDirective, BsSpinnerComponent, SparkIconComponent, ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
383
395
|
'[class.virtual-scrolling]': 'isVirtualScrolling()'
|
|
384
|
-
}, template: "<div class=\"d-flex flex-column h-100\">\n
|
|
385
|
-
}], ctorParameters: () => [], propDecorators: { extraActionsTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraActionsTemplate", required: false }] }], rowClicked: [{ type: i0.Output, args: ["rowClicked"] }], createClicked: [{ type: i0.Output, args: ["createClicked"] }] } });
|
|
396
|
+
}, template: "<div class=\"d-flex flex-column h-100\">\n <div class=\"spark-actionbar py-2 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\" [class.px-3]=\"!isVirtualScrolling()\">\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n @if (canCreate()) {\n <button *bsPriorityNavItem=\"1\" class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'common.new' | t }}\n </button>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *bsPriorityNavItem=\"50\">\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n </ng-container>\n }\n </bs-priority-nav>\n </div>\n <h2 class=\"mb-4 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n {{ (query()?.description | resolveTranslation) || query()?.name || ('common.loading' | t) }}\n @if (isStreaming()) {\n <span class=\"badge bg-success ms-2\" style=\"font-size: 0.5em; vertical-align: middle;\">LIVE</span>\n }\n </h2>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && resultCount() !== null) {\n <span class=\"text-muted\">\n {{ resultCount() }} {{ resultCount() === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (isStreaming()) {\n <bs-datatable class=\"flex-grow-1\"\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [data]=\"streamItems()\"\n [(settings)]=\"settings\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (row) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, row.id]\" (click)=\"rowClicked.emit(row)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-container>\n </bs-datatable>\n } @else {\n <bs-datatable class=\"flex-grow-1\"\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [fetch]=\"fetchFn()\"\n [(settings)]=\"settings\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (row) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, row.id]\" (click)=\"rowClicked.emit(row)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n }\n } @else {\n \n }\n </td>\n }\n </ng-container>\n </bs-datatable>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n\n<ng-template #cellContent let-item let-attr=\"attr\">\n @if (getColumnRendererComponent(attr); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: getColumnRendererInputs(item, attr)\"></ng-container>\n } @else if (attr.dataType === 'boolean') {\n <input type=\"checkbox\"\n [checked]=\"(attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) === true\"\n [indeterminate]=\"(attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) == null\"\n disabled\n onclick=\"return false;\">\n } @else if (attr.dataType === 'color') {\n @let colorVal = (attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes());\n @if (colorVal) {\n <span class=\"d-inline-block align-middle border rounded\" [style.background-color]=\"colorVal\" style=\"width: 1.5em; height: 1.5em;\"></span>\n }\n } @else {\n {{ (attr.name | attributeValue:item:entityType():lookupReferenceOptions():allEntityTypes()) }}\n }\n</ng-template>\n", styles: [".spark-actionbar{position:sticky;top:0;z-index:400;background-color:var(--bs-tertiary-bg);border-bottom:1px solid var(--bs-border-color);margin-bottom:1rem}.spark-actionbar .btn{border-radius:0}:host{display:flex;flex-direction:column;flex:1;min-height:0}:host.virtual-scrolling{margin:0 -1.5rem -1.5rem}:host.virtual-scrolling ::ng-deep bs-datatable{display:flex;flex-direction:column;min-height:0;--mp-datatable-virtual-max-height: 100%}:host.virtual-scrolling ::ng-deep bs-datatable mp-datatable{flex:1 1 auto;min-height:0}tr:hover{background-color:#0000000d}td input[type=checkbox]:disabled{opacity:1;pointer-events:none}\n"] }]
|
|
397
|
+
}], ctorParameters: () => [], propDecorators: { extraActionsTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraActionsTemplate", required: false }] }], showCustomActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCustomActions", required: false }] }], rowClicked: [{ type: i0.Output, args: ["rowClicked"] }], createClicked: [{ type: i0.Output, args: ["createClicked"] }], customActionExecuted: [{ type: i0.Output, args: ["customActionExecuted"] }] } });
|
|
386
398
|
|
|
387
399
|
/**
|
|
388
400
|
* Generated bundle index. Do not edit.
|