@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.0.6", ngImport: i0, type: RetryActionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
89
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: RetryActionService, providedIn: 'root' });
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.0.6", ngImport: i0, type: RetryActionService, decorators: [{
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.0.6", ngImport: i0, type: SparkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
234
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkService, providedIn: 'root' });
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.0.6", ngImport: i0, type: SparkService, decorators: [{
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.0.6", ngImport: i0, type: SparkLanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
281
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkLanguageService, providedIn: 'root' });
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.0.6", ngImport: i0, type: SparkLanguageService, decorators: [{
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.0.6", ngImport: i0, type: TranslateKeyPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
294
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: TranslateKeyPipe, isStandalone: true, name: "t", pure: false });
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.0.6", ngImport: i0, type: TranslateKeyPipe, decorators: [{
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.0.6", ngImport: i0, type: ResolveTranslationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
306
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ResolveTranslationPipe, isStandalone: true, name: "resolveTranslation", pure: false });
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.0.6", ngImport: i0, type: ResolveTranslationPipe, decorators: [{
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.0.6", ngImport: i0, type: InputTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
332
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: InputTypePipe, isStandalone: true, name: "inputType" });
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.0.6", ngImport: i0, type: InputTypePipe, decorators: [{
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.0.6", ngImport: i0, type: LookupDisplayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
352
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LookupDisplayValuePipe, isStandalone: true, name: "lookupDisplayValue" });
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.0.6", ngImport: i0, type: LookupDisplayValuePipe, decorators: [{
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.0.6", ngImport: i0, type: LookupDisplayTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
365
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LookupDisplayTypePipe, isStandalone: true, name: "lookupDisplayType" });
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.0.6", ngImport: i0, type: LookupDisplayTypePipe, decorators: [{
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.0.6", ngImport: i0, type: LookupOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
378
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LookupOptionsPipe, isStandalone: true, name: "lookupOptions" });
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.0.6", ngImport: i0, type: LookupOptionsPipe, decorators: [{
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.0.6", ngImport: i0, type: ReferenceDisplayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
396
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ReferenceDisplayValuePipe, isStandalone: true, name: "referenceDisplayValue" });
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.0.6", ngImport: i0, type: ReferenceDisplayValuePipe, decorators: [{
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.0.6", ngImport: i0, type: AsDetailDisplayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
435
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: AsDetailDisplayValuePipe, isStandalone: true, name: "asDetailDisplayValue" });
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.0.6", ngImport: i0, type: AsDetailDisplayValuePipe, decorators: [{
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.0.6", ngImport: i0, type: AsDetailTypePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
447
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: AsDetailTypePipe, isStandalone: true, name: "asDetailType" });
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.0.6", ngImport: i0, type: AsDetailTypePipe, decorators: [{
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.0.6", ngImport: i0, type: AsDetailColumnsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
464
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: AsDetailColumnsPipe, isStandalone: true, name: "asDetailColumns" });
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.0.6", ngImport: i0, type: AsDetailColumnsPipe, decorators: [{
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.0.6", ngImport: i0, type: AsDetailCellValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
490
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: AsDetailCellValuePipe, isStandalone: true, name: "asDetailCellValue" });
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.0.6", ngImport: i0, type: AsDetailCellValuePipe, decorators: [{
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.0.6", ngImport: i0, type: CanCreateDetailRowPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
503
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: CanCreateDetailRowPipe, isStandalone: true, name: "canCreateDetailRow" });
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.0.6", ngImport: i0, type: CanCreateDetailRowPipe, decorators: [{
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.0.6", ngImport: i0, type: CanDeleteDetailRowPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
516
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: CanDeleteDetailRowPipe, isStandalone: true, name: "canDeleteDetailRow" });
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.0.6", ngImport: i0, type: CanDeleteDetailRowPipe, decorators: [{
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.0.6", ngImport: i0, type: InlineRefOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
528
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: InlineRefOptionsPipe, isStandalone: true, name: "inlineRefOptions" });
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.0.6", ngImport: i0, type: InlineRefOptionsPipe, decorators: [{
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.0.6", ngImport: i0, type: ReferenceAttrValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
545
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ReferenceAttrValuePipe, isStandalone: true, name: "referenceAttrValue" });
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.0.6", ngImport: i0, type: ReferenceAttrValuePipe, decorators: [{
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.0.6", ngImport: i0, type: ErrorForAttributePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
558
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ErrorForAttributePipe, isStandalone: true, name: "errorForAttribute" });
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.0.6", ngImport: i0, type: ErrorForAttributePipe, decorators: [{
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.0.6", ngImport: i0, type: SparkIconRegistry, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
594
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkIconRegistry, providedIn: 'root' });
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.0.6", ngImport: i0, type: SparkIconRegistry, decorators: [{
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.0.6", ngImport: i0, type: SparkIconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
607
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkIconComponent, isStandalone: true, selector: "spark-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
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.0.6", ngImport: i0, type: SparkIconComponent, decorators: [{
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.0.6", ngImport: i0, type: SparkPoFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
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.0.6", ngImport: i0, type: SparkPoFormComponent, decorators: [{
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.0.6", ngImport: i0, type: SparkPoCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1089
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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"], outputs: ["formDataChange", "save", "cancel"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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.0.6", ngImport: i0, type: SparkPoCreateComponent, decorators: [{
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.0.6", ngImport: i0, type: SparkPoEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1213
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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 (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"], outputs: ["formDataChange", "save", "cancel"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
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.0.6", ngImport: i0, type: SparkPoEditComponent, decorators: [{
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.0.6", ngImport: i0, type: AttributeValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1281
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: AttributeValuePipe, isStandalone: true, name: "attributeValue" });
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.0.6", ngImport: i0, type: AttributeValuePipe, decorators: [{
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.0.6", ngImport: i0, type: RawAttributeValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1293
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: RawAttributeValuePipe, isStandalone: true, name: "rawAttributeValue" });
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.0.6", ngImport: i0, type: RawAttributeValuePipe, decorators: [{
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.0.6", ngImport: i0, type: ArrayValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1308
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ArrayValuePipe, isStandalone: true, name: "arrayValue" });
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.0.6", ngImport: i0, type: ArrayValuePipe, decorators: [{
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.0.6", ngImport: i0, type: ReferenceLinkRoutePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
1325
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ReferenceLinkRoutePipe, isStandalone: true, name: "referenceLinkRoute" });
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.0.6", ngImport: i0, type: ReferenceLinkRoutePipe, decorators: [{
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.0.6", ngImport: i0, type: SparkSubQueryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1477
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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 &nbsp;\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 });
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 &nbsp;\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.0.6", ngImport: i0, type: SparkSubQueryComponent, decorators: [{
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 &nbsp;\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.0.6", ngImport: i0, type: SparkPoDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
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.0.6", ngImport: i0, type: SparkPoDetailComponent, decorators: [{
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
- this.initVirtualDataSource();
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
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SparkQueryListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1902
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkQueryListComponent, isStandalone: true, selector: "spark-query-list", inputs: { extraActionsTemplate: { classPropertyName: "extraActionsTemplate", publicName: "extraActionsTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClicked: "rowClicked", createClicked: "createClicked" }, host: { properties: { "class.virtual-scrolling": "isVirtualScrolling()" } }, ngImport: i0, template: "<div class=\"d-flex flex-column h-100\">\n <!-- Title + Actions row -->\n <div class=\"d-flex justify-content-between align-items-center mb-4 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <h2>{{ (query()?.description | resolveTranslation) || query()?.name || ('loading' | t) }}</h2>\n <div class=\"d-flex gap-2\">\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (canCreate()) {\n <button class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'new' | t }}\n </button>\n }\n </div>\n </div>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && paginationData()) {\n <span class=\"text-muted\">\n {{ paginationData()!.totalRecords }} {{ paginationData()!.totalRecords === 1 ? ('resultFound' | t) : ('resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (query()?.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <bs-virtual-datatable class=\"flex-grow-1 overflow-hidden\"\n [(settings)]=\"virtualSettings\"\n [dataSource]=\"vds\"\n [isResponsive]=\"true\"\n (settingsChange)=\"onSettingsChange()\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-template bsVirtualRowTemplate let-item>\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (item) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, item.id]\" (click)=\"rowClicked.emit(item)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n }\n } @else {\n &nbsp;\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 });
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 &nbsp;\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.0.6", ngImport: i0, type: SparkQueryListComponent, decorators: [{
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>{{ (query()?.description | resolveTranslation) || query()?.name || ('loading' | t) }}</h2>\n <div class=\"d-flex gap-2\">\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (canCreate()) {\n <button class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'new' | t }}\n </button>\n }\n </div>\n </div>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && paginationData()) {\n <span class=\"text-muted\">\n {{ paginationData()!.totalRecords }} {{ paginationData()!.totalRecords === 1 ? ('resultFound' | t) : ('resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (query()?.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <bs-virtual-datatable class=\"flex-grow-1 overflow-hidden\"\n [(settings)]=\"virtualSettings\"\n [dataSource]=\"vds\"\n [isResponsive]=\"true\"\n (settingsChange)=\"onSettingsChange()\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-template bsVirtualRowTemplate let-item>\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (item) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, item.id]\" (click)=\"rowClicked.emit(item)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n }\n } @else {\n &nbsp;\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"] }]
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 &nbsp;\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.0.6", ngImport: i0, type: SparkRetryActionModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1931
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: SparkRetryActionModalComponent, isStandalone: true, selector: "spark-retry-action-modal", ngImport: i0, template: `
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.0.6", ngImport: i0, type: SparkRetryActionModalComponent, decorators: [{
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.0.6", ngImport: i0, type: RouterLinkPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2000
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: RouterLinkPipe, isStandalone: true, name: "routerLink" });
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.0.6", ngImport: i0, type: RouterLinkPipe, decorators: [{
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.0.6", ngImport: i0, type: IconNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2014
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: IconNamePipe, isStandalone: true, name: "iconName" });
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.0.6", ngImport: i0, type: IconNamePipe, decorators: [{
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