@mintplayer/ng-spark 0.0.9 → 0.1.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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, InjectionToken, Injectable, inject, Pipe, input, computed, ChangeDetectionStrategy, Component, model, output, effect } from '@angular/core';
|
|
2
|
+
import { signal, InjectionToken, Injectable, inject, NgZone, Pipe, input, computed, ChangeDetectionStrategy, Component, model, output, effect, DestroyRef } from '@angular/core';
|
|
3
3
|
import { HttpClient, HttpParams } from '@angular/common/http';
|
|
4
|
-
import { firstValueFrom } from 'rxjs';
|
|
4
|
+
import { firstValueFrom, Observable } from 'rxjs';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
6
6
|
import { CommonModule, NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
|
|
7
7
|
import * as i2 from '@angular/forms';
|
|
@@ -238,6 +238,92 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
238
238
|
args: [{ providedIn: 'root' }]
|
|
239
239
|
}] });
|
|
240
240
|
|
|
241
|
+
class SparkStreamingService {
|
|
242
|
+
config = inject(SPARK_CONFIG, { optional: true });
|
|
243
|
+
baseUrl = this.config?.baseUrl ?? '/spark';
|
|
244
|
+
ngZone = inject(NgZone);
|
|
245
|
+
connectToStreamingQuery(queryId) {
|
|
246
|
+
return new Observable(subscriber => {
|
|
247
|
+
let ws = null;
|
|
248
|
+
let retryCount = 0;
|
|
249
|
+
let retryTimeout = null;
|
|
250
|
+
let closed = false;
|
|
251
|
+
const maxRetries = 10;
|
|
252
|
+
const maxDelay = 30000;
|
|
253
|
+
const connect = () => {
|
|
254
|
+
if (closed)
|
|
255
|
+
return;
|
|
256
|
+
const url = this.buildWebSocketUrl(queryId);
|
|
257
|
+
ws = new WebSocket(url);
|
|
258
|
+
ws.onopen = () => {
|
|
259
|
+
retryCount = 0; // Reset on successful connect
|
|
260
|
+
};
|
|
261
|
+
ws.onmessage = (event) => {
|
|
262
|
+
try {
|
|
263
|
+
const message = JSON.parse(event.data);
|
|
264
|
+
this.ngZone.run(() => subscriber.next(message));
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
// Ignore malformed messages
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
ws.onerror = () => {
|
|
271
|
+
// Error will trigger onclose
|
|
272
|
+
};
|
|
273
|
+
ws.onclose = (event) => {
|
|
274
|
+
if (closed)
|
|
275
|
+
return;
|
|
276
|
+
// Don't reconnect on normal closure
|
|
277
|
+
if (event.code === 1000) {
|
|
278
|
+
this.ngZone.run(() => subscriber.complete());
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
// Reconnect with exponential backoff
|
|
282
|
+
if (retryCount < maxRetries) {
|
|
283
|
+
const delay = Math.min(1000 * Math.pow(2, retryCount), maxDelay);
|
|
284
|
+
retryCount++;
|
|
285
|
+
retryTimeout = setTimeout(() => connect(), delay);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
this.ngZone.run(() => subscriber.error(new Error('WebSocket connection failed after maximum retries')));
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
connect();
|
|
293
|
+
// Teardown: close WebSocket on unsubscribe
|
|
294
|
+
return () => {
|
|
295
|
+
closed = true;
|
|
296
|
+
if (retryTimeout) {
|
|
297
|
+
clearTimeout(retryTimeout);
|
|
298
|
+
}
|
|
299
|
+
if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) {
|
|
300
|
+
ws.close(1000, 'Client unsubscribed');
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
buildWebSocketUrl(queryId) {
|
|
306
|
+
const encodedId = encodeURIComponent(queryId);
|
|
307
|
+
const path = `${this.baseUrl}/queries/${encodedId}/stream`;
|
|
308
|
+
// If baseUrl is absolute (starts with http/https), replace protocol
|
|
309
|
+
if (this.baseUrl.startsWith('http://')) {
|
|
310
|
+
return path.replace(/^http:\/\//, 'ws://');
|
|
311
|
+
}
|
|
312
|
+
if (this.baseUrl.startsWith('https://')) {
|
|
313
|
+
return path.replace(/^https:\/\//, 'wss://');
|
|
314
|
+
}
|
|
315
|
+
// Relative URL — construct from window.location
|
|
316
|
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
317
|
+
return `${protocol}//${window.location.host}${path}`;
|
|
318
|
+
}
|
|
319
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkStreamingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
320
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkStreamingService, providedIn: 'root' });
|
|
321
|
+
}
|
|
322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkStreamingService, decorators: [{
|
|
323
|
+
type: Injectable,
|
|
324
|
+
args: [{ providedIn: 'root' }]
|
|
325
|
+
}] });
|
|
326
|
+
|
|
241
327
|
class SparkLanguageService {
|
|
242
328
|
http = inject(HttpClient);
|
|
243
329
|
config = inject(SPARK_CONFIG, { optional: true });
|
|
@@ -1673,7 +1759,9 @@ class SparkQueryListComponent {
|
|
|
1673
1759
|
route = inject(ActivatedRoute);
|
|
1674
1760
|
router = inject(Router);
|
|
1675
1761
|
sparkService = inject(SparkService);
|
|
1762
|
+
streamingService = inject(SparkStreamingService);
|
|
1676
1763
|
rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
|
|
1764
|
+
destroyRef = inject(DestroyRef);
|
|
1677
1765
|
extraActionsTemplate = input(null, ...(ngDevMode ? [{ debugName: "extraActionsTemplate" }] : []));
|
|
1678
1766
|
rowClicked = output();
|
|
1679
1767
|
createClicked = output();
|
|
@@ -1687,6 +1775,10 @@ class SparkQueryListComponent {
|
|
|
1687
1775
|
searchTerm = '';
|
|
1688
1776
|
canRead = signal(false, ...(ngDevMode ? [{ debugName: "canRead" }] : []));
|
|
1689
1777
|
canCreate = signal(false, ...(ngDevMode ? [{ debugName: "canCreate" }] : []));
|
|
1778
|
+
isStreaming = signal(false, ...(ngDevMode ? [{ debugName: "isStreaming" }] : []));
|
|
1779
|
+
streamingSub = null;
|
|
1780
|
+
allItems = signal([], ...(ngDevMode ? [{ debugName: "allItems" }] : []));
|
|
1781
|
+
filteredItems = [];
|
|
1690
1782
|
settings = signal(new DatatableSettings({
|
|
1691
1783
|
perPage: { values: [10, 25, 50], selected: 10 },
|
|
1692
1784
|
page: { values: [1], selected: 1 },
|
|
@@ -1698,6 +1790,7 @@ class SparkQueryListComponent {
|
|
|
1698
1790
|
}), ...(ngDevMode ? [{ debugName: "virtualSettings" }] : []));
|
|
1699
1791
|
constructor() {
|
|
1700
1792
|
this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));
|
|
1793
|
+
this.destroyRef.onDestroy(() => this.disconnectStreaming());
|
|
1701
1794
|
}
|
|
1702
1795
|
async onParamsChange(params) {
|
|
1703
1796
|
const queryId = params.get('queryId');
|
|
@@ -1743,7 +1836,17 @@ class SparkQueryListComponent {
|
|
|
1743
1836
|
}));
|
|
1744
1837
|
if (resolvedQuery?.renderMode === 'VirtualScrolling') {
|
|
1745
1838
|
this.virtualSettings.set(new DatatableSettings({ sortColumns: initialSortColumns }));
|
|
1746
|
-
|
|
1839
|
+
if (resolvedQuery?.isStreamingQuery) {
|
|
1840
|
+
// Streaming + VirtualScrolling: create a stable client-side data source, then connect WebSocket
|
|
1841
|
+
this.virtualDataSource.set(new VirtualDatatableDataSource((skip, take) => Promise.resolve({
|
|
1842
|
+
data: this.filteredItems.slice(skip, skip + take),
|
|
1843
|
+
totalRecords: this.filteredItems.length
|
|
1844
|
+
}), 50));
|
|
1845
|
+
this.connectStreaming(resolvedQuery.id);
|
|
1846
|
+
}
|
|
1847
|
+
else {
|
|
1848
|
+
this.initVirtualDataSource();
|
|
1849
|
+
}
|
|
1747
1850
|
}
|
|
1748
1851
|
else {
|
|
1749
1852
|
this.settings.set(new DatatableSettings({
|
|
@@ -1751,14 +1854,12 @@ class SparkQueryListComponent {
|
|
|
1751
1854
|
page: { values: [1], selected: 1 },
|
|
1752
1855
|
sortColumns: initialSortColumns
|
|
1753
1856
|
}));
|
|
1857
|
+
await this.loadItems();
|
|
1754
1858
|
}
|
|
1755
1859
|
this.loadLookupReferenceOptions();
|
|
1756
1860
|
const permissions = await this.sparkService.getPermissions(resolvedEntityType.id);
|
|
1757
1861
|
this.canRead.set(permissions.canRead);
|
|
1758
1862
|
this.canCreate.set(permissions.canCreate);
|
|
1759
|
-
if (resolvedQuery?.renderMode !== 'VirtualScrolling') {
|
|
1760
|
-
await this.loadItems();
|
|
1761
|
-
}
|
|
1762
1863
|
}
|
|
1763
1864
|
}
|
|
1764
1865
|
async resolveEntityTypeForQuery(query) {
|
|
@@ -1814,6 +1915,13 @@ class SparkQueryListComponent {
|
|
|
1814
1915
|
const currentQuery = this.query();
|
|
1815
1916
|
if (!currentQuery)
|
|
1816
1917
|
return;
|
|
1918
|
+
// Streaming queries use WebSocket instead of HTTP
|
|
1919
|
+
if (currentQuery.isStreamingQuery) {
|
|
1920
|
+
this.connectStreaming(currentQuery.id);
|
|
1921
|
+
return;
|
|
1922
|
+
}
|
|
1923
|
+
// Non-streaming: disconnect any previous streaming connection
|
|
1924
|
+
this.disconnectStreaming();
|
|
1817
1925
|
try {
|
|
1818
1926
|
const s = this.settings();
|
|
1819
1927
|
const result = await this.sparkService.executeQuery(currentQuery.id, {
|
|
@@ -1839,6 +1947,11 @@ class SparkQueryListComponent {
|
|
|
1839
1947
|
}
|
|
1840
1948
|
}
|
|
1841
1949
|
onSettingsChange() {
|
|
1950
|
+
if (this.isStreaming()) {
|
|
1951
|
+
// Streaming: sort/filter is client-side only
|
|
1952
|
+
this.applyFilter();
|
|
1953
|
+
return;
|
|
1954
|
+
}
|
|
1842
1955
|
if (this.query()?.renderMode === 'VirtualScrolling') {
|
|
1843
1956
|
this.virtualDataSource()?.reset();
|
|
1844
1957
|
this.initVirtualDataSource();
|
|
@@ -1848,6 +1961,10 @@ class SparkQueryListComponent {
|
|
|
1848
1961
|
}
|
|
1849
1962
|
}
|
|
1850
1963
|
onSearchChange() {
|
|
1964
|
+
if (this.isStreaming()) {
|
|
1965
|
+
this.applyFilter();
|
|
1966
|
+
return;
|
|
1967
|
+
}
|
|
1851
1968
|
if (this.query()?.renderMode === 'VirtualScrolling') {
|
|
1852
1969
|
this.virtualDataSource()?.reset();
|
|
1853
1970
|
this.initVirtualDataSource();
|
|
@@ -1898,14 +2015,106 @@ class SparkQueryListComponent {
|
|
|
1898
2015
|
this.router.navigate(['/po', et.alias || et.id, 'new']);
|
|
1899
2016
|
}
|
|
1900
2017
|
}
|
|
2018
|
+
connectStreaming(queryId) {
|
|
2019
|
+
this.disconnectStreaming();
|
|
2020
|
+
this.isStreaming.set(true);
|
|
2021
|
+
this.streamingSub = this.streamingService.connectToStreamingQuery(queryId).subscribe({
|
|
2022
|
+
next: (message) => this.handleStreamingMessage(message),
|
|
2023
|
+
error: (err) => {
|
|
2024
|
+
this.errorMessage.set(err?.message || 'Streaming connection failed');
|
|
2025
|
+
this.isStreaming.set(false);
|
|
2026
|
+
},
|
|
2027
|
+
complete: () => {
|
|
2028
|
+
this.isStreaming.set(false);
|
|
2029
|
+
}
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
disconnectStreaming() {
|
|
2033
|
+
if (this.streamingSub) {
|
|
2034
|
+
this.streamingSub.unsubscribe();
|
|
2035
|
+
this.streamingSub = null;
|
|
2036
|
+
}
|
|
2037
|
+
this.isStreaming.set(false);
|
|
2038
|
+
}
|
|
2039
|
+
handleStreamingMessage(message) {
|
|
2040
|
+
switch (message.type) {
|
|
2041
|
+
case 'snapshot':
|
|
2042
|
+
this.errorMessage.set(null);
|
|
2043
|
+
this.allItems.set(message.data);
|
|
2044
|
+
this.applyFilter();
|
|
2045
|
+
break;
|
|
2046
|
+
case 'patch':
|
|
2047
|
+
if (message.updated.length > 0) {
|
|
2048
|
+
const currentItems = this.allItems();
|
|
2049
|
+
const updatedItems = currentItems.map(item => {
|
|
2050
|
+
const patch = message.updated.find(u => u.id === item.id);
|
|
2051
|
+
if (!patch)
|
|
2052
|
+
return item;
|
|
2053
|
+
// Clone the item and update only changed attribute values
|
|
2054
|
+
const updatedAttributes = item.attributes.map(attr => {
|
|
2055
|
+
if (attr.name in patch.attributes) {
|
|
2056
|
+
return { ...attr, value: patch.attributes[attr.name] };
|
|
2057
|
+
}
|
|
2058
|
+
return attr;
|
|
2059
|
+
});
|
|
2060
|
+
return { ...item, attributes: updatedAttributes };
|
|
2061
|
+
});
|
|
2062
|
+
this.allItems.set(updatedItems);
|
|
2063
|
+
this.applyFilter();
|
|
2064
|
+
}
|
|
2065
|
+
break;
|
|
2066
|
+
case 'error':
|
|
2067
|
+
this.errorMessage.set(message.message);
|
|
2068
|
+
break;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
applyFilter() {
|
|
2072
|
+
let items = this.allItems();
|
|
2073
|
+
// Apply search filter
|
|
2074
|
+
if (this.searchTerm) {
|
|
2075
|
+
const term = this.searchTerm.toLowerCase();
|
|
2076
|
+
items = items.filter(item => item.attributes.some(a => String(a.value ?? '').toLowerCase().includes(term)));
|
|
2077
|
+
}
|
|
2078
|
+
// Apply sorting
|
|
2079
|
+
const isVirtual = this.query()?.renderMode === 'VirtualScrolling';
|
|
2080
|
+
const sortCols = isVirtual ? this.virtualSettings().sortColumns : this.settings().sortColumns;
|
|
2081
|
+
if (sortCols.length > 0) {
|
|
2082
|
+
items = [...items].sort((a, b) => {
|
|
2083
|
+
for (const col of sortCols) {
|
|
2084
|
+
const aVal = a.attributes.find(attr => attr.name === col.property)?.value ?? '';
|
|
2085
|
+
const bVal = b.attributes.find(attr => attr.name === col.property)?.value ?? '';
|
|
2086
|
+
const cmp = String(aVal).localeCompare(String(bVal));
|
|
2087
|
+
if (cmp !== 0)
|
|
2088
|
+
return col.direction === 'descending' ? -cmp : cmp;
|
|
2089
|
+
}
|
|
2090
|
+
return 0;
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
if (isVirtual) {
|
|
2094
|
+
// Update the mutable filtered items array.
|
|
2095
|
+
// The stable data source's fetchFn closure reads from this.filteredItems,
|
|
2096
|
+
// so clearing its cache and emitting empty triggers the CDK viewport to re-fetch.
|
|
2097
|
+
this.filteredItems = items;
|
|
2098
|
+
this.virtualDataSource()?.reset();
|
|
2099
|
+
}
|
|
2100
|
+
else {
|
|
2101
|
+
this.paginationData.set({
|
|
2102
|
+
data: items,
|
|
2103
|
+
totalRecords: items.length,
|
|
2104
|
+
totalPages: 1,
|
|
2105
|
+
perPage: items.length,
|
|
2106
|
+
page: 1
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
1901
2110
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkQueryListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1902
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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>{{ (query()?.description | resolveTranslation) || query()?.name || ('loading' | t) }}</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\" /> {{ '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]=\"'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 ? ('resultFound' | t) : ('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: i2$1.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 });
|
|
2111
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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 || ('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\" /> {{ '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]=\"'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 ? ('resultFound' | t) : ('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: i2$1.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 });
|
|
1903
2112
|
}
|
|
1904
2113
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkQueryListComponent, decorators: [{
|
|
1905
2114
|
type: Component,
|
|
1906
2115
|
args: [{ selector: 'spark-query-list', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, FormsModule, RouterModule, BsAlertComponent, BsContainerComponent, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsVirtualDatatableComponent, BsVirtualRowTemplateDirective, BsFormComponent, BsFormControlDirective, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsInputGroupComponent, BsSpinnerComponent, SparkIconComponent, ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1907
2116
|
'[class.virtual-scrolling]': 'isVirtualScrolling()'
|
|
1908
|
-
}, 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
|
|
2117
|
+
}, 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 || ('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\" /> {{ '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]=\"'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 ? ('resultFound' | t) : ('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"] }]
|
|
1909
2118
|
}], 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"] }] } });
|
|
1910
2119
|
|
|
1911
2120
|
var sparkQueryList_component = /*#__PURE__*/Object.freeze({
|
|
@@ -2056,5 +2265,5 @@ function provideSpark(config) {
|
|
|
2056
2265
|
* Generated bundle index. Do not edit.
|
|
2057
2266
|
*/
|
|
2058
2267
|
|
|
2059
|
-
export { ArrayValuePipe, AsDetailCellValuePipe, AsDetailColumnsPipe, AsDetailDisplayValuePipe, AsDetailTypePipe, AttributeValuePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, ELookupDisplayType, ErrorForAttributePipe, IconNamePipe, InlineRefOptionsPipe, InputTypePipe, LookupDisplayTypePipe, LookupDisplayValuePipe, LookupOptionsPipe, RawAttributeValuePipe, ReferenceAttrValuePipe, ReferenceDisplayValuePipe, ReferenceLinkRoutePipe, ResolveTranslationPipe, RetryActionService, RouterLinkPipe, SPARK_ATTRIBUTE_RENDERERS, SPARK_CONFIG, ShowedOn, SparkIconComponent, SparkIconRegistry, SparkLanguageService, SparkPoCreateComponent, SparkPoDetailComponent, SparkPoEditComponent, SparkPoFormComponent, SparkQueryListComponent, SparkRetryActionModalComponent, SparkService, SparkSubQueryComponent, TranslateKeyPipe, currentLanguage, defaultSparkConfig, hasShowedOnFlag, provideSpark, provideSparkAttributeRenderers, resolveTranslation, sparkRoutes };
|
|
2268
|
+
export { ArrayValuePipe, AsDetailCellValuePipe, AsDetailColumnsPipe, AsDetailDisplayValuePipe, AsDetailTypePipe, AttributeValuePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, ELookupDisplayType, ErrorForAttributePipe, IconNamePipe, InlineRefOptionsPipe, InputTypePipe, LookupDisplayTypePipe, LookupDisplayValuePipe, LookupOptionsPipe, RawAttributeValuePipe, ReferenceAttrValuePipe, ReferenceDisplayValuePipe, ReferenceLinkRoutePipe, ResolveTranslationPipe, RetryActionService, RouterLinkPipe, SPARK_ATTRIBUTE_RENDERERS, SPARK_CONFIG, ShowedOn, SparkIconComponent, SparkIconRegistry, SparkLanguageService, SparkPoCreateComponent, SparkPoDetailComponent, SparkPoEditComponent, SparkPoFormComponent, SparkQueryListComponent, SparkRetryActionModalComponent, SparkService, SparkStreamingService, SparkSubQueryComponent, TranslateKeyPipe, currentLanguage, defaultSparkConfig, hasShowedOnFlag, provideSpark, provideSparkAttributeRenderers, resolveTranslation, sparkRoutes };
|
|
2060
2269
|
//# sourceMappingURL=mintplayer-ng-spark.mjs.map
|