@mintplayer/ng-spark 0.4.0 → 22.0.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.
Files changed (29) hide show
  1. package/fesm2022/mintplayer-ng-spark-client-operations.mjs +22 -10
  2. package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
  3. package/fesm2022/mintplayer-ng-spark-icon.mjs +9 -6
  4. package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -1
  5. package/fesm2022/mintplayer-ng-spark-pipes.mjs +66 -66
  6. package/fesm2022/mintplayer-ng-spark-po-create.mjs +17 -10
  7. package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -1
  8. package/fesm2022/mintplayer-ng-spark-po-detail.mjs +96 -91
  9. package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
  10. package/fesm2022/mintplayer-ng-spark-po-edit.mjs +17 -10
  11. package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -1
  12. package/fesm2022/mintplayer-ng-spark-po-form.mjs +71 -36
  13. package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -1
  14. package/fesm2022/mintplayer-ng-spark-query-list.mjs +111 -126
  15. package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -1
  16. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +10 -7
  17. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -1
  18. package/fesm2022/mintplayer-ng-spark-services.mjs +48 -20
  19. package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
  20. package/package.json +8 -7
  21. package/types/mintplayer-ng-spark-client-operations.d.ts +11 -0
  22. package/types/mintplayer-ng-spark-icon.d.ts +1 -1
  23. package/types/mintplayer-ng-spark-po-create.d.ts +1 -1
  24. package/types/mintplayer-ng-spark-po-detail.d.ts +12 -15
  25. package/types/mintplayer-ng-spark-po-edit.d.ts +2 -2
  26. package/types/mintplayer-ng-spark-po-form.d.ts +10 -9
  27. package/types/mintplayer-ng-spark-query-list.d.ts +16 -14
  28. package/types/mintplayer-ng-spark-retry-action-modal.d.ts +1 -1
  29. package/types/mintplayer-ng-spark-services.d.ts +26 -2
