@mintplayer/ng-spark 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/fesm2022/mintplayer-ng-spark-icon.mjs +35 -0
  2. package/fesm2022/mintplayer-ng-spark-icon.mjs.map +1 -0
  3. package/fesm2022/mintplayer-ng-spark-models.mjs +48 -0
  4. package/fesm2022/mintplayer-ng-spark-models.mjs.map +1 -0
  5. package/fesm2022/mintplayer-ng-spark-pipes.mjs +427 -0
  6. package/fesm2022/mintplayer-ng-spark-pipes.mjs.map +1 -0
  7. package/fesm2022/mintplayer-ng-spark-po-create.mjs +121 -0
  8. package/fesm2022/mintplayer-ng-spark-po-create.mjs.map +1 -0
  9. package/fesm2022/mintplayer-ng-spark-po-detail.mjs +368 -0
  10. package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -0
  11. package/fesm2022/mintplayer-ng-spark-po-edit.mjs +139 -0
  12. package/fesm2022/mintplayer-ng-spark-po-edit.mjs.map +1 -0
  13. package/fesm2022/mintplayer-ng-spark-po-form.mjs +393 -0
  14. package/fesm2022/mintplayer-ng-spark-po-form.mjs.map +1 -0
  15. package/fesm2022/mintplayer-ng-spark-query-list.mjs +392 -0
  16. package/fesm2022/mintplayer-ng-spark-query-list.mjs.map +1 -0
  17. package/fesm2022/mintplayer-ng-spark-renderers.mjs +25 -0
  18. package/fesm2022/mintplayer-ng-spark-renderers.mjs.map +1 -0
  19. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs +87 -0
  20. package/fesm2022/mintplayer-ng-spark-retry-action-modal.mjs.map +1 -0
  21. package/fesm2022/mintplayer-ng-spark-routes.mjs +31 -0
  22. package/fesm2022/mintplayer-ng-spark-routes.mjs.map +1 -0
  23. package/fesm2022/mintplayer-ng-spark-services.mjs +348 -0
  24. package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -0
  25. package/fesm2022/mintplayer-ng-spark.mjs +17 -2262
  26. package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
  27. package/package.json +49 -1
  28. package/types/mintplayer-ng-spark-icon.d.ts +13 -0
  29. package/types/mintplayer-ng-spark-models.d.ts +275 -0
  30. package/types/mintplayer-ng-spark-pipes.d.ts +143 -0
  31. package/types/mintplayer-ng-spark-po-create.d.ts +29 -0
  32. package/types/mintplayer-ng-spark-po-detail.d.ts +88 -0
  33. package/types/mintplayer-ng-spark-po-edit.d.ts +31 -0
  34. package/types/mintplayer-ng-spark-po-form.d.ts +84 -0
  35. package/types/mintplayer-ng-spark-query-list.d.ts +60 -0
  36. package/types/mintplayer-ng-spark-renderers.d.ts +68 -0
  37. package/types/mintplayer-ng-spark-retry-action-modal.d.ts +14 -0
  38. package/types/mintplayer-ng-spark-routes.d.ts +12 -0
  39. package/types/mintplayer-ng-spark-services.d.ts +100 -0
  40. package/types/mintplayer-ng-spark.d.ts +3 -855
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mintplayer-ng-spark-po-form.mjs","sources":["../../po-form/src/spark-po-form.component.ts","../../po-form/src/spark-po-form.component.html","../../po-form/mintplayer-ng-spark-po-form.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, inject, input, model, output, signal, effect, Type } from '@angular/core';\nimport { CommonModule, NgComponentOutlet, NgTemplateOutlet } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsGridComponent, BsGridRowDirective, BsGridColumnDirective, BsGridColDirective, BsColFormLabelDirective } from '@mintplayer/ng-bootstrap/grid';\nimport { BsInputGroupComponent } from '@mintplayer/ng-bootstrap/input-group';\nimport { BsButtonTypeDirective } from '@mintplayer/ng-bootstrap/button-type';\nimport { BsSelectComponent, BsSelectOption } from '@mintplayer/ng-bootstrap/select';\nimport { BsModalHostComponent, BsModalDirective, BsModalHeaderDirective, BsModalBodyDirective, BsModalFooterDirective } from '@mintplayer/ng-bootstrap/modal';\nimport { BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective, DatatableSettings } from '@mintplayer/ng-bootstrap/datatable';\nimport { BsToggleButtonComponent } from '@mintplayer/ng-bootstrap/toggle-button';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { BsTabControlComponent, BsTabPageComponent, BsTabPageHeaderDirective } from '@mintplayer/ng-bootstrap/tab-control';\nimport { BsTableComponent } from '@mintplayer/ng-bootstrap/table';\nimport { PaginationResponse } from '@mintplayer/pagination';\nimport { SparkService, SparkLanguageService } from '@mintplayer/ng-spark/services';\nimport {\n TranslateKeyPipe,\n ResolveTranslationPipe,\n InputTypePipe,\n LookupDisplayValuePipe,\n LookupDisplayTypePipe,\n LookupOptionsPipe,\n ReferenceDisplayValuePipe,\n AsDetailDisplayValuePipe,\n AsDetailTypePipe,\n AsDetailColumnsPipe,\n AsDetailCellValuePipe,\n CanCreateDetailRowPipe,\n CanDeleteDetailRowPipe,\n InlineRefOptionsPipe,\n ReferenceAttrValuePipe,\n ErrorForAttributePipe,\n} from '@mintplayer/ng-spark/pipes';\nimport {\n ELookupDisplayType,\n EntityPermissions,\n EntityType,\n EntityAttributeDefinition,\n AttributeTab,\n AttributeGroup,\n LookupReference,\n LookupReferenceValue,\n PersistentObject,\n PersistentObjectAttribute,\n ValidationError,\n ShowedOn,\n hasShowedOnFlag,\n resolveTranslation,\n} from '@mintplayer/ng-spark/models';\nimport { SparkIconComponent } from '@mintplayer/ng-spark/icon';\nimport { SPARK_ATTRIBUTE_RENDERERS } from '@mintplayer/ng-spark/renderers';\n\n@Component({\n selector: 'spark-po-form',\n 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],\n templateUrl: './spark-po-form.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SparkPoFormComponent {\n private readonly sparkService = inject(SparkService);\n private readonly translations = inject(SparkLanguageService);\n private readonly rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);\n\n entityType = input<EntityType | null>(null);\n formData = model<Record<string, any>>({});\n validationErrors = input<ValidationError[]>([]);\n showButtons = input(false);\n isSaving = input(false);\n parentId = input<string | undefined>(undefined);\n parentType = input<string | undefined>(undefined);\n\n save = output<void>();\n cancel = output<void>();\n\n colors = Color;\n referenceOptions = signal<Record<string, PersistentObject[]>>({});\n asDetailTypes = signal<Record<string, EntityType>>({});\n lookupReferenceOptions = signal<Record<string, LookupReference>>({});\n\n // Modal state for AsDetail object editing\n editingAsDetailAttr = signal<EntityAttributeDefinition | null>(null);\n asDetailFormData = signal<Record<string, any>>({});\n showAsDetailModal = signal(false);\n editingArrayIndex = signal<number | null>(null);\n\n // Permissions for array AsDetail entity types\n asDetailPermissions = signal<Record<string, EntityPermissions>>({});\n\n // Reference options for columns within array AsDetail types (keyed by parent attr name, then column name)\n asDetailReferenceOptions = signal<Record<string, Record<string, PersistentObject[]>>>({});\n\n // Modal state for Reference selection\n editingReferenceAttr = signal<EntityAttributeDefinition | null>(null);\n showReferenceModal = signal(false);\n referenceModalItems = signal<PersistentObject[]>([]);\n referenceModalEntityType = signal<EntityType | null>(null);\n referenceModalPagination = signal<PaginationResponse<PersistentObject> | undefined>(undefined);\n referenceModalSettings = signal(new DatatableSettings({\n perPage: { values: [10, 25, 50], selected: 10 },\n page: { values: [1], selected: 1 },\n sortColumns: []\n }));\n referenceSearchTerm = '';\n\n // Modal state for LookupReference selection (Modal display type)\n editingLookupAttr = signal<EntityAttributeDefinition | null>(null);\n showLookupModal = signal(false);\n lookupModalItems = signal<LookupReferenceValue[]>([]);\n lookupSearchTerm = signal('');\n ELookupDisplayType = ELookupDisplayType;\n\n editableAttributes = computed(() => {\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 private static readonly DEFAULT_TAB: AttributeTab = { id: '__default__', name: 'Algemeen', label: { nl: 'Algemeen', en: 'General' }, order: 0 };\n\n ungroupedAttributes = computed(() => {\n const attrs = this.editableAttributes();\n const groupIds = new Set((this.entityType()?.groups || []).map(g => g.id));\n return attrs.filter(a => !a.group || !groupIds.has(a.group));\n });\n\n resolvedTabs = computed((): AttributeTab[] => {\n const et = this.entityType();\n const definedTabs = et?.tabs?.length ? [...et.tabs].sort((a, b) => a.order - b.order) : [];\n const hasUngroupedAttrs = this.ungroupedAttributes().length > 0;\n const hasUntabbedGroups = (et?.groups || []).some(g => !g.tab);\n\n if (hasUngroupedAttrs || hasUntabbedGroups || definedTabs.length === 0) {\n return [SparkPoFormComponent.DEFAULT_TAB, ...definedTabs];\n }\n return definedTabs;\n });\n\n groupsForTab(tab: AttributeTab): AttributeGroup[] {\n const groups = this.entityType()?.groups || [];\n if (tab.id === '__default__') {\n return groups.filter(g => !g.tab).sort((a, b) => a.order - b.order);\n }\n return groups.filter(g => g.tab === tab.id).sort((a, b) => a.order - b.order);\n }\n\n attrsForGroup(group: AttributeGroup): EntityAttributeDefinition[] {\n return this.editableAttributes().filter(a => a.group === group.id);\n }\n\n referenceVisibleAttributes = computed(() => {\n return this.referenceModalEntityType()?.attributes\n .filter(a => a.isVisible)\n .sort((a, b) => a.order - b.order) || [];\n });\n\n filteredLookupItems = computed(() => {\n if (!this.lookupSearchTerm().trim()) {\n return this.lookupModalItems();\n }\n const term = this.lookupSearchTerm().toLowerCase().trim();\n return this.lookupModalItems().filter(item => {\n const translation = resolveTranslation(item.values);\n return translation.toLowerCase().includes(term) || item.key.toLowerCase().includes(term);\n });\n });\n\n constructor() {\n effect(() => {\n const et = this.entityType();\n const _pid = this.parentId();\n const _ptype = this.parentType();\n if (et) {\n this.loadReferenceOptions();\n this.loadAsDetailTypes();\n this.loadLookupReferenceOptions();\n }\n });\n }\n\n private toRecord<T>(entries: [string, T][]): Record<string, T> {\n const result: Record<string, T> = {};\n for (const [key, value] of entries) {\n result[key] = value;\n }\n return result;\n }\n\n async loadReferenceOptions(): Promise<void> {\n const refAttrs = this.editableAttributes().filter(a => a.dataType === 'Reference' && a.query);\n if (refAttrs.length === 0) return;\n\n const entries = await Promise.all(\n refAttrs.filter(a => a.query).map(async attr => {\n const result = await this.sparkService.executeQueryByName(attr.query!, {\n parentId: this.parentId(),\n parentType: this.parentType(),\n });\n return [attr.name, result.data] as [string, PersistentObject[]];\n })\n );\n this.referenceOptions.set(this.toRecord(entries));\n }\n\n async loadAsDetailTypes(): Promise<void> {\n const asDetailAttrs = this.editableAttributes().filter(a => a.dataType === 'AsDetail' && a.asDetailType);\n if (asDetailAttrs.length === 0) return;\n\n const types = await this.sparkService.getEntityTypes();\n const newAsDetailTypes: Record<string, EntityType> = {};\n\n for (const attr of asDetailAttrs) {\n const asDetailType = types.find(t => t.clrType === attr.asDetailType);\n if (asDetailType) {\n newAsDetailTypes[attr.name] = asDetailType;\n\n if (attr.isArray) {\n const perms = await this.sparkService.getPermissions(asDetailType.id);\n this.asDetailPermissions.update(prev => ({ ...prev, [attr.name]: perms }));\n\n const refCols = asDetailType.attributes.filter(a => a.dataType === 'Reference' && a.query);\n if (refCols.length > 0) {\n const refEntries = await Promise.all(\n refCols.filter(c => c.query).map(async col => {\n const result = await this.sparkService.executeQueryByName(col.query!, {\n parentId: this.parentId(),\n parentType: this.parentType(),\n });\n return [col.name, result.data] as [string, PersistentObject[]];\n })\n );\n this.asDetailReferenceOptions.update(prev => ({ ...prev, [attr.name]: this.toRecord(refEntries) }));\n }\n }\n }\n }\n this.asDetailTypes.set(newAsDetailTypes);\n }\n\n async loadLookupReferenceOptions(): Promise<void> {\n const lookupAttrs = this.editableAttributes().filter(a => a.lookupReferenceType);\n if (lookupAttrs.length === 0) return;\n\n const lookupNames = [...new Set(lookupAttrs.map(a => a.lookupReferenceType!))];\n const entries = await Promise.all(\n lookupNames.map(async name => {\n const ref = await this.sparkService.getLookupReference(name);\n return [name, ref] as [string, LookupReference];\n })\n );\n this.lookupReferenceOptions.set(this.toRecord(entries));\n }\n\n getReferenceOptions(attr: EntityAttributeDefinition): PersistentObject[] {\n return this.referenceOptions()[attr.name] || [];\n }\n\n getLookupOptions(attr: EntityAttributeDefinition): LookupReferenceValue[] {\n const lookupRef = attr.lookupReferenceType ? this.lookupReferenceOptions()[attr.lookupReferenceType] : null;\n return lookupRef?.values.filter(v => v.isActive) || [];\n }\n\n // LookupReference modal methods\n openLookupSelector(attr: EntityAttributeDefinition): void {\n this.editingLookupAttr.set(attr);\n this.lookupSearchTerm.set('');\n this.lookupModalItems.set(this.getLookupOptions(attr));\n this.showLookupModal.set(true);\n }\n\n selectLookupItem(item: LookupReferenceValue): void {\n const attr = this.editingLookupAttr();\n if (attr) {\n const data = { ...this.formData() };\n data[attr.name] = item.key;\n this.formData.set(data);\n }\n this.closeLookupModal();\n }\n\n closeLookupModal(): void {\n this.showLookupModal.set(false);\n this.editingLookupAttr.set(null);\n this.lookupModalItems.set([]);\n this.lookupSearchTerm.set('');\n }\n\n getEditRendererComponent(attr: EntityAttributeDefinition): Type<any> | null {\n if (!attr.renderer) return null;\n const reg = this.rendererRegistry.find(r => r.name === attr.renderer);\n return reg?.editComponent ?? null;\n }\n\n getEditRendererInputs(attr: EntityAttributeDefinition): Record<string, any> {\n return {\n value: this.formData()[attr.name],\n attribute: attr,\n options: attr.rendererOptions,\n valueChange: (newValue: any) => {\n const data = { ...this.formData() };\n data[attr.name] = newValue;\n this.formData.set(data);\n },\n };\n }\n\n hasError(attrName: string): boolean {\n return this.validationErrors().some(e => e.attributeName === attrName);\n }\n\n onFieldChange(): void {\n this.formData.set({ ...this.formData() });\n }\n\n onSave(): void {\n this.save.emit();\n }\n\n onCancel(): void {\n this.cancel.emit();\n }\n\n // AsDetail object modal methods\n openAsDetailEditor(attr: EntityAttributeDefinition): void {\n this.editingAsDetailAttr.set(attr);\n this.editingArrayIndex.set(null);\n this.asDetailFormData.set({ ...(this.formData()[attr.name] || {}) });\n this.showAsDetailModal.set(true);\n }\n\n saveAsDetailObject(): void {\n const attr = this.editingAsDetailAttr();\n if (attr) {\n const data = { ...this.formData() };\n if (attr.isArray) {\n const arr = [...(data[attr.name] || [])];\n const idx = this.editingArrayIndex();\n if (idx !== null) {\n arr[idx] = { ...this.asDetailFormData() };\n } else {\n arr.push({ ...this.asDetailFormData() });\n }\n data[attr.name] = arr;\n } else {\n data[attr.name] = { ...this.asDetailFormData() };\n }\n this.formData.set(data);\n }\n this.closeAsDetailModal();\n }\n\n closeAsDetailModal(): void {\n this.showAsDetailModal.set(false);\n this.editingAsDetailAttr.set(null);\n this.editingArrayIndex.set(null);\n this.asDetailFormData.set({});\n }\n\n // Inline AsDetail methods\n addInlineRow(attr: EntityAttributeDefinition): void {\n const data = { ...this.formData() };\n const arr = [...(data[attr.name] || [])];\n arr.push({});\n data[attr.name] = arr;\n this.formData.set(data);\n }\n\n // Array AsDetail methods\n addArrayItem(attr: EntityAttributeDefinition): void {\n this.editingAsDetailAttr.set(attr);\n this.editingArrayIndex.set(null);\n this.asDetailFormData.set({});\n this.showAsDetailModal.set(true);\n }\n\n editArrayItem(attr: EntityAttributeDefinition, index: number): void {\n this.editingAsDetailAttr.set(attr);\n this.editingArrayIndex.set(index);\n const arr = this.formData()[attr.name] || [];\n this.asDetailFormData.set({ ...(arr[index] || {}) });\n this.showAsDetailModal.set(true);\n }\n\n removeArrayItem(attr: EntityAttributeDefinition, index: number): void {\n const data = { ...this.formData() };\n const arr = [...(data[attr.name] || [])];\n arr.splice(index, 1);\n data[attr.name] = arr;\n this.formData.set(data);\n }\n\n // Reference modal methods\n async openReferenceSelector(attr: EntityAttributeDefinition): Promise<void> {\n this.editingReferenceAttr.set(attr);\n this.referenceSearchTerm = '';\n this.referenceModalItems.set(this.getReferenceOptions(attr));\n\n const types = await this.sparkService.getEntityTypes();\n this.referenceModalEntityType.set(types.find(t => t.clrType === attr.referenceType) || null);\n this.referenceModalSettings.set(new DatatableSettings({\n perPage: { values: [10, 25, 50], selected: 10 },\n page: { values: [1], selected: 1 },\n sortColumns: []\n }));\n this.applyReferenceFilter();\n this.showReferenceModal.set(true);\n }\n\n onReferenceSearchChange(): void {\n this.referenceModalSettings().page.selected = 1;\n this.applyReferenceFilter();\n }\n\n applyReferenceFilter(): void {\n let filteredItems = this.referenceModalItems();\n\n if (this.referenceSearchTerm.trim()) {\n const term = this.referenceSearchTerm.toLowerCase().trim();\n filteredItems = this.referenceModalItems().filter(item => {\n if (item.name?.toLowerCase().includes(term)) return true;\n if (item.breadcrumb?.toLowerCase().includes(term)) return true;\n return item.attributes.some(attr => {\n const value = attr.breadcrumb || attr.value;\n if (value == null) return false;\n return String(value).toLowerCase().includes(term);\n });\n });\n }\n\n const totalPages = Math.ceil(filteredItems.length / this.referenceModalSettings().perPage.selected) || 1;\n this.referenceModalPagination.set({\n data: filteredItems,\n totalRecords: filteredItems.length,\n totalPages: totalPages,\n perPage: this.referenceModalSettings().perPage.selected,\n page: this.referenceModalSettings().page.selected\n });\n\n this.referenceModalSettings().page.values = Array.from({ length: totalPages }, (_, i) => i + 1);\n\n if (this.referenceModalSettings().page.selected > totalPages) {\n this.referenceModalSettings().page.selected = 1;\n }\n }\n\n clearReferenceSearch(): void {\n this.referenceSearchTerm = '';\n this.onReferenceSearchChange();\n }\n\n selectReferenceItem(item: PersistentObject): void {\n const attr = this.editingReferenceAttr();\n if (attr) {\n const data = { ...this.formData() };\n data[attr.name] = item.id;\n this.formData.set(data);\n }\n this.closeReferenceModal();\n }\n\n closeReferenceModal(): void {\n this.showReferenceModal.set(false);\n this.editingReferenceAttr.set(null);\n this.referenceModalItems.set([]);\n this.referenceModalEntityType.set(null);\n this.referenceSearchTerm = '';\n }\n}\n","<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\">{{ 'common.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 class=\"align-middle\">\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\">{{ 'common.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 {{ 'common.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\" /> {{ 'common.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 class=\"align-middle\">\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 {{ 'common.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\" /> {{ 'common.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()\">{{ 'common.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 {{ 'common.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\">{{ 'common.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()\">{{ 'common.cancel' | t }}</button>\n <button type=\"button\" [color]=\"colors.primary\" (click)=\"saveAsDetailObject()\">{{ 'common.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\">{{ 'common.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]=\"'common.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 ? ('common.resultFound' | t) : ('common.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()\">{{ 'common.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\">{{ 'common.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]=\"'common.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 class=\"align-middle\">\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\">{{ 'common.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()\">{{ 'common.cancel' | t }}</button>\n </div>\n </div>\n</bs-modal>\n</bs-form>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,392 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, DestroyRef, input, output, signal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@angular/common';
5
+ import { CommonModule, NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
6
+ import * as i2 from '@angular/forms';
7
+ import { FormsModule } from '@angular/forms';
8
+ import * as i3 from '@angular/router';
9
+ import { ActivatedRoute, Router, RouterModule } from '@angular/router';
10
+ import { Color } from '@mintplayer/ng-bootstrap';
11
+ import { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';
12
+ import { DatatableSettings, BsDatatableComponent, BsDatatableColumnDirective, BsRowTemplateDirective } from '@mintplayer/ng-bootstrap/datatable';
13
+ import { VirtualDatatableDataSource, BsVirtualDatatableComponent, BsVirtualRowTemplateDirective } from '@mintplayer/ng-bootstrap/virtual-datatable';
14
+ import { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';
15
+ import { BsContainerComponent } from '@mintplayer/ng-bootstrap/container';
16
+ import { BsGridComponent, BsGridRowDirective, BsGridColumnDirective } from '@mintplayer/ng-bootstrap/grid';
17
+ import { BsInputGroupComponent } from '@mintplayer/ng-bootstrap/input-group';
18
+ import { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';
19
+ import { SparkService, SparkStreamingService } from '@mintplayer/ng-spark/services';
20
+ import { ResolveTranslationPipe, TranslateKeyPipe, AttributeValuePipe } from '@mintplayer/ng-spark/pipes';
21
+ import { SparkIconComponent } from '@mintplayer/ng-spark/icon';
22
+ import { SPARK_ATTRIBUTE_RENDERERS } from '@mintplayer/ng-spark/renderers';
23
+ import { hasShowedOnFlag, ShowedOn } from '@mintplayer/ng-spark/models';
24
+
25
+ class SparkQueryListComponent {
26
+ route = inject(ActivatedRoute);
27
+ router = inject(Router);
28
+ sparkService = inject(SparkService);
29
+ streamingService = inject(SparkStreamingService);
30
+ rendererRegistry = inject(SPARK_ATTRIBUTE_RENDERERS);
31
+ destroyRef = inject(DestroyRef);
32
+ extraActionsTemplate = input(null, ...(ngDevMode ? [{ debugName: "extraActionsTemplate" }] : []));
33
+ rowClicked = output();
34
+ createClicked = output();
35
+ colors = Color;
36
+ errorMessage = signal(null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
37
+ query = signal(null, ...(ngDevMode ? [{ debugName: "query" }] : []));
38
+ entityType = signal(null, ...(ngDevMode ? [{ debugName: "entityType" }] : []));
39
+ allEntityTypes = signal([], ...(ngDevMode ? [{ debugName: "allEntityTypes" }] : []));
40
+ lookupReferenceOptions = signal({}, ...(ngDevMode ? [{ debugName: "lookupReferenceOptions" }] : []));
41
+ paginationData = signal(undefined, ...(ngDevMode ? [{ debugName: "paginationData" }] : []));
42
+ searchTerm = '';
43
+ canRead = signal(false, ...(ngDevMode ? [{ debugName: "canRead" }] : []));
44
+ canCreate = signal(false, ...(ngDevMode ? [{ debugName: "canCreate" }] : []));
45
+ isStreaming = signal(false, ...(ngDevMode ? [{ debugName: "isStreaming" }] : []));
46
+ streamingSub = null;
47
+ allItems = signal([], ...(ngDevMode ? [{ debugName: "allItems" }] : []));
48
+ filteredItems = [];
49
+ settings = signal(new DatatableSettings({
50
+ perPage: { values: [10, 25, 50], selected: 10 },
51
+ page: { values: [1], selected: 1 },
52
+ sortColumns: []
53
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : []));
54
+ virtualDataSource = signal(null, ...(ngDevMode ? [{ debugName: "virtualDataSource" }] : []));
55
+ virtualSettings = signal(new DatatableSettings({
56
+ sortColumns: []
57
+ }), ...(ngDevMode ? [{ debugName: "virtualSettings" }] : []));
58
+ constructor() {
59
+ this.route.paramMap.pipe(takeUntilDestroyed()).subscribe(params => this.onParamsChange(params));
60
+ this.destroyRef.onDestroy(() => this.disconnectStreaming());
61
+ }
62
+ async onParamsChange(params) {
63
+ const queryId = params.get('queryId');
64
+ const typeParam = params.get('type');
65
+ let resolvedQuery = null;
66
+ let resolvedEntityType = null;
67
+ let resolvedEntityTypes = [];
68
+ if (queryId) {
69
+ resolvedQuery = await this.sparkService.getQuery(queryId);
70
+ if (resolvedQuery) {
71
+ const result = await this.resolveEntityTypeForQuery(resolvedQuery);
72
+ resolvedEntityType = result.entityType;
73
+ resolvedEntityTypes = result.entityTypes;
74
+ }
75
+ }
76
+ else if (typeParam) {
77
+ resolvedEntityTypes = await this.sparkService.getEntityTypes();
78
+ resolvedEntityType = resolvedEntityTypes.find(t => t.id === typeParam || t.alias === typeParam) || null;
79
+ if (resolvedEntityType) {
80
+ const queries = await this.sparkService.getQueries();
81
+ const singularName = resolvedEntityType.name;
82
+ resolvedQuery = queries.find(q => {
83
+ // Match by explicit entityType
84
+ if (q.entityType === singularName)
85
+ return true;
86
+ // Match by source name
87
+ const sourceName = this.extractSourceName(q.source);
88
+ const sourceSingular = this.singularize(sourceName);
89
+ return sourceName === singularName ||
90
+ sourceSingular === singularName ||
91
+ sourceName === singularName + 's';
92
+ }) || null;
93
+ }
94
+ }
95
+ if (resolvedQuery)
96
+ this.query.set(resolvedQuery);
97
+ if (resolvedEntityType) {
98
+ this.entityType.set(resolvedEntityType);
99
+ this.allEntityTypes.set(resolvedEntityTypes);
100
+ const initialSortColumns = (resolvedQuery?.sortColumns || []).map(sc => ({
101
+ property: sc.property,
102
+ direction: sc.direction === 'desc' ? 'descending' : 'ascending'
103
+ }));
104
+ if (resolvedQuery?.renderMode === 'VirtualScrolling') {
105
+ this.virtualSettings.set(new DatatableSettings({ sortColumns: initialSortColumns }));
106
+ if (resolvedQuery?.isStreamingQuery) {
107
+ // Streaming + VirtualScrolling: create a stable client-side data source, then connect WebSocket
108
+ this.virtualDataSource.set(new VirtualDatatableDataSource((skip, take) => Promise.resolve({
109
+ data: this.filteredItems.slice(skip, skip + take),
110
+ totalRecords: this.filteredItems.length
111
+ }), 50));
112
+ this.connectStreaming(resolvedQuery.id);
113
+ }
114
+ else {
115
+ this.initVirtualDataSource();
116
+ }
117
+ }
118
+ else {
119
+ this.settings.set(new DatatableSettings({
120
+ perPage: { values: [10, 25, 50], selected: 10 },
121
+ page: { values: [1], selected: 1 },
122
+ sortColumns: initialSortColumns
123
+ }));
124
+ await this.loadItems();
125
+ }
126
+ this.loadLookupReferenceOptions();
127
+ const permissions = await this.sparkService.getPermissions(resolvedEntityType.id);
128
+ this.canRead.set(permissions.canRead);
129
+ this.canCreate.set(permissions.canCreate);
130
+ }
131
+ }
132
+ async resolveEntityTypeForQuery(query) {
133
+ const entityTypes = await this.sparkService.getEntityTypes();
134
+ // If entityType is explicitly set on the query, use it directly
135
+ if (query.entityType) {
136
+ const type = entityTypes.find(t => t.name === query.entityType || t.alias === query.entityType?.toLowerCase());
137
+ return { entityType: type || null, entityTypes };
138
+ }
139
+ // For Database.X sources, extract the property name and try to match
140
+ const sourceName = this.extractSourceName(query.source);
141
+ const singularName = this.singularize(sourceName);
142
+ const type = entityTypes.find(t => t.name === sourceName ||
143
+ t.name === singularName ||
144
+ t.clrType.endsWith(singularName));
145
+ return { entityType: type || null, entityTypes };
146
+ }
147
+ extractSourceName(source) {
148
+ const dotIndex = source.indexOf('.');
149
+ return dotIndex >= 0 ? source.substring(dotIndex + 1) : source;
150
+ }
151
+ singularize(plural) {
152
+ const irregulars = {
153
+ 'People': 'Person',
154
+ 'Children': 'Child',
155
+ 'Men': 'Men',
156
+ 'Women': 'Woman'
157
+ };
158
+ if (irregulars[plural])
159
+ return irregulars[plural];
160
+ if (plural.endsWith('ies')) {
161
+ return plural.slice(0, -3) + 'y';
162
+ }
163
+ if (plural.endsWith('es')) {
164
+ return plural.slice(0, -2);
165
+ }
166
+ if (plural.endsWith('s')) {
167
+ return plural.slice(0, -1);
168
+ }
169
+ return plural;
170
+ }
171
+ initVirtualDataSource() {
172
+ const currentQuery = this.query();
173
+ if (!currentQuery)
174
+ return;
175
+ this.virtualDataSource.set(new VirtualDatatableDataSource((skip, take) => this.sparkService.executeQuery(currentQuery.id, {
176
+ sortColumns: this.virtualSettings().sortColumns,
177
+ skip, take,
178
+ search: this.searchTerm || undefined,
179
+ }).then(r => ({ data: r.data, totalRecords: r.totalRecords })), 50));
180
+ }
181
+ async loadItems() {
182
+ const currentQuery = this.query();
183
+ if (!currentQuery)
184
+ return;
185
+ // Streaming queries use WebSocket instead of HTTP
186
+ if (currentQuery.isStreamingQuery) {
187
+ this.connectStreaming(currentQuery.id);
188
+ return;
189
+ }
190
+ // Non-streaming: disconnect any previous streaming connection
191
+ this.disconnectStreaming();
192
+ try {
193
+ const s = this.settings();
194
+ const result = await this.sparkService.executeQuery(currentQuery.id, {
195
+ sortColumns: s.sortColumns,
196
+ skip: (s.page.selected - 1) * s.perPage.selected,
197
+ take: s.perPage.selected,
198
+ search: this.searchTerm || undefined,
199
+ });
200
+ this.errorMessage.set(null);
201
+ const totalPages = Math.ceil(result.totalRecords / s.perPage.selected) || 1;
202
+ this.paginationData.set({
203
+ data: result.data,
204
+ totalRecords: result.totalRecords,
205
+ totalPages: totalPages,
206
+ perPage: s.perPage.selected,
207
+ page: s.page.selected
208
+ });
209
+ s.page.values = Array.from({ length: totalPages }, (_, i) => i + 1);
210
+ }
211
+ catch (e) {
212
+ this.errorMessage.set(e.error?.error || e.message || 'An unexpected error occurred');
213
+ this.paginationData.set(undefined);
214
+ }
215
+ }
216
+ onSettingsChange() {
217
+ if (this.isStreaming()) {
218
+ // Streaming: sort/filter is client-side only
219
+ this.applyFilter();
220
+ return;
221
+ }
222
+ if (this.query()?.renderMode === 'VirtualScrolling') {
223
+ this.virtualDataSource()?.reset();
224
+ this.initVirtualDataSource();
225
+ }
226
+ else {
227
+ this.loadItems();
228
+ }
229
+ }
230
+ onSearchChange() {
231
+ if (this.isStreaming()) {
232
+ this.applyFilter();
233
+ return;
234
+ }
235
+ if (this.query()?.renderMode === 'VirtualScrolling') {
236
+ this.virtualDataSource()?.reset();
237
+ this.initVirtualDataSource();
238
+ }
239
+ else {
240
+ this.settings().page.selected = 1;
241
+ this.loadItems();
242
+ }
243
+ }
244
+ clearSearch() {
245
+ this.searchTerm = '';
246
+ this.onSearchChange();
247
+ }
248
+ isVirtualScrolling = computed(() => this.query()?.renderMode === 'VirtualScrolling', ...(ngDevMode ? [{ debugName: "isVirtualScrolling" }] : []));
249
+ visibleAttributes = computed(() => {
250
+ return this.entityType()?.attributes
251
+ .filter(a => a.isVisible && hasShowedOnFlag(a.showedOn, ShowedOn.Query))
252
+ .sort((a, b) => a.order - b.order) || [];
253
+ }, ...(ngDevMode ? [{ debugName: "visibleAttributes" }] : []));
254
+ getColumnRendererComponent(attr) {
255
+ if (!attr.renderer)
256
+ return null;
257
+ return this.rendererRegistry.find(r => r.name === attr.renderer)?.columnComponent ?? null;
258
+ }
259
+ getColumnRendererInputs(item, attr) {
260
+ const itemAttr = item.attributes.find(a => a.name === attr.name);
261
+ return {
262
+ value: itemAttr?.value,
263
+ attribute: attr,
264
+ options: attr.rendererOptions,
265
+ };
266
+ }
267
+ async loadLookupReferenceOptions() {
268
+ const lookupAttrs = this.visibleAttributes().filter(a => a.lookupReferenceType);
269
+ if (lookupAttrs.length === 0)
270
+ return;
271
+ const lookupNames = [...new Set(lookupAttrs.map(a => a.lookupReferenceType))];
272
+ const entries = await Promise.all(lookupNames.map(async (name) => {
273
+ const result = await this.sparkService.getLookupReference(name);
274
+ return [name, result];
275
+ }));
276
+ this.lookupReferenceOptions.set(entries.reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}));
277
+ }
278
+ onCreate() {
279
+ this.createClicked.emit();
280
+ const et = this.entityType();
281
+ if (et) {
282
+ this.router.navigate(['/po', et.alias || et.id, 'new']);
283
+ }
284
+ }
285
+ connectStreaming(queryId) {
286
+ this.disconnectStreaming();
287
+ this.isStreaming.set(true);
288
+ this.streamingSub = this.streamingService.connectToStreamingQuery(queryId).subscribe({
289
+ next: (message) => this.handleStreamingMessage(message),
290
+ error: (err) => {
291
+ this.errorMessage.set(err?.message || 'Streaming connection failed');
292
+ this.isStreaming.set(false);
293
+ },
294
+ complete: () => {
295
+ this.isStreaming.set(false);
296
+ }
297
+ });
298
+ }
299
+ disconnectStreaming() {
300
+ if (this.streamingSub) {
301
+ this.streamingSub.unsubscribe();
302
+ this.streamingSub = null;
303
+ }
304
+ this.isStreaming.set(false);
305
+ }
306
+ handleStreamingMessage(message) {
307
+ switch (message.type) {
308
+ case 'snapshot':
309
+ this.errorMessage.set(null);
310
+ this.allItems.set(message.data);
311
+ this.applyFilter();
312
+ break;
313
+ case 'patch':
314
+ if (message.updated.length > 0) {
315
+ const currentItems = this.allItems();
316
+ const updatedItems = currentItems.map(item => {
317
+ const patch = message.updated.find(u => u.id === item.id);
318
+ if (!patch)
319
+ return item;
320
+ // Clone the item and update only changed attribute values
321
+ const updatedAttributes = item.attributes.map(attr => {
322
+ if (attr.name in patch.attributes) {
323
+ return { ...attr, value: patch.attributes[attr.name] };
324
+ }
325
+ return attr;
326
+ });
327
+ return { ...item, attributes: updatedAttributes };
328
+ });
329
+ this.allItems.set(updatedItems);
330
+ this.applyFilter();
331
+ }
332
+ break;
333
+ case 'error':
334
+ this.errorMessage.set(message.message);
335
+ break;
336
+ }
337
+ }
338
+ applyFilter() {
339
+ let items = this.allItems();
340
+ // Apply search filter
341
+ if (this.searchTerm) {
342
+ const term = this.searchTerm.toLowerCase();
343
+ items = items.filter(item => item.attributes.some(a => String(a.value ?? '').toLowerCase().includes(term)));
344
+ }
345
+ // Apply sorting
346
+ const isVirtual = this.query()?.renderMode === 'VirtualScrolling';
347
+ const sortCols = isVirtual ? this.virtualSettings().sortColumns : this.settings().sortColumns;
348
+ if (sortCols.length > 0) {
349
+ items = [...items].sort((a, b) => {
350
+ for (const col of sortCols) {
351
+ const aVal = a.attributes.find(attr => attr.name === col.property)?.value ?? '';
352
+ const bVal = b.attributes.find(attr => attr.name === col.property)?.value ?? '';
353
+ const cmp = String(aVal).localeCompare(String(bVal));
354
+ if (cmp !== 0)
355
+ return col.direction === 'descending' ? -cmp : cmp;
356
+ }
357
+ return 0;
358
+ });
359
+ }
360
+ if (isVirtual) {
361
+ // Update the mutable filtered items array.
362
+ // The stable data source's fetchFn closure reads from this.filteredItems,
363
+ // so clearing its cache and emitting empty triggers the CDK viewport to re-fetch.
364
+ this.filteredItems = items;
365
+ this.virtualDataSource()?.reset();
366
+ }
367
+ else {
368
+ this.paginationData.set({
369
+ data: items,
370
+ totalRecords: items.length,
371
+ totalPages: 1,
372
+ perPage: items.length,
373
+ page: 1
374
+ });
375
+ }
376
+ }
377
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkQueryListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
378
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.6", type: SparkQueryListComponent, isStandalone: true, selector: "spark-query-list", inputs: { extraActionsTemplate: { classPropertyName: "extraActionsTemplate", publicName: "extraActionsTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rowClicked: "rowClicked", createClicked: "createClicked" }, host: { properties: { "class.virtual-scrolling": "isVirtualScrolling()" } }, ngImport: i0, template: "<div class=\"d-flex flex-column h-100\">\n <!-- Title + Actions row -->\n <div class=\"d-flex justify-content-between align-items-center mb-4 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <h2>\n {{ (query()?.description | resolveTranslation) || query()?.name || ('common.loading' | t) }}\n @if (isStreaming()) {\n <span class=\"badge bg-success ms-2\" style=\"font-size: 0.5em; vertical-align: middle;\">LIVE</span>\n }\n </h2>\n <div class=\"d-flex gap-2\">\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (canCreate()) {\n <button class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'common.new' | t }}\n </button>\n }\n </div>\n </div>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && paginationData()) {\n <span class=\"text-muted\">\n {{ paginationData()!.totalRecords }} {{ paginationData()!.totalRecords === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (query()?.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <bs-virtual-datatable class=\"flex-grow-1 overflow-hidden\"\n [(settings)]=\"virtualSettings\"\n [dataSource]=\"vds\"\n [isResponsive]=\"true\"\n (settingsChange)=\"onSettingsChange()\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-template bsVirtualRowTemplate let-item>\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (item) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, item.id]\" (click)=\"rowClicked.emit(item)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n }\n } @else {\n &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: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsDatatableComponent, selector: "bs-datatable", inputs: ["data"], outputs: ["dataChange"] }, { kind: "directive", type: BsDatatableColumnDirective, selector: "[bsDatatableColumn]", inputs: ["bsDatatableColumn", "bsDatatableColumnSortable"] }, { kind: "directive", type: BsRowTemplateDirective, selector: "[bsRowTemplate]", inputs: ["bsRowTemplateOf"] }, { kind: "component", type: BsVirtualDatatableComponent, selector: "bs-virtual-datatable", inputs: ["dataSource", "isResponsive", "itemSize"] }, { kind: "directive", type: BsVirtualRowTemplateDirective, selector: "[bsVirtualRowTemplate]" }, { kind: "component", type: BsFormComponent, selector: "bs-form", inputs: ["action", "method"], outputs: ["submitted"] }, { kind: "directive", type: BsFormControlDirective, selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)" }, { kind: "component", type: BsGridComponent, selector: "bs-grid", inputs: ["stopFullWidthAt"] }, { kind: "directive", type: BsGridRowDirective, selector: "[bsRow]" }, { kind: "directive", type: BsGridColumnDirective, selector: "[xxs],[xs],[sm],[md],[lg],[xl],[xxl]", inputs: ["xxs", "xs", "sm", "md", "lg", "xl", "xxl"] }, { kind: "component", type: BsInputGroupComponent, selector: "bs-input-group" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkIconComponent, selector: "spark-icon", inputs: ["name"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }, { kind: "pipe", type: AttributeValuePipe, name: "attributeValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
379
+ }
380
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.6", ngImport: i0, type: SparkQueryListComponent, decorators: [{
381
+ type: Component,
382
+ 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: {
383
+ '[class.virtual-scrolling]': 'isVirtualScrolling()'
384
+ }, template: "<div class=\"d-flex flex-column h-100\">\n <!-- Title + Actions row -->\n <div class=\"d-flex justify-content-between align-items-center mb-4 flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <h2>\n {{ (query()?.description | resolveTranslation) || query()?.name || ('common.loading' | t) }}\n @if (isStreaming()) {\n <span class=\"badge bg-success ms-2\" style=\"font-size: 0.5em; vertical-align: middle;\">LIVE</span>\n }\n </h2>\n <div class=\"d-flex gap-2\">\n @if (extraActionsTemplate(); as extraActionsTpl) {\n <ng-container *ngTemplateOutlet=\"extraActionsTpl\"></ng-container>\n }\n @if (canCreate()) {\n <button class=\"btn btn-primary\" (click)=\"onCreate()\">\n <spark-icon name=\"plus-lg\" /> {{ 'common.new' | t }}\n </button>\n }\n </div>\n </div>\n\n @if (entityType()) {\n <!-- Search box -->\n <div class=\"flex-shrink-0\" [class.px-4]=\"isVirtualScrolling()\">\n <bs-form>\n <bs-grid>\n <div bsRow class=\"mb-3\">\n <div [md]=\"4\">\n <bs-input-group>\n <span class=\"input-group-text\">\n <spark-icon name=\"search\" />\n </span>\n <input\n type=\"text\"\n [placeholder]=\"'common.search' | t\"\n [(ngModel)]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange()\">\n @if (searchTerm) {\n <button\n type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"clearSearch()\">\n <spark-icon name=\"x-lg\" />\n </button>\n }\n </bs-input-group>\n </div>\n <div [md]=\"8\" class=\"text-end\">\n @if (searchTerm && paginationData()) {\n <span class=\"text-muted\">\n {{ paginationData()!.totalRecords }} {{ paginationData()!.totalRecords === 1 ? ('common.resultFound' | t) : ('common.resultsFound' | t) }}\n </span>\n }\n </div>\n </div>\n </bs-grid>\n </bs-form>\n\n @if (errorMessage(); as err) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ err }}\n </bs-alert>\n }\n </div>\n\n @if (query()?.renderMode === 'VirtualScrolling') {\n @if (virtualDataSource(); as vds) {\n <bs-virtual-datatable class=\"flex-grow-1 overflow-hidden\"\n [(settings)]=\"virtualSettings\"\n [dataSource]=\"vds\"\n [isResponsive]=\"true\"\n (settingsChange)=\"onSettingsChange()\">\n @for (attr of visibleAttributes(); track attr.id) {\n <div *bsDatatableColumn=\"attr.name; sortable: true\">\n {{ (attr.label | resolveTranslation) || attr.name }}\n </div>\n }\n\n <ng-template bsVirtualRowTemplate let-item>\n @for (attr of visibleAttributes(); track attr.id; let first = $first) {\n <td>\n @if (item) {\n @if (first && canRead()) {\n <a [routerLink]=\"['/po', entityType()!.alias || entityType()!.id, item.id]\" (click)=\"rowClicked.emit(item)\">\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n </a>\n } @else {\n <ng-container *ngTemplateOutlet=\"cellContent; context: { $implicit: item, attr: attr }\"></ng-container>\n }\n } @else {\n &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"] }]
385
+ }], ctorParameters: () => [], propDecorators: { extraActionsTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "extraActionsTemplate", required: false }] }], rowClicked: [{ type: i0.Output, args: ["rowClicked"] }], createClicked: [{ type: i0.Output, args: ["createClicked"] }] } });
386
+
387
+ /**
388
+ * Generated bundle index. Do not edit.
389
+ */
390
+
391
+ export { SparkQueryListComponent };
392
+ //# sourceMappingURL=mintplayer-ng-spark-query-list.mjs.map