@mintplayer/ng-spark 0.0.9 → 0.1.1
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';
|
|
@@ -85,10 +85,10 @@ class RetryActionService {
|
|
|
85
85
|
this.resolveRetry?.(result);
|
|
86
86
|
this.resolveRetry = null;
|
|
87
87
|
}
|
|
88
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
89
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
88
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RetryActionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
89
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RetryActionService, providedIn: 'root' });
|
|
90
90
|
}
|
|
91
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
91
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RetryActionService, decorators: [{
|
|
92
92
|
type: Injectable,
|
|
93
93
|
args: [{ providedIn: 'root' }]
|
|
94
94
|
}] });
|
|
@@ -141,9 +141,9 @@ class SparkService {
|
|
|
141
141
|
params = params.set('search', options.search);
|
|
142
142
|
return firstValueFrom(this.http.get(`${this.baseUrl}/queries/${encodeURIComponent(queryId)}/execute`, { params }));
|
|
143
143
|
}
|
|
144
|
-
async executeQueryByName(queryName) {
|
|
144
|
+
async executeQueryByName(queryName, options) {
|
|
145
145
|
const query = await this.getQueryByName(queryName);
|
|
146
|
-
return query ? this.executeQuery(query.id) : { data: [], totalRecords: 0, skip: 0, take: 50 };
|
|
146
|
+
return query ? this.executeQuery(query.id, { parentId: options?.parentId, parentType: options?.parentType }) : { data: [], totalRecords: 0, skip: 0, take: 50 };
|
|
147
147
|
}
|
|
148
148
|
// Program Units
|
|
149
149
|
async getProgramUnits() {
|
|
@@ -230,10 +230,96 @@ class SparkService {
|
|
|
230
230
|
body.retryResults = [...(body.retryResults || []), result];
|
|
231
231
|
return retryFn();
|
|
232
232
|
}
|
|
233
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
234
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
233
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
234
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkService, providedIn: 'root' });
|
|
235
235
|
}
|
|
236
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
236
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkService, decorators: [{
|
|
237
|
+
type: Injectable,
|
|
238
|
+
args: [{ providedIn: 'root' }]
|
|
239
|
+
}] });
|
|
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.1.6", ngImport: i0, type: SparkStreamingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
320
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkStreamingService, providedIn: 'root' });
|
|
321
|
+
}
|
|
322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkStreamingService, decorators: [{
|
|
237
323
|
type: Injectable,
|
|
238
324
|
args: [{ providedIn: 'root' }]
|
|
239
325
|
}] });
|
|
@@ -277,10 +363,10 @@ class SparkLanguageService {
|
|
|
277
363
|
const ts = this.translationsMap()[key];
|
|
278
364
|
return this.resolve(ts) || key;
|
|
279
365
|
}
|
|
280
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
281
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
366
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkLanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
367
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkLanguageService, providedIn: 'root' });
|
|
282
368
|
}
|
|
283
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
369
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkLanguageService, decorators: [{
|
|
284
370
|
type: Injectable,
|
|
285
371
|
args: [{ providedIn: 'root' }]
|
|
286
372
|
}], ctorParameters: () => [] });
|
|
@@ -290,10 +376,10 @@ class TranslateKeyPipe {
|
|
|
290
376
|
transform(key) {
|
|
291
377
|
return this.lang.t(key);
|
|
292
378
|
}
|
|
293
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
294
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
379
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: TranslateKeyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
380
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: TranslateKeyPipe, isStandalone: true, name: "t", pure: false });
|
|
295
381
|
}
|
|
296
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
382
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: TranslateKeyPipe, decorators: [{
|
|
297
383
|
type: Pipe,
|
|
298
384
|
args: [{ name: 't', pure: false, standalone: true }]
|
|
299
385
|
}] });
|
|
@@ -302,10 +388,10 @@ class ResolveTranslationPipe {
|
|
|
302
388
|
transform(value, fallback) {
|
|
303
389
|
return resolveTranslation(value) || fallback || '';
|
|
304
390
|
}
|
|
305
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
306
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
391
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ResolveTranslationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
392
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: ResolveTranslationPipe, isStandalone: true, name: "resolveTranslation", pure: false });
|
|
307
393
|
}
|
|
308
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
394
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ResolveTranslationPipe, decorators: [{
|
|
309
395
|
type: Pipe,
|
|
310
396
|
args: [{ name: 'resolveTranslation', standalone: true, pure: false }]
|
|
311
397
|
}] });
|
|
@@ -328,10 +414,10 @@ class InputTypePipe {
|
|
|
328
414
|
return 'text';
|
|
329
415
|
}
|
|
330
416
|
}
|
|
331
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
332
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
417
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InputTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
418
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: InputTypePipe, isStandalone: true, name: "inputType" });
|
|
333
419
|
}
|
|
334
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
420
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InputTypePipe, decorators: [{
|
|
335
421
|
type: Pipe,
|
|
336
422
|
args: [{ name: 'inputType', standalone: true, pure: true }]
|
|
337
423
|
}] });
|
|
@@ -348,10 +434,10 @@ class LookupDisplayValuePipe {
|
|
|
348
434
|
return String(currentValue);
|
|
349
435
|
return resolveTranslation(selected.values) || selected.key;
|
|
350
436
|
}
|
|
351
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
352
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
437
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: LookupDisplayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
438
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: LookupDisplayValuePipe, isStandalone: true, name: "lookupDisplayValue" });
|
|
353
439
|
}
|
|
354
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
440
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: LookupDisplayValuePipe, decorators: [{
|
|
355
441
|
type: Pipe,
|
|
356
442
|
args: [{ name: 'lookupDisplayValue', standalone: true, pure: true }]
|
|
357
443
|
}] });
|
|
@@ -361,10 +447,10 @@ class LookupDisplayTypePipe {
|
|
|
361
447
|
const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;
|
|
362
448
|
return lookupRef?.displayType ?? ELookupDisplayType.Dropdown;
|
|
363
449
|
}
|
|
364
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
365
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
450
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: LookupDisplayTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
451
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: LookupDisplayTypePipe, isStandalone: true, name: "lookupDisplayType" });
|
|
366
452
|
}
|
|
367
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
453
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: LookupDisplayTypePipe, decorators: [{
|
|
368
454
|
type: Pipe,
|
|
369
455
|
args: [{ name: 'lookupDisplayType', standalone: true, pure: true }]
|
|
370
456
|
}] });
|
|
@@ -374,10 +460,10 @@ class LookupOptionsPipe {
|
|
|
374
460
|
const lookupRef = attr.lookupReferenceType ? lookupRefOptions[attr.lookupReferenceType] : null;
|
|
375
461
|
return lookupRef?.values.filter(v => v.isActive) || [];
|
|
376
462
|
}
|
|
377
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
378
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
463
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: LookupOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
464
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: LookupOptionsPipe, isStandalone: true, name: "lookupOptions" });
|
|
379
465
|
}
|
|
380
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
466
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: LookupOptionsPipe, decorators: [{
|
|
381
467
|
type: Pipe,
|
|
382
468
|
args: [{ name: 'lookupOptions', standalone: true, pure: true }]
|
|
383
469
|
}] });
|
|
@@ -392,10 +478,10 @@ class ReferenceDisplayValuePipe {
|
|
|
392
478
|
const selected = options.find(o => o.id === selectedId);
|
|
393
479
|
return selected?.breadcrumb || selected?.name || selectedId;
|
|
394
480
|
}
|
|
395
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
396
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
481
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ReferenceDisplayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
482
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: ReferenceDisplayValuePipe, isStandalone: true, name: "referenceDisplayValue" });
|
|
397
483
|
}
|
|
398
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
484
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ReferenceDisplayValuePipe, decorators: [{
|
|
399
485
|
type: Pipe,
|
|
400
486
|
args: [{ name: 'referenceDisplayValue', standalone: true, pure: true }]
|
|
401
487
|
}] });
|
|
@@ -431,10 +517,10 @@ class AsDetailDisplayValuePipe {
|
|
|
431
517
|
return value != null ? String(value) : '';
|
|
432
518
|
});
|
|
433
519
|
}
|
|
434
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
435
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
520
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailDisplayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
521
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: AsDetailDisplayValuePipe, isStandalone: true, name: "asDetailDisplayValue" });
|
|
436
522
|
}
|
|
437
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
523
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailDisplayValuePipe, decorators: [{
|
|
438
524
|
type: Pipe,
|
|
439
525
|
args: [{ name: 'asDetailDisplayValue', standalone: true, pure: true }]
|
|
440
526
|
}] });
|
|
@@ -443,10 +529,10 @@ class AsDetailTypePipe {
|
|
|
443
529
|
transform(attr, asDetailTypes) {
|
|
444
530
|
return asDetailTypes[attr.name] || null;
|
|
445
531
|
}
|
|
446
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
447
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
532
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
533
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: AsDetailTypePipe, isStandalone: true, name: "asDetailType" });
|
|
448
534
|
}
|
|
449
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
535
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailTypePipe, decorators: [{
|
|
450
536
|
type: Pipe,
|
|
451
537
|
args: [{ name: 'asDetailType', standalone: true, pure: true }]
|
|
452
538
|
}] });
|
|
@@ -460,10 +546,10 @@ class AsDetailColumnsPipe {
|
|
|
460
546
|
.filter(a => a.isVisible)
|
|
461
547
|
.sort((a, b) => a.order - b.order);
|
|
462
548
|
}
|
|
463
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
464
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
549
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailColumnsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
550
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: AsDetailColumnsPipe, isStandalone: true, name: "asDetailColumns" });
|
|
465
551
|
}
|
|
466
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
552
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailColumnsPipe, decorators: [{
|
|
467
553
|
type: Pipe,
|
|
468
554
|
args: [{ name: 'asDetailColumns', standalone: true, pure: true }]
|
|
469
555
|
}] });
|
|
@@ -486,10 +572,10 @@ class AsDetailCellValuePipe {
|
|
|
486
572
|
}
|
|
487
573
|
return String(value);
|
|
488
574
|
}
|
|
489
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
490
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
575
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailCellValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
576
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: AsDetailCellValuePipe, isStandalone: true, name: "asDetailCellValue" });
|
|
491
577
|
}
|
|
492
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
578
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AsDetailCellValuePipe, decorators: [{
|
|
493
579
|
type: Pipe,
|
|
494
580
|
args: [{ name: 'asDetailCellValue', standalone: true, pure: true }]
|
|
495
581
|
}] });
|
|
@@ -499,10 +585,10 @@ class CanCreateDetailRowPipe {
|
|
|
499
585
|
const perms = permissions[attr.name];
|
|
500
586
|
return perms ? perms.canCreate : true;
|
|
501
587
|
}
|
|
502
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
503
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
588
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CanCreateDetailRowPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
589
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: CanCreateDetailRowPipe, isStandalone: true, name: "canCreateDetailRow" });
|
|
504
590
|
}
|
|
505
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
591
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CanCreateDetailRowPipe, decorators: [{
|
|
506
592
|
type: Pipe,
|
|
507
593
|
args: [{ name: 'canCreateDetailRow', standalone: true, pure: true }]
|
|
508
594
|
}] });
|
|
@@ -512,10 +598,10 @@ class CanDeleteDetailRowPipe {
|
|
|
512
598
|
const perms = permissions[attr.name];
|
|
513
599
|
return perms ? perms.canDelete : true;
|
|
514
600
|
}
|
|
515
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
516
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
601
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CanDeleteDetailRowPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
602
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: CanDeleteDetailRowPipe, isStandalone: true, name: "canDeleteDetailRow" });
|
|
517
603
|
}
|
|
518
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
604
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: CanDeleteDetailRowPipe, decorators: [{
|
|
519
605
|
type: Pipe,
|
|
520
606
|
args: [{ name: 'canDeleteDetailRow', standalone: true, pure: true }]
|
|
521
607
|
}] });
|
|
@@ -524,10 +610,10 @@ class InlineRefOptionsPipe {
|
|
|
524
610
|
transform(parentAttr, col, asDetailRefOptions) {
|
|
525
611
|
return asDetailRefOptions[parentAttr.name]?.[col.name] || [];
|
|
526
612
|
}
|
|
527
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
528
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
613
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InlineRefOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
614
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: InlineRefOptionsPipe, isStandalone: true, name: "inlineRefOptions" });
|
|
529
615
|
}
|
|
530
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
616
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: InlineRefOptionsPipe, decorators: [{
|
|
531
617
|
type: Pipe,
|
|
532
618
|
args: [{ name: 'inlineRefOptions', standalone: true, pure: true }]
|
|
533
619
|
}] });
|
|
@@ -541,10 +627,10 @@ class ReferenceAttrValuePipe {
|
|
|
541
627
|
return attr.breadcrumb;
|
|
542
628
|
return attr.value ?? '';
|
|
543
629
|
}
|
|
544
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
545
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
630
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ReferenceAttrValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
631
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: ReferenceAttrValuePipe, isStandalone: true, name: "referenceAttrValue" });
|
|
546
632
|
}
|
|
547
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
633
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ReferenceAttrValuePipe, decorators: [{
|
|
548
634
|
type: Pipe,
|
|
549
635
|
args: [{ name: 'referenceAttrValue', standalone: true, pure: true }]
|
|
550
636
|
}] });
|
|
@@ -554,10 +640,10 @@ class ErrorForAttributePipe {
|
|
|
554
640
|
const error = validationErrors.find(e => e.attributeName === attrName);
|
|
555
641
|
return error ? resolveTranslation(error.errorMessage) : null;
|
|
556
642
|
}
|
|
557
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
558
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
643
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ErrorForAttributePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
644
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: ErrorForAttributePipe, isStandalone: true, name: "errorForAttribute" });
|
|
559
645
|
}
|
|
560
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
646
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ErrorForAttributePipe, decorators: [{
|
|
561
647
|
type: Pipe,
|
|
562
648
|
args: [{ name: 'errorForAttribute', standalone: true, pure: true }]
|
|
563
649
|
}] });
|
|
@@ -590,10 +676,10 @@ class SparkIconRegistry {
|
|
|
590
676
|
has(name) {
|
|
591
677
|
return this.icons.has(name);
|
|
592
678
|
}
|
|
593
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
594
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
679
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkIconRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
680
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkIconRegistry, providedIn: 'root' });
|
|
595
681
|
}
|
|
596
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
682
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkIconRegistry, decorators: [{
|
|
597
683
|
type: Injectable,
|
|
598
684
|
args: [{ providedIn: 'root' }]
|
|
599
685
|
}], ctorParameters: () => [] });
|
|
@@ -603,8 +689,8 @@ class SparkIconComponent {
|
|
|
603
689
|
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : []));
|
|
604
690
|
iconHtml = computed(() => this.registry.get(this.name()), ...(ngDevMode ? [{ debugName: "iconHtml" }] : []));
|
|
605
691
|
cssFallbackClass = computed(() => `bi-${this.name()}`, ...(ngDevMode ? [{ debugName: "cssFallbackClass" }] : []));
|
|
606
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
607
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
692
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
693
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkIconComponent, isStandalone: true, selector: "spark-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
|
|
608
694
|
@if (iconHtml(); as html) {
|
|
609
695
|
<span [innerHTML]="html"></span>
|
|
610
696
|
} @else {
|
|
@@ -612,7 +698,7 @@ class SparkIconComponent {
|
|
|
612
698
|
}
|
|
613
699
|
`, isInline: true, styles: [":host{display:inline-flex;align-items:center;justify-content:center}span{display:inline-flex;align-items:center}span ::ng-deep svg{width:1em;height:1em;fill:currentColor}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
614
700
|
}
|
|
615
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
701
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkIconComponent, decorators: [{
|
|
616
702
|
type: Component,
|
|
617
703
|
args: [{ selector: 'spark-icon', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
618
704
|
@if (iconHtml(); as html) {
|
|
@@ -649,6 +735,8 @@ class SparkPoFormComponent {
|
|
|
649
735
|
validationErrors = input([], ...(ngDevMode ? [{ debugName: "validationErrors" }] : []));
|
|
650
736
|
showButtons = input(false, ...(ngDevMode ? [{ debugName: "showButtons" }] : []));
|
|
651
737
|
isSaving = input(false, ...(ngDevMode ? [{ debugName: "isSaving" }] : []));
|
|
738
|
+
parentId = input(undefined, ...(ngDevMode ? [{ debugName: "parentId" }] : []));
|
|
739
|
+
parentType = input(undefined, ...(ngDevMode ? [{ debugName: "parentType" }] : []));
|
|
652
740
|
save = output();
|
|
653
741
|
cancel = output();
|
|
654
742
|
colors = Color;
|
|
@@ -731,6 +819,8 @@ class SparkPoFormComponent {
|
|
|
731
819
|
constructor() {
|
|
732
820
|
effect(() => {
|
|
733
821
|
const et = this.entityType();
|
|
822
|
+
const _pid = this.parentId();
|
|
823
|
+
const _ptype = this.parentType();
|
|
734
824
|
if (et) {
|
|
735
825
|
this.loadReferenceOptions();
|
|
736
826
|
this.loadAsDetailTypes();
|
|
@@ -750,7 +840,10 @@ class SparkPoFormComponent {
|
|
|
750
840
|
if (refAttrs.length === 0)
|
|
751
841
|
return;
|
|
752
842
|
const entries = await Promise.all(refAttrs.filter(a => a.query).map(async (attr) => {
|
|
753
|
-
const result = await this.sparkService.executeQueryByName(attr.query
|
|
843
|
+
const result = await this.sparkService.executeQueryByName(attr.query, {
|
|
844
|
+
parentId: this.parentId(),
|
|
845
|
+
parentType: this.parentType(),
|
|
846
|
+
});
|
|
754
847
|
return [attr.name, result.data];
|
|
755
848
|
}));
|
|
756
849
|
this.referenceOptions.set(this.toRecord(entries));
|
|
@@ -771,7 +864,10 @@ class SparkPoFormComponent {
|
|
|
771
864
|
const refCols = asDetailType.attributes.filter(a => a.dataType === 'Reference' && a.query);
|
|
772
865
|
if (refCols.length > 0) {
|
|
773
866
|
const refEntries = await Promise.all(refCols.filter(c => c.query).map(async (col) => {
|
|
774
|
-
const result = await this.sparkService.executeQueryByName(col.query
|
|
867
|
+
const result = await this.sparkService.executeQueryByName(col.query, {
|
|
868
|
+
parentId: this.parentId(),
|
|
869
|
+
parentType: this.parentType(),
|
|
870
|
+
});
|
|
775
871
|
return [col.name, result.data];
|
|
776
872
|
}));
|
|
777
873
|
this.asDetailReferenceOptions.update(prev => ({ ...prev, [attr.name]: this.toRecord(refEntries) }));
|
|
@@ -984,13 +1080,13 @@ class SparkPoFormComponent {
|
|
|
984
1080
|
this.referenceModalEntityType.set(null);
|
|
985
1081
|
this.referenceSearchTerm = '';
|
|
986
1082
|
}
|
|
987
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
988
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkPoFormComponent, isStandalone: true, selector: "spark-po-form", inputs: { entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, formData: { classPropertyName: "formData", publicName: "formData", isSignal: true, isRequired: false, transformFunction: null }, validationErrors: { classPropertyName: "validationErrors", publicName: "validationErrors", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, isSaving: { classPropertyName: "isSaving", publicName: "isSaving", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formData: "formDataChange", save: "save", cancel: "cancel" }, ngImport: i0, template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n </label>\n <div [md]=\"8\">\n @if (attr.dataType === 'boolean') {\n <bs-toggle-button\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\">\n </bs-toggle-button>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | lookupDisplayValue:formData():lookupReferenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openLookupSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else {\n <bs-select\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | referenceDisplayValue:formData():referenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openReferenceSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'boolean') {\n <bs-toggle-button\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n </bs-toggle-button>\n } @else if (col.dataType === 'Reference' && col.query) {\n <bs-select\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.name || option.id }}\n </option>\n }\n </bs-select>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n (ngModelChange)=\"onFieldChange()\">\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</td>\n }\n <td class=\"text-nowrap\">\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(attr)\"></ng-container>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting Reference items -->\n<bs-modal [isOpen]=\"showReferenceModal()\" (isOpenChange)=\"!$event && closeReferenceModal()\">\n <div *bsModal class=\"reference-modal\">\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingReferenceAttr()?.label | resolveTranslation:editingReferenceAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n @if (referenceModalEntityType()) {\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"6\">\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)]=\"referenceSearchTerm\"\n (ngModelChange)=\"onReferenceSearchChange()\">\n @if (referenceSearchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearReferenceSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"6\" class=\"text-end\">\n @if (referenceSearchTerm && referenceModalPagination()) {\n <span class=\"text-muted\">\n {{ referenceModalPagination()!.totalRecords }} {{ referenceModalPagination()!.totalRecords === 1 ? ('resultFound' | t) : ('resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n\n <bs-datatable [(settings)]=\"referenceModalSettings\" (settingsChange)=\"applyReferenceFilter()\">\n @for (attr of referenceVisibleAttributes(); 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 referenceModalPagination()\" (click)=\"selectReferenceItem(item)\" style=\"cursor: pointer;\">\n @for (attr of referenceVisibleAttributes(); track attr.id) {\n <td>{{ item | referenceAttrValue:attr.name }}</td>\n }\n </tr>\n </bs-datatable>\n } @else {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n }\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeReferenceModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting LookupReference items -->\n<bs-modal [isOpen]=\"showLookupModal()\" (isOpenChange)=\"!$event && closeLookupModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingLookupAttr()?.label | resolveTranslation:editingLookupAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\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]=\"lookupSearchTerm()\"\n (ngModelChange)=\"lookupSearchTerm.set($event)\">\n @if (lookupSearchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"lookupSearchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody>\n @for (item of filteredLookupItems(); track item.key) {\n <tr\n [class.table-primary]=\"formData()[editingLookupAttr()?.name ?? ''] === item.key\"\n (click)=\"selectLookupItem(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeLookupModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n", dependencies: [{ kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving"], outputs: ["formDataChange", "save", "cancel"] }, { 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.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { 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: "directive", type: BsGridColDirective, selector: "[col]", inputs: ["col"] }, { kind: "directive", type: BsColFormLabelDirective, selector: "[bsColFormLabel]" }, { kind: "directive", type: BsButtonTypeDirective, selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]", inputs: ["color"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group" }, { kind: "component", type: BsSelectComponent, selector: "bs-select", inputs: ["identifier", "size", "multiple", "numberVisible", "disabled"] }, { kind: "directive", type: BsSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type: BsModalHostComponent, selector: "bs-modal", inputs: ["isOpen", "closeOnEscape"], outputs: ["isOpenChange"] }, { kind: "directive", type: BsModalDirective, selector: "[bsModal]" }, { kind: "directive", type: BsModalHeaderDirective, selector: "[bsModalHeader]" }, { kind: "directive", type: BsModalBodyDirective, selector: "[bsModalBody]" }, { kind: "directive", type: BsModalFooterDirective, selector: "[bsModalFooter]" }, { 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: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover"] }, { kind: "component", type: BsToggleButtonComponent, selector: "bs-toggle-button", inputs: ["type", "isToggled", "name", "value", "group"], outputs: ["isToggledChange"] }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: BsTabControlComponent, selector: "bs-tab-control", inputs: ["border", "restrictDragging", "selectFirstTab", "tabsPosition", "allowDragDrop"] }, { kind: "component", type: BsTabPageComponent, selector: "bs-tab-page", inputs: ["disabled"] }, { kind: "directive", type: BsTabPageHeaderDirective, selector: "[bsTabPageHeader]" }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: InputTypePipe, name: "inputType" }, { kind: "pipe", type: LookupDisplayValuePipe, name: "lookupDisplayValue" }, { kind: "pipe", type: LookupDisplayTypePipe, name: "lookupDisplayType" }, { kind: "pipe", type: LookupOptionsPipe, name: "lookupOptions" }, { kind: "pipe", type: ReferenceDisplayValuePipe, name: "referenceDisplayValue" }, { kind: "pipe", type: AsDetailDisplayValuePipe, name: "asDetailDisplayValue" }, { kind: "pipe", type: AsDetailTypePipe, name: "asDetailType" }, { kind: "pipe", type: AsDetailColumnsPipe, name: "asDetailColumns" }, { kind: "pipe", type: AsDetailCellValuePipe, name: "asDetailCellValue" }, { kind: "pipe", type: CanCreateDetailRowPipe, name: "canCreateDetailRow" }, { kind: "pipe", type: CanDeleteDetailRowPipe, name: "canDeleteDetailRow" }, { kind: "pipe", type: InlineRefOptionsPipe, name: "inlineRefOptions" }, { kind: "pipe", type: ReferenceAttrValuePipe, name: "referenceAttrValue" }, { kind: "pipe", type: ErrorForAttributePipe, name: "errorForAttribute" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1083
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1084
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkPoFormComponent, isStandalone: true, selector: "spark-po-form", inputs: { entityType: { classPropertyName: "entityType", publicName: "entityType", isSignal: true, isRequired: false, transformFunction: null }, formData: { classPropertyName: "formData", publicName: "formData", isSignal: true, isRequired: false, transformFunction: null }, validationErrors: { classPropertyName: "validationErrors", publicName: "validationErrors", isSignal: true, isRequired: false, transformFunction: null }, showButtons: { classPropertyName: "showButtons", publicName: "showButtons", isSignal: true, isRequired: false, transformFunction: null }, isSaving: { classPropertyName: "isSaving", publicName: "isSaving", isSignal: true, isRequired: false, transformFunction: null }, parentId: { classPropertyName: "parentId", publicName: "parentId", isSignal: true, isRequired: false, transformFunction: null }, parentType: { classPropertyName: "parentType", publicName: "parentType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formData: "formDataChange", save: "save", cancel: "cancel" }, ngImport: i0, template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n </label>\n <div [md]=\"8\">\n @if (attr.dataType === 'boolean') {\n <bs-toggle-button\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\">\n </bs-toggle-button>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | lookupDisplayValue:formData():lookupReferenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openLookupSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else {\n <bs-select\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | referenceDisplayValue:formData():referenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openReferenceSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'boolean') {\n <bs-toggle-button\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n </bs-toggle-button>\n } @else if (col.dataType === 'Reference' && col.query) {\n <bs-select\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.name || option.id }}\n </option>\n }\n </bs-select>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n (ngModelChange)=\"onFieldChange()\">\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</td>\n }\n <td class=\"text-nowrap\">\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(attr)\"></ng-container>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting Reference items -->\n<bs-modal [isOpen]=\"showReferenceModal()\" (isOpenChange)=\"!$event && closeReferenceModal()\">\n <div *bsModal class=\"reference-modal\">\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingReferenceAttr()?.label | resolveTranslation:editingReferenceAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n @if (referenceModalEntityType()) {\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"6\">\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)]=\"referenceSearchTerm\"\n (ngModelChange)=\"onReferenceSearchChange()\">\n @if (referenceSearchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearReferenceSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"6\" class=\"text-end\">\n @if (referenceSearchTerm && referenceModalPagination()) {\n <span class=\"text-muted\">\n {{ referenceModalPagination()!.totalRecords }} {{ referenceModalPagination()!.totalRecords === 1 ? ('resultFound' | t) : ('resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n\n <bs-datatable [(settings)]=\"referenceModalSettings\" (settingsChange)=\"applyReferenceFilter()\">\n @for (attr of referenceVisibleAttributes(); 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 referenceModalPagination()\" (click)=\"selectReferenceItem(item)\" style=\"cursor: pointer;\">\n @for (attr of referenceVisibleAttributes(); track attr.id) {\n <td>{{ item | referenceAttrValue:attr.name }}</td>\n }\n </tr>\n </bs-datatable>\n } @else {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n }\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeReferenceModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting LookupReference items -->\n<bs-modal [isOpen]=\"showLookupModal()\" (isOpenChange)=\"!$event && closeLookupModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingLookupAttr()?.label | resolveTranslation:editingLookupAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\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]=\"lookupSearchTerm()\"\n (ngModelChange)=\"lookupSearchTerm.set($event)\">\n @if (lookupSearchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"lookupSearchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody>\n @for (item of filteredLookupItems(); track item.key) {\n <tr\n [class.table-primary]=\"formData()[editingLookupAttr()?.name ?? ''] === item.key\"\n (click)=\"selectLookupItem(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeLookupModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n", dependencies: [{ kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType"], outputs: ["formDataChange", "save", "cancel"] }, { 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.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { 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: "directive", type: BsGridColDirective, selector: "[col]", inputs: ["col"] }, { kind: "directive", type: BsColFormLabelDirective, selector: "[bsColFormLabel]" }, { kind: "directive", type: BsButtonTypeDirective, selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]", inputs: ["color"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group" }, { kind: "component", type: BsSelectComponent, selector: "bs-select", inputs: ["identifier", "size", "multiple", "numberVisible", "disabled"] }, { kind: "directive", type: BsSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "component", type: BsModalHostComponent, selector: "bs-modal", inputs: ["isOpen", "closeOnEscape"], outputs: ["isOpenChange"] }, { kind: "directive", type: BsModalDirective, selector: "[bsModal]" }, { kind: "directive", type: BsModalHeaderDirective, selector: "[bsModalHeader]" }, { kind: "directive", type: BsModalBodyDirective, selector: "[bsModalBody]" }, { kind: "directive", type: BsModalFooterDirective, selector: "[bsModalFooter]" }, { 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: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover"] }, { kind: "component", type: BsToggleButtonComponent, selector: "bs-toggle-button", inputs: ["type", "isToggled", "name", "value", "group"], outputs: ["isToggledChange"] }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: BsTabControlComponent, selector: "bs-tab-control", inputs: ["border", "restrictDragging", "selectFirstTab", "tabsPosition", "allowDragDrop"] }, { kind: "component", type: BsTabPageComponent, selector: "bs-tab-page", inputs: ["disabled"] }, { kind: "directive", type: BsTabPageHeaderDirective, selector: "[bsTabPageHeader]" }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: InputTypePipe, name: "inputType" }, { kind: "pipe", type: LookupDisplayValuePipe, name: "lookupDisplayValue" }, { kind: "pipe", type: LookupDisplayTypePipe, name: "lookupDisplayType" }, { kind: "pipe", type: LookupOptionsPipe, name: "lookupOptions" }, { kind: "pipe", type: ReferenceDisplayValuePipe, name: "referenceDisplayValue" }, { kind: "pipe", type: AsDetailDisplayValuePipe, name: "asDetailDisplayValue" }, { kind: "pipe", type: AsDetailTypePipe, name: "asDetailType" }, { kind: "pipe", type: AsDetailColumnsPipe, name: "asDetailColumns" }, { kind: "pipe", type: AsDetailCellValuePipe, name: "asDetailCellValue" }, { kind: "pipe", type: CanCreateDetailRowPipe, name: "canCreateDetailRow" }, { kind: "pipe", type: CanDeleteDetailRowPipe, name: "canDeleteDetailRow" }, { kind: "pipe", type: InlineRefOptionsPipe, name: "inlineRefOptions" }, { kind: "pipe", type: ReferenceAttrValuePipe, name: "referenceAttrValue" }, { kind: "pipe", type: ErrorForAttributePipe, name: "errorForAttribute" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
989
1085
|
}
|
|
990
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1086
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoFormComponent, decorators: [{
|
|
991
1087
|
type: Component,
|
|
992
|
-
args: [{ selector: 'spark-po-form', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, FormsModule, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsGridColDirective, BsColFormLabelDirective, BsButtonTypeDirective, BsInputGroupComponent, BsSelectComponent, BsSelectOption, BsModalHostComponent, BsModalDirective, BsModalHeaderDirective, BsModalBodyDirective, BsModalFooterDirective, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsTableComponent, BsToggleButtonComponent, BsSpinnerComponent, BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective, SparkIconComponent, SparkPoFormComponent, TranslateKeyPipe, ResolveTranslationPipe, InputTypePipe, LookupDisplayValuePipe, LookupDisplayTypePipe, LookupOptionsPipe, ReferenceDisplayValuePipe, AsDetailDisplayValuePipe, AsDetailTypePipe, AsDetailColumnsPipe, AsDetailCellValuePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, InlineRefOptionsPipe, ReferenceAttrValuePipe, ErrorForAttributePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n </label>\n <div [md]=\"8\">\n @if (attr.dataType === 'boolean') {\n <bs-toggle-button\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\">\n </bs-toggle-button>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | lookupDisplayValue:formData():lookupReferenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openLookupSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else {\n <bs-select\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | referenceDisplayValue:formData():referenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openReferenceSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'boolean') {\n <bs-toggle-button\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n </bs-toggle-button>\n } @else if (col.dataType === 'Reference' && col.query) {\n <bs-select\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.name || option.id }}\n </option>\n }\n </bs-select>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n (ngModelChange)=\"onFieldChange()\">\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</td>\n }\n <td class=\"text-nowrap\">\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(attr)\"></ng-container>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting Reference items -->\n<bs-modal [isOpen]=\"showReferenceModal()\" (isOpenChange)=\"!$event && closeReferenceModal()\">\n <div *bsModal class=\"reference-modal\">\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingReferenceAttr()?.label | resolveTranslation:editingReferenceAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n @if (referenceModalEntityType()) {\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"6\">\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)]=\"referenceSearchTerm\"\n (ngModelChange)=\"onReferenceSearchChange()\">\n @if (referenceSearchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearReferenceSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"6\" class=\"text-end\">\n @if (referenceSearchTerm && referenceModalPagination()) {\n <span class=\"text-muted\">\n {{ referenceModalPagination()!.totalRecords }} {{ referenceModalPagination()!.totalRecords === 1 ? ('resultFound' | t) : ('resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n\n <bs-datatable [(settings)]=\"referenceModalSettings\" (settingsChange)=\"applyReferenceFilter()\">\n @for (attr of referenceVisibleAttributes(); 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 referenceModalPagination()\" (click)=\"selectReferenceItem(item)\" style=\"cursor: pointer;\">\n @for (attr of referenceVisibleAttributes(); track attr.id) {\n <td>{{ item | referenceAttrValue:attr.name }}</td>\n }\n </tr>\n </bs-datatable>\n } @else {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n }\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeReferenceModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting LookupReference items -->\n<bs-modal [isOpen]=\"showLookupModal()\" (isOpenChange)=\"!$event && closeLookupModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingLookupAttr()?.label | resolveTranslation:editingLookupAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\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]=\"lookupSearchTerm()\"\n (ngModelChange)=\"lookupSearchTerm.set($event)\">\n @if (lookupSearchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"lookupSearchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody>\n @for (item of filteredLookupItems(); track item.key) {\n <tr\n [class.table-primary]=\"formData()[editingLookupAttr()?.name ?? ''] === item.key\"\n (click)=\"selectLookupItem(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeLookupModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n" }]
|
|
993
|
-
}], ctorParameters: () => [], propDecorators: { entityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityType", required: false }] }], formData: [{ type: i0.Input, args: [{ isSignal: true, alias: "formData", required: false }] }, { type: i0.Output, args: ["formDataChange"] }], validationErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationErrors", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], isSaving: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSaving", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], cancel: [{ type: i0.Output, args: ["cancel"] }] } });
|
|
1088
|
+
args: [{ selector: 'spark-po-form', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, FormsModule, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsGridColDirective, BsColFormLabelDirective, BsButtonTypeDirective, BsInputGroupComponent, BsSelectComponent, BsSelectOption, BsModalHostComponent, BsModalDirective, BsModalHeaderDirective, BsModalBodyDirective, BsModalFooterDirective, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsTableComponent, BsToggleButtonComponent, BsSpinnerComponent, BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective, SparkIconComponent, SparkPoFormComponent, TranslateKeyPipe, ResolveTranslationPipe, InputTypePipe, LookupDisplayValuePipe, LookupDisplayTypePipe, LookupOptionsPipe, ReferenceDisplayValuePipe, AsDetailDisplayValuePipe, AsDetailTypePipe, AsDetailColumnsPipe, AsDetailCellValuePipe, CanCreateDetailRowPipe, CanDeleteDetailRowPipe, InlineRefOptionsPipe, ReferenceAttrValuePipe, ErrorForAttributePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-form>\n @if (entityType()) {\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"tabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #tabContent let-tab>\n @if (tab.id === '__default__') {\n @if (ungroupedAttributes().length > 0) {\n <bs-card class=\"d-block m-3\">\n <div class=\"p-3\">\n @for (attr of ungroupedAttributes(); track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card class=\"d-block m-3\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"attrField; context: { $implicit: attr }\"></ng-container>\n }\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #attrField let-attr>\n <div bsRow class=\"mb-3\">\n <label [md]=\"4\" bsColFormLabel [for]=\"attr.name\">\n {{ attr.label | resolveTranslation:attr.name }}\n @if (attr.isRequired) {\n <span class=\"text-danger\">*</span>\n }\n </label>\n <div [md]=\"8\">\n @if (attr.dataType === 'boolean') {\n <bs-toggle-button\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\">\n </bs-toggle-button>\n } @else if (attr.lookupReferenceType) {\n @if ((attr | lookupDisplayType:lookupReferenceOptions()) === ELookupDisplayType.Modal) {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | lookupDisplayValue:formData():lookupReferenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openLookupSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else {\n <bs-select\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [id]=\"attr.name\"\n [class.is-invalid]=\"hasError(attr.name)\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | lookupOptions:lookupReferenceOptions()); track option.key) {\n <option [ngValue]=\"option.key\">\n {{ option.values | resolveTranslation:option.key }}\n </option>\n }\n </bs-select>\n }\n } @else if (attr.dataType === 'Reference') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | referenceDisplayValue:formData():referenceOptions()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openReferenceSelector(attr)\">\n ...\n </button>\n </bs-input-group>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray && attr.editMode === 'inline') {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 50px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'boolean') {\n <bs-toggle-button\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n </bs-toggle-button>\n } @else if (col.dataType === 'Reference' && col.query) {\n <bs-select\n [(ngModel)]=\"row[col.name]\"\n (ngModelChange)=\"onFieldChange()\">\n <option [ngValue]=\"null\">{{ 'selectPlaceholder' | t }}</option>\n @for (option of (attr | inlineRefOptions:col:asDetailReferenceOptions()); track option.id) {\n <option [ngValue]=\"option.id\">\n {{ option.breadcrumb || option.name || option.id }}\n </option>\n }\n </bs-select>\n } @else {\n <input\n [type]=\"col.dataType | inputType\"\n [(ngModel)]=\"row[col.name]\"\n [required]=\"col.isRequired\"\n [step]=\"col.dataType === 'decimal' ? '0.01' : '1'\"\n (ngModelChange)=\"onFieldChange()\">\n }\n </td>\n }\n <td class=\"text-nowrap\">\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addInlineRow(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\" class=\"mb-1\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ col.label | resolveTranslation:col.name }}</th>\n }\n <th style=\"width: 80px\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of formData()[attr.name] || []; track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>{{ row | asDetailCellValue:attr:col:asDetailReferenceOptions() }}</td>\n }\n <td class=\"text-nowrap\">\n <button type=\"button\" class=\"btn btn-sm btn-outline-secondary me-1\" (click)=\"editArrayItem(attr, $index)\">\n <spark-icon name=\"pencil\" />\n </button>\n @if (attr | canDeleteDetailRow:asDetailPermissions()) {\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger\" (click)=\"removeArrayItem(attr, $index)\">\n <spark-icon name=\"trash\" />\n </button>\n }\n </td>\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length + 1\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\n @if (attr | canCreateDetailRow:asDetailPermissions()) {\n <button type=\"button\" [color]=\"colors.primary\" class=\"w-100 rounded-0\" (click)=\"addArrayItem(attr)\">\n <spark-icon name=\"plus\" /> {{ 'add' | t }}\n </button>\n }\n } @else if (attr.dataType === 'AsDetail') {\n <bs-input-group>\n <input\n type=\"text\"\n [id]=\"attr.name\"\n [value]=\"attr | asDetailDisplayValue:formData():asDetailTypes()\"\n readonly\n [class.is-invalid]=\"hasError(attr.name)\">\n <button\n type=\"button\"\n bsInputGroupBtn\n [color]=\"colors.secondary\"\n (click)=\"openAsDetailEditor(attr)\">\n <spark-icon name=\"pencil\" />\n </button>\n </bs-input-group>\n } @else if (getEditRendererComponent(attr); as editComp) {\n <ng-container *ngComponentOutlet=\"editComp; inputs: getEditRendererInputs(attr)\"></ng-container>\n } @else {\n <input\n [type]=\"attr.dataType | inputType\"\n [id]=\"attr.name\"\n [ngModel]=\"formData()[attr.name]\"\n (ngModelChange)=\"formData()[attr.name] = $event; onFieldChange()\"\n [name]=\"attr.name\"\n [required]=\"attr.isRequired\"\n [step]=\"attr.dataType === 'decimal' ? '0.01' : '1'\"\n [class.is-invalid]=\"hasError(attr.name)\">\n }\n @if (attr.name | errorForAttribute:validationErrors(); as errorMsg) {\n <div class=\"invalid-feedback d-block\">\n {{ errorMsg }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n\n @if (showButtons()) {\n <div bsRow class=\"mt-4\">\n <div [md]=\"4\"></div>\n <div [md]=\"8\" class=\"d-flex justify-content-end gap-2\">\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"onCancel()\" [disabled]=\"isSaving()\">{{ 'cancel' | t }}</button>\n <button type=\"submit\" [color]=\"colors.primary\" [disabled]=\"isSaving()\" (click)=\"onSave()\">\n @if (isSaving()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'save' | t }}\n </button>\n </div>\n </div>\n }\n </bs-grid>\n}\n\n<!-- Modal for editing AsDetail objects -->\n<bs-modal [isOpen]=\"showAsDetailModal()\" (isOpenChange)=\"!$event && closeAsDetailModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'edit' | t }} {{ editingAsDetailAttr()?.label | resolveTranslation:editingAsDetailAttr()?.name }}</h5>\n </div>\n\n @if (editingAsDetailAttr(); as attr) {\n <div bsModalBody>\n <spark-po-form\n [entityType]=\"attr | asDetailType:asDetailTypes()\"\n [(formData)]=\"asDetailFormData\"\n [parentId]=\"parentId()\"\n [parentType]=\"parentType()\">\n </spark-po-form>\n </div>\n }\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeAsDetailModal()\">{{ 'cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'save' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting Reference items -->\n<bs-modal [isOpen]=\"showReferenceModal()\" (isOpenChange)=\"!$event && closeReferenceModal()\">\n <div *bsModal class=\"reference-modal\">\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingReferenceAttr()?.label | resolveTranslation:editingReferenceAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n @if (referenceModalEntityType()) {\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"6\">\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)]=\"referenceSearchTerm\"\n (ngModelChange)=\"onReferenceSearchChange()\">\n @if (referenceSearchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearReferenceSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"6\" class=\"text-end\">\n @if (referenceSearchTerm && referenceModalPagination()) {\n <span class=\"text-muted\">\n {{ referenceModalPagination()!.totalRecords }} {{ referenceModalPagination()!.totalRecords === 1 ? ('resultFound' | t) : ('resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n\n <bs-datatable [(settings)]=\"referenceModalSettings\" (settingsChange)=\"applyReferenceFilter()\">\n @for (attr of referenceVisibleAttributes(); 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 referenceModalPagination()\" (click)=\"selectReferenceItem(item)\" style=\"cursor: pointer;\">\n @for (attr of referenceVisibleAttributes(); track attr.id) {\n <td>{{ item | referenceAttrValue:attr.name }}</td>\n }\n </tr>\n </bs-datatable>\n } @else {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n }\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeReferenceModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n\n<!-- Modal for selecting LookupReference items -->\n<bs-modal [isOpen]=\"showLookupModal()\" (isOpenChange)=\"!$event && closeLookupModal()\">\n <div *bsModal>\n <div bsModalHeader>\n <h5 class=\"modal-title\">{{ 'select' | t }} {{ editingLookupAttr()?.label | resolveTranslation:editingLookupAttr()?.name }}</h5>\n </div>\n\n <div bsModalBody>\n <!-- Search box -->\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [col]>\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]=\"lookupSearchTerm()\"\n (ngModelChange)=\"lookupSearchTerm.set($event)\">\n @if (lookupSearchTerm()) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"lookupSearchTerm.set('')\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n </div>\n </bs-grid>\n\n <!-- List of items -->\n <bs-table [striped]=\"true\" [hover]=\"true\">\n <tbody>\n @for (item of filteredLookupItems(); track item.key) {\n <tr\n [class.table-primary]=\"formData()[editingLookupAttr()?.name ?? ''] === item.key\"\n (click)=\"selectLookupItem(item)\"\n style=\"cursor: pointer;\">\n <td>{{ item.values | resolveTranslation:item.key }}</td>\n </tr>\n } @empty {\n <tr>\n <td class=\"text-center text-muted\">{{ 'noItemsFound' | t }}</td>\n </tr>\n }\n </tbody>\n </bs-table>\n </div>\n\n <div bsModalFooter>\n <button type=\"button\" [color]=\"colors.secondary\" (click)=\"closeLookupModal()\">{{ 'cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n" }]
|
|
1089
|
+
}], ctorParameters: () => [], propDecorators: { entityType: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityType", required: false }] }], formData: [{ type: i0.Input, args: [{ isSignal: true, alias: "formData", required: false }] }, { type: i0.Output, args: ["formDataChange"] }], validationErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationErrors", required: false }] }], showButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showButtons", required: false }] }], isSaving: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSaving", required: false }] }], parentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentId", required: false }] }], parentType: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentType", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], cancel: [{ type: i0.Output, args: ["cancel"] }] } });
|
|
994
1090
|
|
|
995
1091
|
class SparkPoCreateComponent {
|
|
996
1092
|
route = inject(ActivatedRoute);
|
|
@@ -1085,10 +1181,10 @@ class SparkPoCreateComponent {
|
|
|
1085
1181
|
this.cancelled.emit();
|
|
1086
1182
|
window.history.back();
|
|
1087
1183
|
}
|
|
1088
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1089
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
1184
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1185
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkPoCreateComponent, isStandalone: true, selector: "spark-po-create", outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @if (entityType(); as et) {\n <h2 class=\"mb-4\">{{ 'create' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage }}\n </bs-alert>\n }\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType"], outputs: ["formDataChange", "save", "cancel"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1090
1186
|
}
|
|
1091
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1187
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoCreateComponent, decorators: [{
|
|
1092
1188
|
type: Component,
|
|
1093
1189
|
args: [{ selector: 'spark-po-create', imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-container>\n<div class=\"container\">\n @if (entityType(); as et) {\n <h2 class=\"mb-4\">{{ 'create' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage }}\n </bs-alert>\n }\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n" }]
|
|
1094
1190
|
}], ctorParameters: () => [], propDecorators: { saved: [{ type: i0.Output, args: ["saved"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });
|
|
@@ -1209,12 +1305,12 @@ class SparkPoEditComponent {
|
|
|
1209
1305
|
this.cancelled.emit();
|
|
1210
1306
|
this.router.navigate(['/po', this.type, this.id]);
|
|
1211
1307
|
}
|
|
1212
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1213
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
1308
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1309
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkPoEditComponent, isStandalone: true, selector: "spark-po-edit", outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n [parentId]=\"id\"\n [parentType]=\"type\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType"], outputs: ["formDataChange", "save", "cancel"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1214
1310
|
}
|
|
1215
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1311
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoEditComponent, decorators: [{
|
|
1216
1312
|
type: Component,
|
|
1217
|
-
args: [{ selector: 'spark-po-edit', imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n" }]
|
|
1313
|
+
args: [{ selector: 'spark-po-edit', imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n [parentId]=\"id\"\n [parentType]=\"type\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n" }]
|
|
1218
1314
|
}], ctorParameters: () => [], propDecorators: { saved: [{ type: i0.Output, args: ["saved"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }] } });
|
|
1219
1315
|
|
|
1220
1316
|
var sparkPoEdit_component = /*#__PURE__*/Object.freeze({
|
|
@@ -1277,10 +1373,10 @@ class AttributeValuePipe {
|
|
|
1277
1373
|
return value != null ? String(value) : '';
|
|
1278
1374
|
});
|
|
1279
1375
|
}
|
|
1280
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1281
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
1376
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AttributeValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1377
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: AttributeValuePipe, isStandalone: true, name: "attributeValue" });
|
|
1282
1378
|
}
|
|
1283
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1379
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: AttributeValuePipe, decorators: [{
|
|
1284
1380
|
type: Pipe,
|
|
1285
1381
|
args: [{ name: 'attributeValue', standalone: true, pure: true }]
|
|
1286
1382
|
}] });
|
|
@@ -1289,10 +1385,10 @@ class RawAttributeValuePipe {
|
|
|
1289
1385
|
transform(attrName, item) {
|
|
1290
1386
|
return item?.attributes.find(a => a.name === attrName)?.value;
|
|
1291
1387
|
}
|
|
1292
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1293
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
1388
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RawAttributeValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1389
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: RawAttributeValuePipe, isStandalone: true, name: "rawAttributeValue" });
|
|
1294
1390
|
}
|
|
1295
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RawAttributeValuePipe, decorators: [{
|
|
1296
1392
|
type: Pipe,
|
|
1297
1393
|
args: [{ name: 'rawAttributeValue', standalone: true, pure: true }]
|
|
1298
1394
|
}] });
|
|
@@ -1304,10 +1400,10 @@ class ArrayValuePipe {
|
|
|
1304
1400
|
return [];
|
|
1305
1401
|
return attr.value;
|
|
1306
1402
|
}
|
|
1307
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1308
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
1403
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ArrayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1404
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: ArrayValuePipe, isStandalone: true, name: "arrayValue" });
|
|
1309
1405
|
}
|
|
1310
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1406
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ArrayValuePipe, decorators: [{
|
|
1311
1407
|
type: Pipe,
|
|
1312
1408
|
args: [{ name: 'arrayValue', standalone: true, pure: true }]
|
|
1313
1409
|
}] });
|
|
@@ -1321,10 +1417,10 @@ class ReferenceLinkRoutePipe {
|
|
|
1321
1417
|
return null;
|
|
1322
1418
|
return ['/po', targetType.alias || targetType.id, referenceId];
|
|
1323
1419
|
}
|
|
1324
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1325
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
1420
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ReferenceLinkRoutePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1421
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: ReferenceLinkRoutePipe, isStandalone: true, name: "referenceLinkRoute" });
|
|
1326
1422
|
}
|
|
1327
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1423
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: ReferenceLinkRoutePipe, decorators: [{
|
|
1328
1424
|
type: Pipe,
|
|
1329
1425
|
args: [{ name: 'referenceLinkRoute', standalone: true, pure: true }]
|
|
1330
1426
|
}] });
|
|
@@ -1473,10 +1569,10 @@ class SparkSubQueryComponent {
|
|
|
1473
1569
|
options: attr.rendererOptions,
|
|
1474
1570
|
};
|
|
1475
1571
|
}
|
|
1476
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1477
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
1572
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkSubQueryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1573
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkSubQueryComponent, isStandalone: true, selector: "spark-sub-query", inputs: { queryId: { classPropertyName: "queryId", publicName: "queryId", isSignal: true, isRequired: true, transformFunction: null }, parentId: { classPropertyName: "parentId", publicName: "parentId", isSignal: true, isRequired: true, transformFunction: null }, parentType: { classPropertyName: "parentType", publicName: "parentType", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@if (query(); as q) {\n <bs-card style=\"display: block; margin: 1rem 0;\">\n <bs-card-header>{{ (q.description | resolveTranslation) || q.name }}</bs-card-header>\n @if (loading()) {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n } @else if (q.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <div class=\"p-3 d-flex flex-column\" style=\"height: 400px;\">\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]\">\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 </div>\n }\n } @else {\n <div class=\"p-3\">\n @if (!paginationData() || paginationData()!.totalRecords === 0) {\n <div class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </div>\n } @else {\n <bs-datatable [(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]\">\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 </div>\n }\n </bs-card>\n}\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 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", 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: RouterModule }, { kind: "directive", type: i2$1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { 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: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1478
1574
|
}
|
|
1479
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1575
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkSubQueryComponent, decorators: [{
|
|
1480
1576
|
type: Component,
|
|
1481
1577
|
args: [{ selector: 'spark-sub-query', imports: [CommonModule, NgComponentOutlet, RouterModule, BsCardComponent, BsCardHeaderComponent, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsVirtualDatatableComponent, BsVirtualRowTemplateDirective, BsTableComponent, BsSpinnerComponent, ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (query(); as q) {\n <bs-card style=\"display: block; margin: 1rem 0;\">\n <bs-card-header>{{ (q.description | resolveTranslation) || q.name }}</bs-card-header>\n @if (loading()) {\n <div class=\"text-center p-3\">\n <bs-spinner />\n </div>\n } @else if (q.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <div class=\"p-3 d-flex flex-column\" style=\"height: 400px;\">\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]\">\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 </div>\n }\n } @else {\n <div class=\"p-3\">\n @if (!paginationData() || paginationData()!.totalRecords === 0) {\n <div class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </div>\n } @else {\n <bs-datatable [(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]\">\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 </div>\n }\n </bs-card>\n}\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 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" }]
|
|
1482
1578
|
}], ctorParameters: () => [], propDecorators: { queryId: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryId", required: true }] }], parentId: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentId", required: true }] }], parentType: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentType", required: true }] }] } });
|
|
@@ -1611,7 +1707,10 @@ class SparkPoDetailComponent {
|
|
|
1611
1707
|
const refCols = asDetailType.attributes.filter(a => a.dataType === 'Reference' && a.query);
|
|
1612
1708
|
if (refCols.length > 0) {
|
|
1613
1709
|
const refEntries = await Promise.all(refCols.map(async (col) => {
|
|
1614
|
-
const result = await this.sparkService.executeQueryByName(col.query
|
|
1710
|
+
const result = await this.sparkService.executeQueryByName(col.query, {
|
|
1711
|
+
parentId: this.id,
|
|
1712
|
+
parentType: this.type,
|
|
1713
|
+
});
|
|
1615
1714
|
return [col.name, result.data];
|
|
1616
1715
|
}));
|
|
1617
1716
|
this.asDetailReferenceOptions.update(prev => ({
|
|
@@ -1656,10 +1755,10 @@ class SparkPoDetailComponent {
|
|
|
1656
1755
|
onBack() {
|
|
1657
1756
|
window.history.back();
|
|
1658
1757
|
}
|
|
1659
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1660
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkPoDetailComponent, isStandalone: true, selector: "spark-po-detail", inputs: { showCustomActions: { classPropertyName: "showCustomActions", publicName: "showCustomActions", isSignal: true, isRequired: false, transformFunction: null }, extraActionsTemplate: { classPropertyName: "extraActionsTemplate", publicName: "extraActionsTemplate", isSignal: true, isRequired: false, transformFunction: null }, extraContentTemplate: { classPropertyName: "extraContentTemplate", publicName: "extraContentTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edited: "edited", deleted: "deleted", customActionExecuted: "customActionExecuted" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n } @else if (item(); as currentItem) {\n @if (entityType(); as et) {\n <div class=\"d-flex justify-content-between align-items-center mb-4\">\n <h2>{{ currentItem.breadcrumb || currentItem.name }}</h2>\n <bs-button-group>\n <button class=\"btn btn-outline-secondary\" (click)=\"onBack()\">\n <spark-icon name=\"arrow-left\" /> {{ 'back' | t }}\n </button>\n @if (canEdit()) {\n <button class=\"btn btn-primary\" (click)=\"onEdit()\">\n <spark-icon name=\"pencil\" /> {{ 'edit' | t }}\n </button>\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (canDelete()) {\n <button class=\"btn btn-danger\" (click)=\"onDelete()\">\n <spark-icon name=\"trash\" /> {{ 'delete' | t }}\n </button>\n }\n </bs-button-group>\n </div>\n\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"detailTabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #detailTabContent let-tab>\n @if (tab.id === '__default__') {\n @let ungroupedAttrs = ungroupedAttributes();\n @if (ungroupedAttrs.length > 0) {\n <bs-card style=\"display: block; margin: 1rem;\">\n <div class=\"p-3\">\n <dl bsRow>\n @for (attr of ungroupedAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"detailAttrField; context: { $implicit: attr, item: currentItem }\"></ng-container>\n }\n </dl>\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card style=\"display: block; margin: 1rem;\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n <dl bsRow>\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"detailAttrField; context: { $implicit: attr, item: currentItem }\"></ng-container>\n }\n </dl>\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #detailAttrField let-attr let-currentItem=\"item\">\n <dt [sm]=\"3\">{{ (attr.label | resolveTranslation) || attr.name }}</dt>\n <dd [sm]=\"9\">\n @if (getDetailRendererComponent(attr); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: getDetailRendererInputs(attr, currentItem)\"></ng-container>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ (col.label | resolveTranslation) || col.name }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of (attr.name | arrayValue:currentItem); track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'Reference' && col.referenceType) {\n @let route = (col.referenceType | referenceLinkRoute:row[col.name]:allEntityTypes());\n @if (route) {\n <a [routerLink]=\"route\">{{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}</a>\n } @else {\n {{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}\n }\n } @else {\n {{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\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 style=\"opacity: 1;\">\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 me-2\" [style.background-color]=\"colorVal\" style=\"width: 1.5em; height: 1.5em;\"></span>\n {{ colorVal }}\n } @else {\n -\n }\n } @else if (attr.dataType === 'Reference' && attr.referenceType) {\n @let refRoute = (attr.referenceType | referenceLinkRoute:(attr.name | rawAttributeValue:item()):allEntityTypes());\n @if (refRoute && (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes())) {\n <a [routerLink]=\"refRoute\">{{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) }}</a>\n } @else {\n {{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) || '-' }}\n }\n } @else {\n {{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) || '-' }}\n }\n </dd>\n </ng-template>\n </bs-grid>\n @if (et.queries?.length) {\n @for (queryAlias of et.queries; track queryAlias) {\n <spark-sub-query [queryId]=\"queryAlias\" [parentId]=\"currentItem.id!\" [parentType]=\"et.name\" />\n }\n }\n @if (extraContentTemplate(); as extraContentTpl) {\n <ng-container *ngTemplateOutlet=\"extraContentTpl; context: { $implicit: currentItem, entityType: et }\"></ng-container>\n }\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\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: 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: BsButtonGroupComponent, selector: "bs-button-group" }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { 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: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover"] }, { kind: "component", type: BsTabControlComponent, selector: "bs-tab-control", inputs: ["border", "restrictDragging", "selectFirstTab", "tabsPosition", "allowDragDrop"] }, { kind: "component", type: BsTabPageComponent, selector: "bs-tab-page", inputs: ["disabled"] }, { kind: "directive", type: BsTabPageHeaderDirective, selector: "[bsTabPageHeader]" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "component", type: SparkSubQueryComponent, selector: "spark-sub-query", inputs: ["queryId", "parentId", "parentType"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }, { kind: "pipe", type: RawAttributeValuePipe, name: "rawAttributeValue" }, { kind: "pipe", type: AsDetailColumnsPipe, name: "asDetailColumns" }, { kind: "pipe", type: AsDetailCellValuePipe, name: "asDetailCellValue" }, { kind: "pipe", type: ArrayValuePipe, name: "arrayValue" }, { kind: "pipe", type: ReferenceLinkRoutePipe, name: "referenceLinkRoute" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1758
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1759
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkPoDetailComponent, isStandalone: true, selector: "spark-po-detail", inputs: { showCustomActions: { classPropertyName: "showCustomActions", publicName: "showCustomActions", isSignal: true, isRequired: false, transformFunction: null }, extraActionsTemplate: { classPropertyName: "extraActionsTemplate", publicName: "extraActionsTemplate", isSignal: true, isRequired: false, transformFunction: null }, extraContentTemplate: { classPropertyName: "extraContentTemplate", publicName: "extraContentTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { edited: "edited", deleted: "deleted", customActionExecuted: "customActionExecuted" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n } @else if (item(); as currentItem) {\n @if (entityType(); as et) {\n <div class=\"d-flex justify-content-between align-items-center mb-4\">\n <h2>{{ currentItem.breadcrumb || currentItem.name }}</h2>\n <bs-button-group>\n <button class=\"btn btn-outline-secondary\" (click)=\"onBack()\">\n <spark-icon name=\"arrow-left\" /> {{ 'back' | t }}\n </button>\n @if (canEdit()) {\n <button class=\"btn btn-primary\" (click)=\"onEdit()\">\n <spark-icon name=\"pencil\" /> {{ 'edit' | t }}\n </button>\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (canDelete()) {\n <button class=\"btn btn-danger\" (click)=\"onDelete()\">\n <spark-icon name=\"trash\" /> {{ 'delete' | t }}\n </button>\n }\n </bs-button-group>\n </div>\n\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"detailTabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #detailTabContent let-tab>\n @if (tab.id === '__default__') {\n @let ungroupedAttrs = ungroupedAttributes();\n @if (ungroupedAttrs.length > 0) {\n <bs-card style=\"display: block; margin: 1rem;\">\n <div class=\"p-3\">\n <dl bsRow>\n @for (attr of ungroupedAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"detailAttrField; context: { $implicit: attr, item: currentItem }\"></ng-container>\n }\n </dl>\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card style=\"display: block; margin: 1rem;\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n <dl bsRow>\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"detailAttrField; context: { $implicit: attr, item: currentItem }\"></ng-container>\n }\n </dl>\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #detailAttrField let-attr let-currentItem=\"item\">\n <dt [sm]=\"3\">{{ (attr.label | resolveTranslation) || attr.name }}</dt>\n <dd [sm]=\"9\">\n @if (getDetailRendererComponent(attr); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: getDetailRendererInputs(attr, currentItem)\"></ng-container>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ (col.label | resolveTranslation) || col.name }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of (attr.name | arrayValue:currentItem); track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'Reference' && col.referenceType) {\n @let route = (col.referenceType | referenceLinkRoute:row[col.name]:allEntityTypes());\n @if (route) {\n <a [routerLink]=\"route\">{{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}</a>\n } @else {\n {{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}\n }\n } @else {\n {{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\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 style=\"opacity: 1;\">\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 me-2\" [style.background-color]=\"colorVal\" style=\"width: 1.5em; height: 1.5em;\"></span>\n {{ colorVal }}\n } @else {\n -\n }\n } @else if (attr.dataType === 'Reference' && attr.referenceType) {\n @let refRoute = (attr.referenceType | referenceLinkRoute:(attr.name | rawAttributeValue:item()):allEntityTypes());\n @if (refRoute && (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes())) {\n <a [routerLink]=\"refRoute\">{{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) }}</a>\n } @else {\n {{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) || '-' }}\n }\n } @else {\n {{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) || '-' }}\n }\n </dd>\n </ng-template>\n </bs-grid>\n @if (et.queries?.length) {\n @for (queryAlias of et.queries; track queryAlias) {\n <spark-sub-query [queryId]=\"queryAlias\" [parentId]=\"currentItem.id!\" [parentType]=\"et.name\" />\n }\n }\n @if (extraContentTemplate(); as extraContentTpl) {\n <ng-container *ngTemplateOutlet=\"extraContentTpl; context: { $implicit: currentItem, entityType: et }\"></ng-container>\n }\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\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: 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: BsButtonGroupComponent, selector: "bs-button-group" }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["rounded"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["noPadding"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { 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: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover"] }, { kind: "component", type: BsTabControlComponent, selector: "bs-tab-control", inputs: ["border", "restrictDragging", "selectFirstTab", "tabsPosition", "allowDragDrop"] }, { kind: "component", type: BsTabPageComponent, selector: "bs-tab-page", inputs: ["disabled"] }, { kind: "directive", type: BsTabPageHeaderDirective, selector: "[bsTabPageHeader]" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "component", type: SparkSubQueryComponent, selector: "spark-sub-query", inputs: ["queryId", "parentId", "parentType"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }, { kind: "pipe", type: RawAttributeValuePipe, name: "rawAttributeValue" }, { kind: "pipe", type: AsDetailColumnsPipe, name: "asDetailColumns" }, { kind: "pipe", type: AsDetailCellValuePipe, name: "asDetailCellValue" }, { kind: "pipe", type: ArrayValuePipe, name: "arrayValue" }, { kind: "pipe", type: ReferenceLinkRoutePipe, name: "referenceLinkRoute" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1661
1760
|
}
|
|
1662
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1761
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoDetailComponent, decorators: [{
|
|
1663
1762
|
type: Component,
|
|
1664
1763
|
args: [{ selector: 'spark-po-detail', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, RouterModule, BsAlertComponent, BsButtonGroupComponent, BsCardComponent, BsCardHeaderComponent, BsContainerComponent, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsTableComponent, BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective, BsSpinnerComponent, SparkIconComponent, SparkSubQueryComponent, ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe, RawAttributeValuePipe, AsDetailColumnsPipe, AsDetailCellValuePipe, ArrayValuePipe, ReferenceLinkRoutePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<bs-container>\n<div class=\"container\">\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n } @else if (item(); as currentItem) {\n @if (entityType(); as et) {\n <div class=\"d-flex justify-content-between align-items-center mb-4\">\n <h2>{{ currentItem.breadcrumb || currentItem.name }}</h2>\n <bs-button-group>\n <button class=\"btn btn-outline-secondary\" (click)=\"onBack()\">\n <spark-icon name=\"arrow-left\" /> {{ 'back' | t }}\n </button>\n @if (canEdit()) {\n <button class=\"btn btn-primary\" (click)=\"onEdit()\">\n <spark-icon name=\"pencil\" /> {{ 'edit' | t }}\n </button>\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (canDelete()) {\n <button class=\"btn btn-danger\" (click)=\"onDelete()\">\n <spark-icon name=\"trash\" /> {{ 'delete' | t }}\n </button>\n }\n </bs-button-group>\n </div>\n\n <bs-grid>\n <bs-tab-control>\n @for (tab of resolvedTabs(); track tab.id) {\n <bs-tab-page>\n <ng-template bsTabPageHeader>{{ tab.label | resolveTranslation:tab.name }}</ng-template>\n <ng-container *ngTemplateOutlet=\"detailTabContent; context: { $implicit: tab }\"></ng-container>\n </bs-tab-page>\n }\n </bs-tab-control>\n\n <ng-template #detailTabContent let-tab>\n @if (tab.id === '__default__') {\n @let ungroupedAttrs = ungroupedAttributes();\n @if (ungroupedAttrs.length > 0) {\n <bs-card style=\"display: block; margin: 1rem;\">\n <div class=\"p-3\">\n <dl bsRow>\n @for (attr of ungroupedAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"detailAttrField; context: { $implicit: attr, item: currentItem }\"></ng-container>\n }\n </dl>\n </div>\n </bs-card>\n }\n }\n @for (group of groupsForTab(tab); track group.id) {\n @if (attrsForGroup(group); as groupAttrs) {\n @if (groupAttrs.length > 0) {\n <bs-card style=\"display: block; margin: 1rem;\">\n @if (group.label) {\n <bs-card-header>{{ group.label | resolveTranslation:group.name }}</bs-card-header>\n }\n <div class=\"p-3\">\n <dl bsRow>\n @for (attr of groupAttrs; track attr.id) {\n <ng-container *ngTemplateOutlet=\"detailAttrField; context: { $implicit: attr, item: currentItem }\"></ng-container>\n }\n </dl>\n </div>\n </bs-card>\n }\n }\n }\n </ng-template>\n\n <ng-template #detailAttrField let-attr let-currentItem=\"item\">\n <dt [sm]=\"3\">{{ (attr.label | resolveTranslation) || attr.name }}</dt>\n <dd [sm]=\"9\">\n @if (getDetailRendererComponent(attr); as rendererType) {\n <ng-container *ngComponentOutlet=\"rendererType; inputs: getDetailRendererInputs(attr, currentItem)\"></ng-container>\n } @else if (attr.dataType === 'AsDetail' && attr.isArray) {\n <bs-table [isResponsive]=\"true\">\n <thead>\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <th>{{ (col.label | resolveTranslation) || col.name }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (row of (attr.name | arrayValue:currentItem); track $index) {\n <tr>\n @for (col of (attr | asDetailColumns:asDetailTypes()); track col.name) {\n <td>\n @if (col.dataType === 'Reference' && col.referenceType) {\n @let route = (col.referenceType | referenceLinkRoute:row[col.name]:allEntityTypes());\n @if (route) {\n <a [routerLink]=\"route\">{{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}</a>\n } @else {\n {{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}\n }\n } @else {\n {{ (row | asDetailCellValue:attr:col:asDetailReferenceOptions()) }}\n }\n </td>\n }\n </tr>\n } @empty {\n <tr>\n <td [attr.colspan]=\"(attr | asDetailColumns:asDetailTypes()).length\" class=\"text-center text-muted\">\n {{ 'noItemsFound' | t }}\n </td>\n </tr>\n }\n </tbody>\n </bs-table>\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 style=\"opacity: 1;\">\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 me-2\" [style.background-color]=\"colorVal\" style=\"width: 1.5em; height: 1.5em;\"></span>\n {{ colorVal }}\n } @else {\n -\n }\n } @else if (attr.dataType === 'Reference' && attr.referenceType) {\n @let refRoute = (attr.referenceType | referenceLinkRoute:(attr.name | rawAttributeValue:item()):allEntityTypes());\n @if (refRoute && (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes())) {\n <a [routerLink]=\"refRoute\">{{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) }}</a>\n } @else {\n {{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) || '-' }}\n }\n } @else {\n {{ (attr.name | attributeValue:item():entityType():lookupReferenceOptions():allEntityTypes()) || '-' }}\n }\n </dd>\n </ng-template>\n </bs-grid>\n @if (et.queries?.length) {\n @for (queryAlias of et.queries; track queryAlias) {\n <spark-sub-query [queryId]=\"queryAlias\" [parentId]=\"currentItem.id!\" [parentType]=\"et.name\" />\n }\n }\n @if (extraContentTemplate(); as extraContentTpl) {\n <ng-container *ngTemplateOutlet=\"extraContentTpl; context: { $implicit: currentItem, entityType: et }\"></ng-container>\n }\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n" }]
|
|
1665
1764
|
}], ctorParameters: () => [], propDecorators: { showCustomActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCustomActions", required: false }] }], extraActionsTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraActionsTemplate", required: false }] }], extraContentTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraContentTemplate", required: false }] }], edited: [{ type: i0.Output, args: ["edited"] }], deleted: [{ type: i0.Output, args: ["deleted"] }], customActionExecuted: [{ type: i0.Output, args: ["customActionExecuted"] }] } });
|
|
@@ -1673,7 +1772,9 @@ class SparkQueryListComponent {
|
|
|
1673
1772
|
route = inject(ActivatedRoute);
|
|
1674
1773
|
router = inject(Router);
|
|
1675
1774
|
sparkService = inject(SparkService);
|
|
1775
|
+
streamingService = inject(SparkStreamingService);
|
|
1676
1776
|
rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
|
|
1777
|
+
destroyRef = inject(DestroyRef);
|
|
1677
1778
|
extraActionsTemplate = input(null, ...(ngDevMode ? [{ debugName: "extraActionsTemplate" }] : []));
|
|
1678
1779
|
rowClicked = output();
|
|
1679
1780
|
createClicked = output();
|
|
@@ -1687,6 +1788,10 @@ class SparkQueryListComponent {
|
|
|
1687
1788
|
searchTerm = '';
|
|
1688
1789
|
canRead = signal(false, ...(ngDevMode ? [{ debugName: "canRead" }] : []));
|
|
1689
1790
|
canCreate = signal(false, ...(ngDevMode ? [{ debugName: "canCreate" }] : []));
|
|
1791
|
+
isStreaming = signal(false, ...(ngDevMode ? [{ debugName: "isStreaming" }] : []));
|
|
1792
|
+
streamingSub = null;
|
|
1793
|
+
allItems = signal([], ...(ngDevMode ? [{ debugName: "allItems" }] : []));
|
|
1794
|
+
filteredItems = [];
|
|
1690
1795
|
settings = signal(new DatatableSettings({
|
|
1691
1796
|
perPage: { values: [10, 25, 50], selected: 10 },
|
|
1692
1797
|
page: { values: [1], selected: 1 },
|
|
@@ -1698,6 +1803,7 @@ class SparkQueryListComponent {
|
|
|
1698
1803
|
}), ...(ngDevMode ? [{ debugName: "virtualSettings" }] : []));
|
|
1699
1804
|
constructor() {
|
|
1700
1805
|
this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));
|
|
1806
|
+
this.destroyRef.onDestroy(() => this.disconnectStreaming());
|
|
1701
1807
|
}
|
|
1702
1808
|
async onParamsChange(params) {
|
|
1703
1809
|
const queryId = params.get('queryId');
|
|
@@ -1743,7 +1849,17 @@ class SparkQueryListComponent {
|
|
|
1743
1849
|
}));
|
|
1744
1850
|
if (resolvedQuery?.renderMode === 'VirtualScrolling') {
|
|
1745
1851
|
this.virtualSettings.set(new DatatableSettings({ sortColumns: initialSortColumns }));
|
|
1746
|
-
|
|
1852
|
+
if (resolvedQuery?.isStreamingQuery) {
|
|
1853
|
+
// Streaming + VirtualScrolling: create a stable client-side data source, then connect WebSocket
|
|
1854
|
+
this.virtualDataSource.set(new VirtualDatatableDataSource((skip, take) => Promise.resolve({
|
|
1855
|
+
data: this.filteredItems.slice(skip, skip + take),
|
|
1856
|
+
totalRecords: this.filteredItems.length
|
|
1857
|
+
}), 50));
|
|
1858
|
+
this.connectStreaming(resolvedQuery.id);
|
|
1859
|
+
}
|
|
1860
|
+
else {
|
|
1861
|
+
this.initVirtualDataSource();
|
|
1862
|
+
}
|
|
1747
1863
|
}
|
|
1748
1864
|
else {
|
|
1749
1865
|
this.settings.set(new DatatableSettings({
|
|
@@ -1751,14 +1867,12 @@ class SparkQueryListComponent {
|
|
|
1751
1867
|
page: { values: [1], selected: 1 },
|
|
1752
1868
|
sortColumns: initialSortColumns
|
|
1753
1869
|
}));
|
|
1870
|
+
await this.loadItems();
|
|
1754
1871
|
}
|
|
1755
1872
|
this.loadLookupReferenceOptions();
|
|
1756
1873
|
const permissions = await this.sparkService.getPermissions(resolvedEntityType.id);
|
|
1757
1874
|
this.canRead.set(permissions.canRead);
|
|
1758
1875
|
this.canCreate.set(permissions.canCreate);
|
|
1759
|
-
if (resolvedQuery?.renderMode !== 'VirtualScrolling') {
|
|
1760
|
-
await this.loadItems();
|
|
1761
|
-
}
|
|
1762
1876
|
}
|
|
1763
1877
|
}
|
|
1764
1878
|
async resolveEntityTypeForQuery(query) {
|
|
@@ -1814,6 +1928,13 @@ class SparkQueryListComponent {
|
|
|
1814
1928
|
const currentQuery = this.query();
|
|
1815
1929
|
if (!currentQuery)
|
|
1816
1930
|
return;
|
|
1931
|
+
// Streaming queries use WebSocket instead of HTTP
|
|
1932
|
+
if (currentQuery.isStreamingQuery) {
|
|
1933
|
+
this.connectStreaming(currentQuery.id);
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
// Non-streaming: disconnect any previous streaming connection
|
|
1937
|
+
this.disconnectStreaming();
|
|
1817
1938
|
try {
|
|
1818
1939
|
const s = this.settings();
|
|
1819
1940
|
const result = await this.sparkService.executeQuery(currentQuery.id, {
|
|
@@ -1839,6 +1960,11 @@ class SparkQueryListComponent {
|
|
|
1839
1960
|
}
|
|
1840
1961
|
}
|
|
1841
1962
|
onSettingsChange() {
|
|
1963
|
+
if (this.isStreaming()) {
|
|
1964
|
+
// Streaming: sort/filter is client-side only
|
|
1965
|
+
this.applyFilter();
|
|
1966
|
+
return;
|
|
1967
|
+
}
|
|
1842
1968
|
if (this.query()?.renderMode === 'VirtualScrolling') {
|
|
1843
1969
|
this.virtualDataSource()?.reset();
|
|
1844
1970
|
this.initVirtualDataSource();
|
|
@@ -1848,6 +1974,10 @@ class SparkQueryListComponent {
|
|
|
1848
1974
|
}
|
|
1849
1975
|
}
|
|
1850
1976
|
onSearchChange() {
|
|
1977
|
+
if (this.isStreaming()) {
|
|
1978
|
+
this.applyFilter();
|
|
1979
|
+
return;
|
|
1980
|
+
}
|
|
1851
1981
|
if (this.query()?.renderMode === 'VirtualScrolling') {
|
|
1852
1982
|
this.virtualDataSource()?.reset();
|
|
1853
1983
|
this.initVirtualDataSource();
|
|
@@ -1898,14 +2028,106 @@ class SparkQueryListComponent {
|
|
|
1898
2028
|
this.router.navigate(['/po', et.alias || et.id, 'new']);
|
|
1899
2029
|
}
|
|
1900
2030
|
}
|
|
1901
|
-
|
|
1902
|
-
|
|
2031
|
+
connectStreaming(queryId) {
|
|
2032
|
+
this.disconnectStreaming();
|
|
2033
|
+
this.isStreaming.set(true);
|
|
2034
|
+
this.streamingSub = this.streamingService.connectToStreamingQuery(queryId).subscribe({
|
|
2035
|
+
next: (message) => this.handleStreamingMessage(message),
|
|
2036
|
+
error: (err) => {
|
|
2037
|
+
this.errorMessage.set(err?.message || 'Streaming connection failed');
|
|
2038
|
+
this.isStreaming.set(false);
|
|
2039
|
+
},
|
|
2040
|
+
complete: () => {
|
|
2041
|
+
this.isStreaming.set(false);
|
|
2042
|
+
}
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
2045
|
+
disconnectStreaming() {
|
|
2046
|
+
if (this.streamingSub) {
|
|
2047
|
+
this.streamingSub.unsubscribe();
|
|
2048
|
+
this.streamingSub = null;
|
|
2049
|
+
}
|
|
2050
|
+
this.isStreaming.set(false);
|
|
2051
|
+
}
|
|
2052
|
+
handleStreamingMessage(message) {
|
|
2053
|
+
switch (message.type) {
|
|
2054
|
+
case 'snapshot':
|
|
2055
|
+
this.errorMessage.set(null);
|
|
2056
|
+
this.allItems.set(message.data);
|
|
2057
|
+
this.applyFilter();
|
|
2058
|
+
break;
|
|
2059
|
+
case 'patch':
|
|
2060
|
+
if (message.updated.length > 0) {
|
|
2061
|
+
const currentItems = this.allItems();
|
|
2062
|
+
const updatedItems = currentItems.map(item => {
|
|
2063
|
+
const patch = message.updated.find(u => u.id === item.id);
|
|
2064
|
+
if (!patch)
|
|
2065
|
+
return item;
|
|
2066
|
+
// Clone the item and update only changed attribute values
|
|
2067
|
+
const updatedAttributes = item.attributes.map(attr => {
|
|
2068
|
+
if (attr.name in patch.attributes) {
|
|
2069
|
+
return { ...attr, value: patch.attributes[attr.name] };
|
|
2070
|
+
}
|
|
2071
|
+
return attr;
|
|
2072
|
+
});
|
|
2073
|
+
return { ...item, attributes: updatedAttributes };
|
|
2074
|
+
});
|
|
2075
|
+
this.allItems.set(updatedItems);
|
|
2076
|
+
this.applyFilter();
|
|
2077
|
+
}
|
|
2078
|
+
break;
|
|
2079
|
+
case 'error':
|
|
2080
|
+
this.errorMessage.set(message.message);
|
|
2081
|
+
break;
|
|
2082
|
+
}
|
|
2083
|
+
}
|
|
2084
|
+
applyFilter() {
|
|
2085
|
+
let items = this.allItems();
|
|
2086
|
+
// Apply search filter
|
|
2087
|
+
if (this.searchTerm) {
|
|
2088
|
+
const term = this.searchTerm.toLowerCase();
|
|
2089
|
+
items = items.filter(item => item.attributes.some(a => String(a.value ?? '').toLowerCase().includes(term)));
|
|
2090
|
+
}
|
|
2091
|
+
// Apply sorting
|
|
2092
|
+
const isVirtual = this.query()?.renderMode === 'VirtualScrolling';
|
|
2093
|
+
const sortCols = isVirtual ? this.virtualSettings().sortColumns : this.settings().sortColumns;
|
|
2094
|
+
if (sortCols.length > 0) {
|
|
2095
|
+
items = [...items].sort((a, b) => {
|
|
2096
|
+
for (const col of sortCols) {
|
|
2097
|
+
const aVal = a.attributes.find(attr => attr.name === col.property)?.value ?? '';
|
|
2098
|
+
const bVal = b.attributes.find(attr => attr.name === col.property)?.value ?? '';
|
|
2099
|
+
const cmp = String(aVal).localeCompare(String(bVal));
|
|
2100
|
+
if (cmp !== 0)
|
|
2101
|
+
return col.direction === 'descending' ? -cmp : cmp;
|
|
2102
|
+
}
|
|
2103
|
+
return 0;
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
if (isVirtual) {
|
|
2107
|
+
// Update the mutable filtered items array.
|
|
2108
|
+
// The stable data source's fetchFn closure reads from this.filteredItems,
|
|
2109
|
+
// so clearing its cache and emitting empty triggers the CDK viewport to re-fetch.
|
|
2110
|
+
this.filteredItems = items;
|
|
2111
|
+
this.virtualDataSource()?.reset();
|
|
2112
|
+
}
|
|
2113
|
+
else {
|
|
2114
|
+
this.paginationData.set({
|
|
2115
|
+
data: items,
|
|
2116
|
+
totalRecords: items.length,
|
|
2117
|
+
totalPages: 1,
|
|
2118
|
+
perPage: items.length,
|
|
2119
|
+
page: 1
|
|
2120
|
+
});
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkQueryListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2124
|
+
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 || ('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
2125
|
}
|
|
1904
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
2126
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkQueryListComponent, decorators: [{
|
|
1905
2127
|
type: Component,
|
|
1906
2128
|
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
2129
|
'[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
|
|
2130
|
+
}, 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
2131
|
}], 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
2132
|
|
|
1911
2133
|
var sparkQueryList_component = /*#__PURE__*/Object.freeze({
|
|
@@ -1927,8 +2149,8 @@ class SparkRetryActionModalComponent {
|
|
|
1927
2149
|
persistentObject: payload.persistentObject
|
|
1928
2150
|
});
|
|
1929
2151
|
}
|
|
1930
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1931
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
2152
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkRetryActionModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2153
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkRetryActionModalComponent, isStandalone: true, selector: "spark-retry-action-modal", ngImport: i0, template: `
|
|
1932
2154
|
<bs-modal [isOpen]="isOpen()" (isOpenChange)="!$event && onOption('Cancel')">
|
|
1933
2155
|
<div *bsModal>
|
|
1934
2156
|
<div bsModalHeader>
|
|
@@ -1953,7 +2175,7 @@ class SparkRetryActionModalComponent {
|
|
|
1953
2175
|
</bs-modal>
|
|
1954
2176
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsModalHostComponent, selector: "bs-modal", inputs: ["isOpen", "closeOnEscape"], outputs: ["isOpenChange"] }, { kind: "directive", type: BsModalDirective, selector: "[bsModal]" }, { kind: "directive", type: BsModalHeaderDirective, selector: "[bsModalHeader]" }, { kind: "directive", type: BsModalBodyDirective, selector: "[bsModalBody]" }, { kind: "directive", type: BsModalFooterDirective, selector: "[bsModalFooter]" }, { kind: "directive", type: BsButtonTypeDirective, selector: "button[color],input[type=\"button\"][color],input[type=\"submit\"][color],a[color]", inputs: ["color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1955
2177
|
}
|
|
1956
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
2178
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkRetryActionModalComponent, decorators: [{
|
|
1957
2179
|
type: Component,
|
|
1958
2180
|
args: [{
|
|
1959
2181
|
selector: 'spark-retry-action-modal',
|
|
@@ -1996,10 +2218,10 @@ class RouterLinkPipe {
|
|
|
1996
2218
|
}
|
|
1997
2219
|
return ['/'];
|
|
1998
2220
|
}
|
|
1999
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
2000
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
2221
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RouterLinkPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2222
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: RouterLinkPipe, isStandalone: true, name: "routerLink" });
|
|
2001
2223
|
}
|
|
2002
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
2224
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: RouterLinkPipe, decorators: [{
|
|
2003
2225
|
type: Pipe,
|
|
2004
2226
|
args: [{ name: 'routerLink', standalone: true, pure: true }]
|
|
2005
2227
|
}] });
|
|
@@ -2010,10 +2232,10 @@ class IconNamePipe {
|
|
|
2010
2232
|
// Strip 'bi-' prefix if present
|
|
2011
2233
|
return iconClass.startsWith('bi-') ? iconClass.substring(3) : iconClass;
|
|
2012
2234
|
}
|
|
2013
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
2014
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.
|
|
2235
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: IconNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
2236
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.1.6", ngImport: i0, type: IconNamePipe, isStandalone: true, name: "iconName" });
|
|
2015
2237
|
}
|
|
2016
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
2238
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: IconNamePipe, decorators: [{
|
|
2017
2239
|
type: Pipe,
|
|
2018
2240
|
args: [{ name: 'iconName', standalone: true, pure: true }]
|
|
2019
2241
|
}] });
|
|
@@ -2056,5 +2278,5 @@ function provideSpark(config) {
|
|
|
2056
2278
|
* Generated bundle index. Do not edit.
|
|
2057
2279
|
*/
|
|
2058
2280
|
|
|
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 };
|
|
2281
|
+
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
2282
|
//# sourceMappingURL=mintplayer-ng-spark.mjs.map
|