@@ -1 +1 @@
1
- {"version":3,"file":"mintplayer-ng-spark-po-create.mjs","sources":["../../po-create/src/spark-po-create.component.ts","../../po-create/src/spark-po-create.component.html","../../po-create/mintplayer-ng-spark-po-create.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, output, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { CommonModule } from '@angular/common';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsContainerComponent } from '@mintplayer/ng-bootstrap/container';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SparkService } from '@mintplayer/ng-spark/services';\nimport { SparkPoFormComponent } from '@mintplayer/ng-spark/po-form';\nimport { TranslateKeyPipe, ResolveTranslationPipe } from '@mintplayer/ng-spark/pipes';\nimport {\n EntityType,\n PersistentObject,\n PersistentObjectAttribute,\n ValidationError,\n ShowedOn,\n hasShowedOnFlag,\n dictToNestedPo,\n EntityTypeResolver,\n} from '@mintplayer/ng-spark/models';\n\n@Component({\n selector: 'spark-po-create',\n imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe],\n templateUrl: './spark-po-create.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SparkPoCreateComponent {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly sparkService = inject(SparkService);\n\n saved = output<PersistentObject>();\n cancelled = output<void>();\n\n colors = Color;\n entityType = signal<EntityType | null>(null);\n type = signal('');\n formData = signal<Record<string, any>>({});\n validationErrors = signal<ValidationError[]>([]);\n isSaving = signal(false);\n private allEntityTypes = signal<EntityType[]>([]);\n generalErrors = computed(() => this.validationErrors().filter(e => !e.attributeName));\n\n constructor() {\n this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));\n }\n\n private async onParamsChange(params: any): Promise<void> {\n this.type.set(params.get('type') || '');\n const types = await this.sparkService.getEntityTypes();\n const entityType = types.find(t => t.id === this.type() || t.alias === this.type()) || null;\n this.entityType.set(entityType);\n this.allEntityTypes.set(types);\n this.initFormData();\n }\n\n initFormData(): void {\n const data: Record<string, any> = {};\n this.getEditableAttributes().forEach(attr => {\n if (attr.dataType === 'Reference') {\n data[attr.name] = null;\n } else if (attr.dataType === 'AsDetail') {\n data[attr.name] = attr.isArray ? [] : {};\n } else if (attr.dataType === 'boolean') {\n data[attr.name] = false;\n } else {\n data[attr.name] = '';\n }\n });\n this.formData.set(data);\n }\n\n getEditableAttributes() {\n return this.entityType()?.attributes\n .filter(a => a.isVisible && !a.isReadOnly && hasShowedOnFlag(a.showedOn, ShowedOn.PersistentObject))\n .sort((a, b) => a.order - b.order) || [];\n }\n\n async onSave(): Promise<void> {\n if (!this.entityType()) return;\n\n this.validationErrors.set([]);\n this.isSaving.set(true);\n\n const resolver: EntityTypeResolver = (clrName) => this.allEntityTypes().find(t => t.clrType === clrName);\n const attributes: PersistentObjectAttribute[] = this.getEditableAttributes().map(attr => {\n const base: PersistentObjectAttribute = {\n id: attr.id,\n name: attr.name,\n value: this.formData()[attr.name],\n dataType: attr.dataType,\n isArray: attr.isArray,\n isRequired: attr.isRequired,\n isVisible: attr.isVisible,\n isReadOnly: attr.isReadOnly,\n isValueChanged: true,\n order: attr.order,\n rules: attr.rules,\n };\n\n // AsDetail: pack the flat form dict into nested PO wire shape. Server's polymorphic\n // converter ignores attr.value for AsDetail and reads attr.object / attr.objects.\n if (attr.dataType === 'AsDetail' && attr.asDetailType) {\n const nestedType = resolver(attr.asDetailType);\n if (nestedType) {\n const raw = this.formData()[attr.name];\n base.value = null;\n base.asDetailType = attr.asDetailType;\n if (attr.isArray) {\n const items: any[] = Array.isArray(raw) ? raw : [];\n base.objects = items.map(item => dictToNestedPo((item ?? {}) as Record<string, any>, nestedType, resolver));\n base.object = null;\n } else {\n base.object = raw ? dictToNestedPo(raw as Record<string, any>, nestedType, resolver) : null;\n base.objects = null;\n }\n }\n }\n return base;\n });\n\n const po: Partial<PersistentObject> = {\n name: this.formData()['Name'] || 'New Item',\n objectTypeId: this.entityType()!.id,\n attributes\n };\n\n try {\n const result = await this.sparkService.create(this.type(), po);\n this.isSaving.set(false);\n this.saved.emit(result);\n this.router.navigate(['/po', this.type(), result.id]);\n } catch (e) {\n this.isSaving.set(false);\n const error = e as HttpErrorResponse;\n if (error.status === 400 && error.error?.errors) {\n this.validationErrors.set(error.error.errors);\n } else {\n this.validationErrors.set([{\n attributeName: '',\n errorMessage: { en: error.message || 'An unexpected error occurred' },\n ruleType: 'error'\n }]);\n }\n }\n }\n\n onCancel(): void {\n this.cancelled.emit();\n window.history.back();\n }\n}\n","<bs-container>\n<div class=\"container\">\n @if (entityType(); as et) {\n <h2 class=\"mb-4\">{{ 'common.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","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mintplayer-ng-spark-po-create.mjs","sources":["../../po-create/src/spark-po-create.component.ts","../../po-create/src/spark-po-create.component.html","../../po-create/mintplayer-ng-spark-po-create.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, output, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { CommonModule } from '@angular/common';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsContainerComponent } from '@mintplayer/ng-bootstrap/container';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SparkService } from '@mintplayer/ng-spark/services';\nimport { SparkPoFormComponent } from '@mintplayer/ng-spark/po-form';\nimport { TranslateKeyPipe, ResolveTranslationPipe } from '@mintplayer/ng-spark/pipes';\nimport {\n EntityType,\n PersistentObject,\n PersistentObjectAttribute,\n ValidationError,\n ShowedOn,\n hasShowedOnFlag,\n dictToNestedPo,\n EntityTypeResolver,\n} from '@mintplayer/ng-spark/models';\n\n@Component({\n selector: 'spark-po-create',\n imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe],\n templateUrl: './spark-po-create.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SparkPoCreateComponent {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly sparkService = inject(SparkService);\n\n saved = output<PersistentObject>();\n cancelled = output<void>();\n\n colors = Color;\n entityType = signal<EntityType | null>(null);\n type = signal('');\n formData = signal<Record<string, any>>({});\n validationErrors = signal<ValidationError[]>([]);\n isSaving = signal(false);\n private allEntityTypes = signal<EntityType[]>([]);\n generalErrors = computed(() => this.validationErrors().filter(e => !e.attributeName));\n\n constructor() {\n this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));\n }\n\n private async onParamsChange(params: any): Promise<void> {\n this.type.set(params.get('type') || '');\n const types = await this.sparkService.getEntityTypes();\n const entityType = types.find(t => t.id === this.type() || t.alias === this.type()) || null;\n this.entityType.set(entityType);\n this.allEntityTypes.set(types);\n this.initFormData();\n }\n\n initFormData(): void {\n const data: Record<string, any> = {};\n this.getEditableAttributes().forEach(attr => {\n if (attr.dataType === 'Reference') {\n data[attr.name] = null;\n } else if (attr.dataType === 'AsDetail') {\n data[attr.name] = attr.isArray ? [] : {};\n } else if (attr.dataType === 'boolean') {\n data[attr.name] = false;\n } else {\n data[attr.name] = '';\n }\n });\n this.formData.set(data);\n }\n\n getEditableAttributes() {\n return this.entityType()?.attributes\n .filter(a => a.isVisible && !a.isReadOnly && hasShowedOnFlag(a.showedOn, ShowedOn.PersistentObject))\n .sort((a, b) => a.order - b.order) || [];\n }\n\n async onSave(): Promise<void> {\n if (!this.entityType()) return;\n\n this.validationErrors.set([]);\n this.isSaving.set(true);\n\n const resolver: EntityTypeResolver = (clrName) => this.allEntityTypes().find(t => t.clrType === clrName);\n const attributes: PersistentObjectAttribute[] = this.getEditableAttributes().map(attr => {\n const base: PersistentObjectAttribute = {\n id: attr.id,\n name: attr.name,\n value: this.formData()[attr.name],\n dataType: attr.dataType,\n isArray: attr.isArray,\n isRequired: attr.isRequired,\n isVisible: attr.isVisible,\n isReadOnly: attr.isReadOnly,\n isValueChanged: true,\n order: attr.order,\n rules: attr.rules,\n };\n\n // AsDetail: pack the flat form dict into nested PO wire shape. Server's polymorphic\n // converter ignores attr.value for AsDetail and reads attr.object / attr.objects.\n if (attr.dataType === 'AsDetail' && attr.asDetailType) {\n const nestedType = resolver(attr.asDetailType);\n if (nestedType) {\n const raw = this.formData()[attr.name];\n base.value = null;\n base.asDetailType = attr.asDetailType;\n if (attr.isArray) {\n const items: any[] = Array.isArray(raw) ? raw : [];\n base.objects = items.map(item => dictToNestedPo((item ?? {}) as Record<string, any>, nestedType, resolver));\n base.object = null;\n } else {\n base.object = raw ? dictToNestedPo(raw as Record<string, any>, nestedType, resolver) : null;\n base.objects = null;\n }\n }\n }\n return base;\n });\n\n const po: Partial<PersistentObject> = {\n name: this.formData()['Name'] || 'New Item',\n objectTypeId: this.entityType()!.id,\n attributes\n };\n\n try {\n const result = await this.sparkService.create(this.type(), po);\n this.isSaving.set(false);\n this.saved.emit(result);\n this.router.navigate(['/po', this.type(), result.id]);\n } catch (e) {\n this.isSaving.set(false);\n const error = e as HttpErrorResponse;\n if (error.status === 400 && error.error?.errors) {\n this.validationErrors.set(error.error.errors);\n } else {\n this.validationErrors.set([{\n attributeName: '',\n errorMessage: { en: error.message || 'An unexpected error occurred' },\n ruleType: 'error'\n }]);\n }\n }\n }\n\n onCancel(): void {\n this.cancelled.emit();\n window.history.back();\n }\n}\n","<bs-container>\n<div class=\"container\">\n @if (entityType(); as et) {\n <h2 class=\"mb-4\">{{ 'common.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","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;;;;;;;MA6Ba,sBAAsB,CAAA;AAChB,IAAA,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC;AAC9B,IAAA,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;AACvB,IAAA,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;IAEpD,KAAK,GAAG,MAAM,EAAoB;IAClC,SAAS,GAAG,MAAM,EAAQ;IAE1B,MAAM,GAAG,KAAK;IACd,UAAU,GAAG,MAAM,CAAoB,IAAI;mFAAC;IAC5C,IAAI,GAAG,MAAM,CAAC,EAAE;6EAAC;IACjB,QAAQ,GAAG,MAAM,CAAsB,EAAE;iFAAC;IAC1C,gBAAgB,GAAG,MAAM,CAAoB,EAAE;yFAAC;IAChD,QAAQ,GAAG,MAAM,CAAC,KAAK;iFAAC;IAChB,cAAc,GAAG,MAAM,CAAe,EAAE;uFAAC;IACjD,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC;sFAAC;AAErF,IAAA,WAAA,GAAA;QACE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACjG;IAEQ,MAAM,cAAc,CAAC,MAAW,EAAA;AACtC,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE;AACtD,QAAA,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;AAC3F,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC;AAC/B,QAAA,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9B,IAAI,CAAC,YAAY,EAAE;IACrB;IAEA,YAAY,GAAA;QACV,MAAM,IAAI,GAAwB,EAAE;QACpC,IAAI,CAAC,qBAAqB,EAAE,CAAC,OAAO,CAAC,IAAI,IAAG;AAC1C,YAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW,EAAE;AACjC,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI;YACxB;AAAO,iBAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,EAAE;AACvC,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE;YAC1C;AAAO,iBAAA,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE;AACtC,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK;YACzB;iBAAO;AACL,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB;AACF,QAAA,CAAC,CAAC;AACF,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;IACzB;IAEA,qBAAqB,GAAA;AACnB,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE;aACvB,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,eAAe,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC;AAClG,aAAA,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE;IAC5C;AAEA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAAE;AAExB,QAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC7B,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;QAEvB,MAAM,QAAQ,GAAuB,CAAC,OAAO,KAAK,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC;QACxG,MAAM,UAAU,GAAgC,IAAI,CAAC,qBAAqB,EAAE,CAAC,GAAG,CAAC,IAAI,IAAG;AACtF,YAAA,MAAM,IAAI,GAA8B;gBACtC,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;gBACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,UAAU,EAAE,IAAI,CAAC,UAAU;AAC3B,gBAAA,cAAc,EAAE,IAAI;gBACpB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK,EAAE,IAAI,CAAC,KAAK;aAClB;;;YAID,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,IAAI,IAAI,CAAC,YAAY,EAAE;gBACrD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC;gBAC9C,IAAI,UAAU,EAAE;oBACd,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;AACtC,oBAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,oBAAA,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY;AACrC,oBAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AAChB,wBAAA,MAAM,KAAK,GAAU,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE;wBAClD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,cAAc,EAAE,IAAI,IAAI,EAAE,GAA0B,UAAU,EAAE,QAAQ,CAAC,CAAC;AAC3G,wBAAA,IAAI,CAAC,MAAM,GAAG,IAAI;oBACpB;yBAAO;AACL,wBAAA,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,cAAc,CAAC,GAA0B,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,IAAI;AAC3F,wBAAA,IAAI,CAAC,OAAO,GAAG,IAAI;oBACrB;gBACF;YACF;AACA,YAAA,OAAO,IAAI;AACb,QAAA,CAAC,CAAC;AAEF,QAAA,MAAM,EAAE,GAA8B;YACpC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,IAAI,UAAU;AAC3C,YAAA,YAAY,EAAE,IAAI,CAAC,UAAU,EAAG,CAAC,EAAE;YACnC;SACD;AAED,QAAA,IAAI;AACF,YAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;AAC9D,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AACxB,YAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AACvB,YAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACvD;QAAE,OAAO,CAAC,EAAE;AACV,YAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;YACxB,MAAM,KAAK,GAAG,CAAsB;AACpC,YAAA,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE;gBAC/C,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;YAC/C;iBAAO;AACL,gBAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC;AACzB,wBAAA,aAAa,EAAE,EAAE;wBACjB,YAAY,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,OAAO,IAAI,8BAA8B,EAAE;AACrE,wBAAA,QAAQ,EAAE;AACX,qBAAA,CAAC,CAAC;YACL;QACF;IACF;IAEA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;AACrB,QAAA,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;IACvB;uGA5HW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,SAAA,EAAA,WAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC7BnC,wvBA2BA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDFY,YAAY,+BAAE,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,iBAAA,EAAA,qBAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,oBAAoB,EAAA,QAAA,EAAA,cAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,kBAAkB,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,oBAAoB,EAAA,QAAA,EAAA,eAAA,EAAA,MAAA,EAAA,CAAA,YAAA,EAAA,UAAA,EAAA,kBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,UAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,gBAAA,EAAA,MAAA,EAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAE,sBAAsB,sDAAE,gBAAgB,EAAA,IAAA,EAAA,GAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAIvI,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBANlC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,WAClB,CAAC,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,gBAAgB,CAAC,EAAA,eAAA,EAElI,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,wvBAAA,EAAA;;;AE3BjD;;AAEG;;;;"}
@@ -15,40 +15,51 @@ import { BsTableComponent } from '@mintplayer/ng-bootstrap/table';
15
15
  import { BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective } from '@mintplayer/ng-bootstrap/tab-control';
16
16
  import { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';
17
17
  import { SparkService, SparkLanguageService } from '@mintplayer/ng-spark/services';
18
- import { ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe, RawAttributeValuePipe, AsDetailColumnsPipe, AsDetailCellValuePipe, ArrayValuePipe, ReferenceLinkRoutePipe } from '@mintplayer/ng-spark/pipes';
18
+ import { ResolveTranslationPipe, AttributeValuePipe, TranslateKeyPipe, RawAttributeValuePipe, AsDetailColumnsPipe, AsDetailCellValuePipe, ArrayValuePipe, ReferenceLinkRoutePipe } from '@mintplayer/ng-spark/pipes';
19
19
  import { SparkIconComponent } from '@mintplayer/ng-spark/icon';
20
20
  import { DatatableSettings, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective } from '@mintplayer/ng-bootstrap/datatable';
21
- import { VirtualDatatableDataSource, BsVirtualDatatableComponent, BsVirtualRowTemplateDirective } from '@mintplayer/ng-bootstrap/virtual-datatable';
22
21
  import { SPARK_ATTRIBUTE_RENDERERS } from '@mintplayer/ng-spark/renderers';
23
22
  import { hasShowedOnFlag, ShowedOn } from '@mintplayer/ng-spark/models';
24
23
 
25
24
  class SparkSubQueryComponent {
26
25
  sparkService = inject(SparkService);
27
26
  rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
28
- queryId = input.required(...(ngDevMode ? [{ debugName: "queryId" }] : []));
29
- parentId = input.required(...(ngDevMode ? [{ debugName: "parentId" }] : []));
30
- parentType = input.required(...(ngDevMode ? [{ debugName: "parentType" }] : []));
31
- query = signal(null, ...(ngDevMode ? [{ debugName: "query" }] : []));
32
- entityType = signal(null, ...(ngDevMode ? [{ debugName: "entityType" }] : []));
33
- allEntityTypes = signal([], ...(ngDevMode ? [{ debugName: "allEntityTypes" }] : []));
34
- paginationData = signal(undefined, ...(ngDevMode ? [{ debugName: "paginationData" }] : []));
35
- lookupReferenceOptions = signal({}, ...(ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : []));
36
- loading = signal(true, ...(ngDevMode ? [{ debugName: "loading" }] : []));
37
- canRead = signal(false, ...(ngDevMode ? [{ debugName: "canRead" }] : []));
27
+ queryId = input.required(/* @ts-ignore */
28
+ ...(ngDevMode ? [{ debugName: "queryId" }] : /* istanbul ignore next */ []));
29
+ parentId = input.required(/* @ts-ignore */
30
+ ...(ngDevMode ? [{ debugName: "parentId" }] : /* istanbul ignore next */ []));
31
+ parentType = input.required(/* @ts-ignore */
32
+ ...(ngDevMode ? [{ debugName: "parentType" }] : /* istanbul ignore next */ []));
33
+ query = signal(null, /* @ts-ignore */
34
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
35
+ entityType = signal(null, /* @ts-ignore */
36
+ ...(ngDevMode ? [{ debugName: "entityType" }] : /* istanbul ignore next */ []));
37
+ allEntityTypes = signal([], /* @ts-ignore */
38
+ ...(ngDevMode ? [{ debugName: "allEntityTypes" }] : /* istanbul ignore next */ []));
39
+ resultCount = signal(null, /* @ts-ignore */
40
+ ...(ngDevMode ? [{ debugName: "resultCount" }] : /* istanbul ignore next */ []));
41
+ lookupReferenceOptions = signal({}, /* @ts-ignore */
42
+ ...(ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : /* istanbul ignore next */ []));
43
+ loading = signal(true, /* @ts-ignore */
44
+ ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
45
+ canRead = signal(false, /* @ts-ignore */
46
+ ...(ngDevMode ? [{ debugName: "canRead" }] : /* istanbul ignore next */ []));
38
47
  settings = signal(new DatatableSettings({
39
48
  perPage: { values: [10, 25, 50], selected: 10 },
40
49
  page: { values: [1], selected: 1 },
41
50
  sortColumns: []
42
- }), ...(ngDevMode ? [{ debugName: "settings" }] : []));
43
- virtualDataSource = signal(null, ...(ngDevMode ? [{ debugName: "virtualDataSource" }] : []));
44
- virtualSettings = signal(new DatatableSettings({
45
- sortColumns: []
46
- }), ...(ngDevMode ? [{ debugName: "virtualSettings" }] : []));
51
+ }), /* @ts-ignore */
52
+ ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
53
+ fetchFn = signal(null, /* @ts-ignore */
54
+ ...(ngDevMode ? [{ debugName: "fetchFn" }] : /* istanbul ignore next */ []));
55
+ isVirtualScrolling = computed(() => this.query()?.renderMode === 'VirtualScrolling', /* @ts-ignore */
56
+ ...(ngDevMode ? [{ debugName: "isVirtualScrolling" }] : /* istanbul ignore next */ []));
47
57
  visibleAttributes = computed(() => {
48
58
  return this.entityType()?.attributes
49
59
  .filter(a => a.isVisible && hasShowedOnFlag(a.showedOn, ShowedOn.Query))
50
60
  .sort((a, b) => a.order - b.order) || [];
51
- }, ...(ngDevMode ? [{ debugName: "visibleAttributes" }] : []));
61
+ }, /* @ts-ignore */
62
+ ...(ngDevMode ? [{ debugName: "visibleAttributes" }] : /* istanbul ignore next */ []));
52
63
  constructor() {
53
64
  effect(() => {
54
65
  const qId = this.queryId();
@@ -61,6 +72,8 @@ class SparkSubQueryComponent {
61
72
  }
62
73
  async loadData(queryId, parentId, parentType) {
63
74
  this.loading.set(true);
75
+ this.resultCount.set(null);
76
+ this.fetchFn.set(null);
64
77
  try {
65
78
  const [resolvedQuery, entityTypes] = await Promise.all([
66
79
  this.sparkService.getQuery(queryId),
@@ -81,66 +94,42 @@ class SparkSubQueryComponent {
81
94
  this.canRead.set(permissions.canRead);
82
95
  }
83
96
  }
84
- if (resolvedQuery.renderMode === 'VirtualScrolling') {
85
- this.virtualSettings.set(new DatatableSettings({ sortColumns: initialSortColumns }));
86
- this.virtualDataSource.set(new VirtualDatatableDataSource((skip, take) => this.sparkService.executeQuery(resolvedQuery.id, {
87
- sortColumns: this.virtualSettings().sortColumns,
88
- skip, take,
89
- parentId, parentType,
90
- }).then(r => ({ data: r.data, totalRecords: r.totalRecords })), 50));
91
- }
92
- else {
93
- this.settings.set(new DatatableSettings({
94
- perPage: { values: [10, 25, 50], selected: 10 },
95
- page: { values: [1], selected: 1 },
96
- sortColumns: initialSortColumns
97
- }));
98
- await this.loadPage(resolvedQuery.id, parentId, parentType);
99
- }
97
+ this.settings.set(new DatatableSettings({
98
+ perPage: { values: [10, 25, 50], selected: 10 },
99
+ page: { values: [1], selected: 1 },
100
+ sortColumns: initialSortColumns
101
+ }));
102
+ // The datatable drives paging/sorting via [(settings)] and calls fetchFn
103
+ // per page. Virtual scrolling is just the [virtualScroll] template flag.
104
+ this.fetchFn.set(this.makeFetch(resolvedQuery, parentId, parentType));
100
105
  this.loadLookupReferenceOptions();
101
106
  }
102
107
  catch {
103
- this.paginationData.set(undefined);
108
+ this.fetchFn.set(null);
104
109
  }
105
110
  finally {
106
111
  this.loading.set(false);
107
112
  }
108
113
  }
109
- async loadPage(queryId, parentId, parentType) {
110
- const s = this.settings();
111
- const result = await this.sparkService.executeQuery(queryId, {
112
- sortColumns: s.sortColumns,
113
- skip: (s.page.selected - 1) * s.perPage.selected,
114
- take: s.perPage.selected,
114
+ makeFetch(query, parentId, parentType) {
115
+ return (req) => this.sparkService.executeQuery(query.id, {
116
+ sortColumns: req.sortColumns,
117
+ skip: (req.page - 1) * req.perPage,
118
+ take: req.perPage,
115
119
  parentId, parentType,
120
+ }).then(r => {
121
+ this.resultCount.set(r.totalRecords);
122
+ return {
123
+ data: r.data,
124
+ totalRecords: r.totalRecords,
125
+ totalPages: Math.ceil(r.totalRecords / req.perPage) || 1,
126
+ perPage: req.perPage,
127
+ page: req.page,
128
+ };
129
+ }).catch(() => {
130
+ this.resultCount.set(0);
131
+ return { data: [], totalRecords: 0, totalPages: 1, perPage: req.perPage, page: req.page };
116
132
  });
117
- const totalPages = Math.ceil(result.totalRecords / s.perPage.selected) || 1;
118
- this.paginationData.set({
119
- data: result.data,
120
- totalRecords: result.totalRecords,
121
- totalPages,
122
- perPage: s.perPage.selected,
123
- page: s.page.selected,
124
- });
125
- s.page.values = Array.from({ length: totalPages }, (_, i) => i + 1);
126
- }
127
- onSettingsChange() {
128
- const q = this.query();
129
- if (!q)
130
- return;
131
- if (q.renderMode === 'VirtualScrolling') {
132
- this.virtualDataSource()?.reset();
133
- const pId = this.parentId();
134
- const pType = this.parentType();
135
- this.virtualDataSource.set(new VirtualDatatableDataSource((skip, take) => this.sparkService.executeQuery(q.id, {
136
- sortColumns: this.virtualSettings().sortColumns,
137
- skip, take,
138
- parentId: pId, parentType: pType,
139
- }).then(r => ({ data: r.data, totalRecords: r.totalRecords })), 50));
140
- }
141
- else {
142
- this.loadPage(q.id, this.parentId(), this.parentType());
143
- }
144
133
  }
145
134
  async loadLookupReferenceOptions() {
146
135
  const lookupAttrs = this.visibleAttributes().filter(a => a.lookupReferenceType);
@@ -166,12 +155,12 @@ class SparkSubQueryComponent {
166
155
  options: attr.rendererOptions,
167
156
  };
168
157
  }
169
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkSubQueryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
170
- 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 {{ 'common.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.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 });
158
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SparkSubQueryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
159
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", 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 {\n <div class=\"p-3\">\n <bs-datatable\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [fetch]=\"fetchFn()\"\n [(settings)]=\"settings\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (row) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, row.id]\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n }\n } @else {\n &nbsp;\n }\n </td>\n }\n </ng-container>\n </bs-datatable>\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.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { kind: "component", type: BsDatatableComponent, selector: "bs-datatable", inputs: ["columns", "data", "fetch", "settings", "selectionMode", "selectable", "selection", "rowKey", "resizableColumns", "pagination", "virtualScroll", "itemSize", "virtualBuffer", "isResponsive", "compareWith", "tree", "idKey", "childCountKey", "treeIndent", "expandedIds", "selectionStrategy"], outputs: ["settingsChange", "selectionChange", "rowClick", "rowDblClick", "rowContextMenu", "expandedIdsChange", "rowExpand", "rowCollapse"] }, { kind: "directive", type: BsDatatableColumnDirective, selector: "[bsDatatableColumn]", inputs: ["bsDatatableColumn", "bsDatatableColumnSortable"] }, { kind: "directive", type: BsRowTemplateDirective, selector: "[bsRowTemplate]" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
171
160
  }
172
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkSubQueryComponent, decorators: [{
161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SparkSubQueryComponent, decorators: [{
173
162
  type: Component,
174
- 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 {{ 'common.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" }]
163
+ args: [{ selector: 'spark-sub-query', imports: [CommonModule, NgComponentOutlet, RouterModule, BsCardComponent, BsCardHeaderComponent, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, BsSpinnerComponent, ResolveTranslationPipe, 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 {\n <div class=\"p-3\">\n <bs-datatable\n [virtualScroll]=\"isVirtualScrolling()\"\n [itemSize]=\"40\"\n [isResponsive]=\"isVirtualScrolling()\"\n [fetch]=\"fetchFn()\"\n [(settings)]=\"settings\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-container *bsRowTemplate=\"let item\">\n @let row = $any(item);\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (row) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, row.id]\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: row, attr: attr }\"></ng-container>\n }\n } @else {\n &nbsp;\n }\n </td>\n }\n </ng-container>\n </bs-datatable>\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" }]
175
164
  }], 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 }] }] } });
176
165
 
177
166
  class SparkPoDetailComponent {
@@ -180,25 +169,38 @@ class SparkPoDetailComponent {
180
169
  sparkService = inject(SparkService);
181
170
  lang = inject(SparkLanguageService);
182
171
  rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
183
- showCustomActions = input(true, ...(ngDevMode ? [{ debugName: "showCustomActions" }] : []));
184
- extraActionsTemplate = input(null, ...(ngDevMode ? [{ debugName: "extraActionsTemplate" }] : []));
185
- extraContentTemplate = input(null, ...(ngDevMode ? [{ debugName: "extraContentTemplate" }] : []));
172
+ showCustomActions = input(true, /* @ts-ignore */
173
+ ...(ngDevMode ? [{ debugName: "showCustomActions" }] : /* istanbul ignore next */ []));
174
+ extraActionsTemplate = input(null, /* @ts-ignore */
175
+ ...(ngDevMode ? [{ debugName: "extraActionsTemplate" }] : /* istanbul ignore next */ []));
176
+ extraContentTemplate = input(null, /* @ts-ignore */
177
+ ...(ngDevMode ? [{ debugName: "extraContentTemplate" }] : /* istanbul ignore next */ []));
186
178
  edited = output();
187
179
  deleted = output();
188
180
  customActionExecuted = output();
189
181
  colors = Color;
190
- errorMessage = signal(null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
191
- entityType = signal(null, ...(ngDevMode ? [{ debugName: "entityType" }] : []));
192
- allEntityTypes = signal([], ...(ngDevMode ? [{ debugName: "allEntityTypes" }] : []));
193
- item = signal(null, ...(ngDevMode ? [{ debugName: "item" }] : []));
194
- lookupReferenceOptions = signal({}, ...(ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : []));
195
- asDetailTypes = signal({}, ...(ngDevMode ? [{ debugName: "asDetailTypes" }] : []));
196
- asDetailReferenceOptions = signal({}, ...(ngDevMode ? [{ debugName: "asDetailReferenceOptions" }] : []));
182
+ errorMessage = signal(null, /* @ts-ignore */
183
+ ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
184
+ entityType = signal(null, /* @ts-ignore */
185
+ ...(ngDevMode ? [{ debugName: "entityType" }] : /* istanbul ignore next */ []));
186
+ allEntityTypes = signal([], /* @ts-ignore */
187
+ ...(ngDevMode ? [{ debugName: "allEntityTypes" }] : /* istanbul ignore next */ []));
188
+ item = signal(null, /* @ts-ignore */
189
+ ...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
190
+ lookupReferenceOptions = signal({}, /* @ts-ignore */
191
+ ...(ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : /* istanbul ignore next */ []));
192
+ asDetailTypes = signal({}, /* @ts-ignore */
193
+ ...(ngDevMode ? [{ debugName: "asDetailTypes" }] : /* istanbul ignore next */ []));
194
+ asDetailReferenceOptions = signal({}, /* @ts-ignore */
195
+ ...(ngDevMode ? [{ debugName: "asDetailReferenceOptions" }] : /* istanbul ignore next */ []));
197
196
  type = '';
198
197
  id = '';
199
- canEdit = signal(false, ...(ngDevMode ? [{ debugName: "canEdit" }] : []));
200
- canDelete = signal(false, ...(ngDevMode ? [{ debugName: "canDelete" }] : []));
201
- customActions = signal([], ...(ngDevMode ? [{ debugName: "customActions" }] : []));
198
+ canEdit = signal(false, /* @ts-ignore */
199
+ ...(ngDevMode ? [{ debugName: "canEdit" }] : /* istanbul ignore next */ []));
200
+ canDelete = signal(false, /* @ts-ignore */
201
+ ...(ngDevMode ? [{ debugName: "canDelete" }] : /* istanbul ignore next */ []));
202
+ customActions = signal([], /* @ts-ignore */
203
+ ...(ngDevMode ? [{ debugName: "customActions" }] : /* istanbul ignore next */ []));
202
204
  constructor() {
203
205
  this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));
204
206
  }
@@ -235,13 +237,15 @@ class SparkPoDetailComponent {
235
237
  return this.entityType()?.attributes
236
238
  .filter(a => a.isVisible && hasShowedOnFlag(a.showedOn, ShowedOn.PersistentObject))
237
239
  .sort((a, b) => a.order - b.order) || [];
238
- }, ...(ngDevMode ? [{ debugName: "visibleAttributes" }] : []));
240
+ }, /* @ts-ignore */
241
+ ...(ngDevMode ? [{ debugName: "visibleAttributes" }] : /* istanbul ignore next */ []));
239
242
  static DEFAULT_TAB = { id: '__default__', name: 'Algemeen', label: { nl: 'Algemeen', en: 'General' }, order: 0 };
240
243
  ungroupedAttributes = computed(() => {
241
244
  const attrs = this.visibleAttributes();
242
245
  const groupIds = new Set((this.entityType()?.groups || []).map(g => g.id));
243
246
  return attrs.filter(a => !a.group || !groupIds.has(a.group));
244
- }, ...(ngDevMode ? [{ debugName: "ungroupedAttributes" }] : []));
247
+ }, /* @ts-ignore */
248
+ ...(ngDevMode ? [{ debugName: "ungroupedAttributes" }] : /* istanbul ignore next */ []));
245
249
  resolvedTabs = computed(() => {
246
250
  const et = this.entityType();
247
251
  const definedTabs = et?.tabs?.length ? [...et.tabs].sort((a, b) => a.order - b.order) : [];
@@ -251,7 +255,8 @@ class SparkPoDetailComponent {
251
255
  return [SparkPoDetailComponent.DEFAULT_TAB, ...definedTabs];
252
256
  }
253
257
  return definedTabs;
254
- }, ...(ngDevMode ? [{ debugName: "resolvedTabs" }] : []));
258
+ }, /* @ts-ignore */
259
+ ...(ngDevMode ? [{ debugName: "resolvedTabs" }] : /* istanbul ignore next */ []));
255
260
  groupsForTab(tab) {
256
261
  const groups = this.entityType()?.groups || [];
257
262
  if (tab.id === '__default__') {
@@ -352,10 +357,10 @@ class SparkPoDetailComponent {
352
357
  onBack() {
353
358
  window.history.back();
354
359
  }
355
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
356
- 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=\"spark-actionbar px-3 py-2\">\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n <button *bsPriorityNavItem=\"1\" class=\"btn btn-outline-secondary\" (click)=\"onBack()\">\n <spark-icon name=\"arrow-left\" /> {{ 'common.back' | t }}\n </button>\n @if (canEdit()) {\n <button *bsPriorityNavItem=\"2\" class=\"btn btn-primary\" (click)=\"onEdit()\">\n <spark-icon name=\"pencil\" /> {{ 'common.edit' | t }}\n </button>\n }\n @if (canDelete()) {\n <button *bsPriorityNavItem=\"3\" class=\"btn btn-danger\" (click)=\"onDelete()\">\n <spark-icon name=\"trash\" /> {{ 'common.delete' | t }}\n </button>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *bsPriorityNavItem=\"50\">\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n </ng-container>\n }\n </bs-priority-nav>\n </div>\n <h2>{{ currentItem.breadcrumb || currentItem.name }}</h2>\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 class=\"align-middle\">\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 {{ 'common.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", styles: [".spark-actionbar{position:sticky;top:0;z-index:400;background-color:var(--bs-tertiary-bg);border-bottom:1px solid var(--bs-border-color);margin-bottom:1rem}.spark-actionbar .btn{border-radius:0}\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.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: 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: BsPriorityNavComponent, selector: "bs-priority-nav", inputs: ["moreLabel", "moreLabelTemplate", "collapseAt", "overflowFrom", "hideEmptyMore"], outputs: ["overflowChange"] }, { kind: "directive", type: BsPriorityNavItemDirective, selector: "[bsPriorityNavItem]", inputs: ["bsPriorityNavItem", "bsPriorityNavItemHideBelow"] }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover", "border"] }, { 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 });
360
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SparkPoDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
361
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", 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=\"spark-actionbar px-3 py-2\">\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n <button *bsPriorityNavItem=\"1\" class=\"btn btn-outline-secondary\" (click)=\"onBack()\">\n <spark-icon name=\"arrow-left\" /> {{ 'common.back' | t }}\n </button>\n @if (canEdit()) {\n <button *bsPriorityNavItem=\"2\" class=\"btn btn-primary\" (click)=\"onEdit()\">\n <spark-icon name=\"pencil\" /> {{ 'common.edit' | t }}\n </button>\n }\n @if (canDelete()) {\n <button *bsPriorityNavItem=\"3\" class=\"btn btn-danger\" (click)=\"onDelete()\">\n <spark-icon name=\"trash\" /> {{ 'common.delete' | t }}\n </button>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *bsPriorityNavItem=\"50\">\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n </ng-container>\n }\n </bs-priority-nav>\n </div>\n <h2>{{ currentItem.breadcrumb || currentItem.name }}</h2>\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 class=\"align-middle\">\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 {{ 'common.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", styles: [".spark-actionbar{position:sticky;top:0;z-index:400;background-color:var(--bs-tertiary-bg);border-bottom:1px solid var(--bs-border-color);margin-bottom:1rem}.spark-actionbar .btn{border-radius:0}\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.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "browserUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsCardComponent, selector: "bs-card", inputs: ["color", "outline"] }, { kind: "component", type: BsCardHeaderComponent, selector: "bs-card-header", inputs: ["color", "navStyle"] }, { 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: BsPriorityNavComponent, selector: "bs-priority-nav", inputs: ["moreLabel", "moreLabelTemplate", "collapseAt", "overflowFrom", "hideEmptyMore", "ariaLabel"], outputs: ["overflowChange"] }, { kind: "directive", type: BsPriorityNavItemDirective, selector: "[bsPriorityNavItem]", inputs: ["bsPriorityNavItem", "bsPriorityNavItemHideBelow"] }, { kind: "component", type: BsTableComponent, selector: "bs-table", inputs: ["isResponsive", "striped", "hover", "border", "ariaRowCount"] }, { kind: "component", type: BsTabControlComponent, selector: "bs-tab-control", inputs: ["border", "selectFirstTab", "tabsPosition"] }, { 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 });
357
362
  }
358
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkPoDetailComponent, decorators: [{
363
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: SparkPoDetailComponent, decorators: [{
359
364
  type: Component,
360
365
  args: [{ selector: 'spark-po-detail', imports: [CommonModule, NgTemplateOutlet, NgComponentOutlet, RouterModule, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsContainerComponent, BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsPriorityNavComponent, BsPriorityNavItemDirective, 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=\"spark-actionbar px-3 py-2\">\n <bs-priority-nav [moreLabel]=\"lang.t('common.more')\" [collapseAt]=\"'sm'\">\n <button *bsPriorityNavItem=\"1\" class=\"btn btn-outline-secondary\" (click)=\"onBack()\">\n <spark-icon name=\"arrow-left\" /> {{ 'common.back' | t }}\n </button>\n @if (canEdit()) {\n <button *bsPriorityNavItem=\"2\" class=\"btn btn-primary\" (click)=\"onEdit()\">\n <spark-icon name=\"pencil\" /> {{ 'common.edit' | t }}\n </button>\n }\n @if (canDelete()) {\n <button *bsPriorityNavItem=\"3\" class=\"btn btn-danger\" (click)=\"onDelete()\">\n <spark-icon name=\"trash\" /> {{ 'common.delete' | t }}\n </button>\n }\n @if (showCustomActions()) {\n @for (action of customActions(); track action.name) {\n <button *bsPriorityNavItem=\"10 + action.offset\" class=\"btn btn-outline-primary\" (click)=\"onCustomAction(action)\">\n {{ action.displayName | resolveTranslation }}\n </button>\n }\n }\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *bsPriorityNavItem=\"50\">\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n </ng-container>\n }\n </bs-priority-nav>\n </div>\n <h2>{{ currentItem.breadcrumb || currentItem.name }}</h2>\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 class=\"align-middle\">\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 {{ 'common.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", styles: [".spark-actionbar{position:sticky;top:0;z-index:400;background-color:var(--bs-tertiary-bg);border-bottom:1px solid var(--bs-border-color);margin-bottom:1rem}.spark-actionbar .btn{border-radius:0}\n"] }]
361
366
  }], 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"] }] } });