@mintplayer/ng-spark 22.18.0 → 22.19.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.
@@ -155,7 +155,7 @@ class SparkPoCreateComponent {
155
155
  window.history.back();
156
156
  }
157
157
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkPoCreateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
158
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkPoCreateComponent, isStandalone: true, selector: "spark-po-create", outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @if (entityType(); as et) {\n <h2 class=\"mb-4\">{{ '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 | resolveTranslation }}\n </bs-alert>\n }\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type()\"\n [parentType]=\"type()\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType", "objectTypeId", "objectId", "refreshOverlay"], outputs: ["formDataChange", "save", "cancel", "refreshOverlayChange"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
158
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkPoCreateComponent, isStandalone: true, selector: "spark-po-create", outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @if (entityType(); as et) {\n <h2 class=\"mb-4\">{{ '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 | resolveTranslation }}\n </bs-alert>\n }\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type()\"\n [parentType]=\"type()\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType", "objectTypeId", "objectId", "triggerPathPrefix", "refreshOverlay"], outputs: ["formDataChange", "save", "cancel", "nestedTriggerRequested", "nestedTriggerBlurred", "refreshOverlayChange"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
159
159
  }
160
160
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkPoCreateComponent, decorators: [{
161
161
  type: Component,
@@ -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 isDateDataType,\n fromDateInputValue,\n RefreshOverlay,\n applyOverlay,\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 /** Bound two-way to the form. See {@link getEditableAttributes}. */\n refreshOverlay = signal<RefreshOverlay>({});\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' && !attr.lookupReferenceType) {\n // Same reason as spark-po-edit: a lookup-backed boolean's third state is the absence of a\n // value, and seeding `false` here would make every new object explicitly opted out.\n data[attr.name] = false;\n } else {\n data[attr.name] = '';\n }\n });\n this.formData.set(data);\n }\n\n /**\n * ⚠️ Overlaid before filtering — same reason as <c>spark-po-edit</c>, and worse here: this list is\n * the <em>only</em> source of the create payload, so an attribute a refresh hook revealed was not\n * merely sent stale, it was absent from the new object entirely.\n */\n getEditableAttributes() {\n const overlay = this.refreshOverlay();\n return this.entityType()?.attributes\n .map(a => applyOverlay(a, overlay[a.name]))\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 // A date control hands back a bare local wall clock; the wire needs a complete ISO-8601\n // instant carrying the viewer's offset for the entered date.\n value: isDateDataType(attr.dataType)\n ? fromDateInputValue(attr.dataType, this.formData()[attr.name])\n : 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 | resolveTranslation }}\n </bs-alert>\n }\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type()\"\n [parentType]=\"type()\"\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 isDateDataType,\n fromDateInputValue,\n RefreshOverlay,\n applyOverlay,\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 /** Bound two-way to the form. See {@link getEditableAttributes}. */\n refreshOverlay = signal<RefreshOverlay>({});\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' && !attr.lookupReferenceType) {\n // Same reason as spark-po-edit: a lookup-backed boolean's third state is the absence of a\n // value, and seeding `false` here would make every new object explicitly opted out.\n data[attr.name] = false;\n } else {\n data[attr.name] = '';\n }\n });\n this.formData.set(data);\n }\n\n /**\n * ⚠️ Overlaid before filtering — same reason as <c>spark-po-edit</c>, and worse here: this list is\n * the <em>only</em> source of the create payload, so an attribute a refresh hook revealed was not\n * merely sent stale, it was absent from the new object entirely.\n */\n getEditableAttributes() {\n const overlay = this.refreshOverlay();\n return this.entityType()?.attributes\n .map(a => applyOverlay(a, overlay[a.name]))\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 // A date control hands back a bare local wall clock; the wire needs a complete ISO-8601\n // instant carrying the viewer's offset for the entered date.\n value: isDateDataType(attr.dataType)\n ? fromDateInputValue(attr.dataType, this.formData()[attr.name])\n : 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 | resolveTranslation }}\n </bs-alert>\n }\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type()\"\n [parentType]=\"type()\"\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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"}
@@ -108,9 +108,26 @@ class SparkPoEditComponent {
108
108
  });
109
109
  this.formData.set(data);
110
110
  }
111
+ /**
112
+ * Resolves a nested AsDetail type by CLR name, for rebuilding the nested PO wire shape on save.
113
+ *
114
+ * ⚠️ <b>`detailTypes` first, catalogue second.</b> The catalogue from `/spark/types` is
115
+ * <b>Query-gated</b>, and an AsDetail row type usually has no rights of its own — nobody grants
116
+ * `Query/GateSettings`, because a gate is edited through the Repository that owns it. So the
117
+ * catalogue does not contain it, the resolver returned undefined, and the save quietly took the
118
+ * scalar branch: the attribute went out as a raw dict under `value` instead of a nested PO under
119
+ * `object`, the server could not map it, and `EntityMapper`'s conversion `catch` swallowed the
120
+ * failure. The save reported success and wrote nothing.
121
+ * <para>
122
+ * `detailTypes` is the parent's own copy of its row types, carried on the type definition for
123
+ * exactly this reason (#385 fixed the rendering half; this is the save half). It is gated on the
124
+ * parent's right, which is the right that governs editing the row anyway.
125
+ * </para>
126
+ */
111
127
  resolveEntityType() {
112
128
  const cache = this.allEntityTypes();
113
- return (clrName) => cache.find(t => t.clrType === clrName);
129
+ const detailTypes = this.entityType()?.detailTypes ?? [];
130
+ return (clrName) => detailTypes.find(t => t.clrType === clrName) ?? cache.find(t => t.clrType === clrName);
114
131
  }
115
132
  /**
116
133
  * The attributes this page will read values from when it builds the save.
@@ -253,7 +270,7 @@ class SparkPoEditComponent {
253
270
  this.router.navigate(['/po', this.type, this.id]);
254
271
  }
255
272
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkPoEditComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
256
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkPoEditComponent, isStandalone: true, selector: "spark-po-edit", outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage | resolveTranslation }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'common.edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type\"\n [objectId]=\"id\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n [parentId]=\"id\"\n [parentType]=\"type\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType", "objectTypeId", "objectId", "refreshOverlay"], outputs: ["formDataChange", "save", "cancel", "refreshOverlayChange"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
273
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: SparkPoEditComponent, isStandalone: true, selector: "spark-po-edit", outputs: { saved: "saved", cancelled: "cancelled" }, ngImport: i0, template: "<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage | resolveTranslation }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'common.edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type\"\n [objectId]=\"id\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n [parentId]=\"id\"\n [parentType]=\"type\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: BsAlertComponent, selector: "bs-alert", inputs: ["type", "announce", "isVisible"], outputs: ["isVisibleChange", "afterOpenedOrClosed"] }, { kind: "component", type: BsContainerComponent, selector: "bs-container" }, { kind: "component", type: BsSpinnerComponent, selector: "bs-spinner", inputs: ["type", "color"] }, { kind: "component", type: SparkPoFormComponent, selector: "spark-po-form", inputs: ["entityType", "formData", "validationErrors", "showButtons", "isSaving", "parentId", "parentType", "objectTypeId", "objectId", "triggerPathPrefix", "refreshOverlay"], outputs: ["formDataChange", "save", "cancel", "nestedTriggerRequested", "nestedTriggerBlurred", "refreshOverlayChange"] }, { kind: "pipe", type: ResolveTranslationPipe, name: "resolveTranslation" }, { kind: "pipe", type: TranslateKeyPipe, name: "t" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
257
274
  }
258
275
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SparkPoEditComponent, decorators: [{
259
276
  type: Component,
@@ -1 +1 @@
1
- {"version":3,"file":"mintplayer-ng-spark-po-edit.mjs","sources":["../../po-edit/src/spark-po-edit.component.ts","../../po-edit/src/spark-po-edit.component.html","../../po-edit/mintplayer-ng-spark-po-edit.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, SparkLanguageService } 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 nestedPoToDict,\n dictToNestedPo,\n EntityTypeResolver,\n isDateDataType,\n toDateInputValue,\n fromDateInputValue,\n wireDatesEqual,\n RefreshOverlay,\n applyOverlay,\n} from '@mintplayer/ng-spark/models';\n\n@Component({\n selector: 'spark-po-edit',\n imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe],\n templateUrl: './spark-po-edit.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SparkPoEditComponent {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly sparkService = inject(SparkService);\n private readonly language = inject(SparkLanguageService);\n\n saved = output<PersistentObject>();\n cancelled = output<void>();\n\n colors = Color;\n entityType = signal<EntityType | null>(null);\n item = signal<PersistentObject | null>(null);\n type = '';\n id = '';\n formData = signal<Record<string, any>>({});\n /**\n * Bound two-way to the form, which is where refreshes land. Read by\n * {@link getEditableAttributes} so the save sees the object the user was actually shown.\n */\n refreshOverlay = signal<RefreshOverlay>({});\n validationErrors = signal<ValidationError[]>([]);\n isSaving = signal(false);\n // Cached list of every entity type — needed by the AsDetail save path to resolve\n // nested type schemas when rebuilding the nested PO wire shape from the flat form dict.\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 = params.get('type') || '';\n this.id = params.get('id') || '';\n\n try {\n const [types, item] = await Promise.all([\n this.sparkService.getEntityTypes(),\n this.sparkService.get(this.type, this.id)\n ]);\n\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.item.set(item);\n this.initFormData();\n } catch (e) {\n const error = e as HttpErrorResponse;\n this.validationErrors.set([{\n attributeName: '',\n errorMessage: { en: error.error?.error || error.message || 'An unexpected error occurred' },\n ruleType: 'error'\n }]);\n }\n }\n\n initFormData(): void {\n const data: Record<string, any> = {};\n const currentItem = this.item();\n this.getEditableAttributes().forEach(attr => {\n const itemAttr = currentItem?.attributes.find(a => a.name === attr.name);\n if (attr.dataType === 'Reference') {\n data[attr.name] = itemAttr?.value ?? null;\n } else if (attr.dataType === 'AsDetail') {\n // Server emits nested PO(s) in attr.object / attr.objects. Flatten back into the\n // Record<string, any> shape the form has always used so the rest of the component\n // tree stays unchanged.\n if (attr.isArray) {\n data[attr.name] = (itemAttr?.objects ?? []).map(po => nestedPoToDict(po));\n } else {\n data[attr.name] = itemAttr?.object ? nestedPoToDict(itemAttr.object) : {};\n }\n } else if (attr.dataType === 'boolean' && !attr.lookupReferenceType) {\n // `?? false` only for a real two-state checkbox. A lookup-backed boolean has a third state\n // that is expressed as the absence of a value, and coercing it here destroyed that BEFORE\n // the control rendered: merely opening the form and saving turned \"unset\" into an explicit\n // false, permanently and with nothing shown to the user.\n data[attr.name] = itemAttr?.value ?? false;\n } else if (isDateDataType(attr.dataType)) {\n // The wire carries a full ISO-8601 instant with an offset; a native date/time control accepts\n // only a bare local wall clock. Assigning the wire value directly does not fail loudly -- the\n // control just renders blank, and saving the untouched form writes that blank back.\n data[attr.name] = toDateInputValue(attr.dataType, itemAttr?.value);\n } else {\n data[attr.name] = itemAttr?.value ?? '';\n }\n });\n this.formData.set(data);\n }\n\n private resolveEntityType(): EntityTypeResolver {\n const cache = this.allEntityTypes();\n return (clrName: string) => cache.find(t => t.clrType === clrName);\n }\n\n /**\n * The attributes this page will read values from when it builds the save.\n *\n * ⚠️ <b>Overlaid before filtering, not after loading.</b> A refresh hook can reveal an attribute\n * that was hidden when the object was loaded, and the ordinary reason it does so is that the\n * attribute has just become required. Filtering on the loaded state left such an attribute out of\n * both {@link initFormData} and the save payload, so the user filled in a field whose value was\n * then dropped on the floor and refused by the server as missing — with no way out of the form.\n * The overlay is the form's, bound two-way, so the two halves cannot drift again.\n */\n getEditableAttributes() {\n const overlay = this.refreshOverlay();\n return this.entityType()?.attributes\n .map(a => applyOverlay(a, overlay[a.name]))\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 const currentItem = this.item();\n if (!this.entityType() || !currentItem) return;\n\n this.validationErrors.set([]);\n this.isSaving.set(true);\n\n const resolver = this.resolveEntityType();\n const attributes: PersistentObjectAttribute[] = currentItem.attributes.map(attr => {\n const editableAttr = this.getEditableAttributes().find(a => a.name === attr.name);\n\n // AsDetail: formData[name] is a flat dict (single) or array of dicts (array). Rebuild\n // the nested PO wire shape so the server's polymorphic converter hydrates it into a\n // PersistentObjectAttributeAsDetail.\n if (editableAttr?.dataType === 'AsDetail' && editableAttr.asDetailType) {\n const nestedType = resolver(editableAttr.asDetailType);\n if (nestedType) {\n const raw = this.formData()[attr.name];\n if (editableAttr.isArray) {\n const items: any[] = Array.isArray(raw) ? raw : [];\n return {\n ...attr,\n value: null,\n object: null,\n objects: items.map(item => dictToNestedPo((item ?? {}) as Record<string, any>, nestedType, resolver)),\n asDetailType: editableAttr.asDetailType,\n isValueChanged: true,\n };\n }\n return {\n ...attr,\n value: null,\n object: raw ? dictToNestedPo(raw as Record<string, any>, nestedType, resolver) : null,\n objects: null,\n asDetailType: editableAttr.asDetailType,\n isValueChanged: true,\n };\n }\n }\n\n // `in`, not a truthiness or `?? attr.value` check: an attribute the refresh revealed has no\n // slot until its control writes one, and an attribute the user cleared has a slot holding ''.\n // Coalescing would resurrect the loaded value on exactly the edit that removed it.\n const formData = this.formData();\n const rawValue = editableAttr && attr.name in formData ? formData[attr.name] : attr.value;\n\n if (editableAttr && isDateDataType(editableAttr.dataType)) {\n // Back out of the control's bare wall clock into a complete ISO-8601 instant, carrying the\n // viewer's offset for the entered date.\n const converted = fromDateInputValue(editableAttr.dataType, rawValue);\n // Compare by instant, not by text: the round trip rewrites the offset to the viewer's even\n // when nothing was edited.\n const changed = !wireDatesEqual(converted, attr.value);\n return {\n ...attr,\n // When the value did not actually change, send back exactly what was loaded. Sending the\n // re-converted string would preserve the instant but rewrite the stored offset to the\n // viewer's, so merely opening a record and saving it would relabel a Seattle registration\n // as a Brussels one. The offset is not business data (so the instant is what we guarantee),\n // but there is no reason to discard it on a save that changed nothing.\n value: changed ? converted : attr.value,\n isValueChanged: changed,\n };\n }\n\n const newValue = rawValue;\n return {\n ...attr,\n value: newValue,\n isValueChanged: editableAttr ? newValue !== attr.value : false\n };\n });\n\n const po: Partial<PersistentObject> = {\n id: currentItem.id,\n // Send back the token this object was loaded with. Left out, the server skips the\n // concurrency check entirely -- it is opt-in by presence -- and a save over somebody else's\n // edit succeeds silently. Left as undefined when the server sent none, which drops the key\n // from the JSON and restores exactly the old behaviour rather than sending an empty string\n // that could never match.\n etag: currentItem.etag,\n name: this.formData()['Name'] || currentItem.name,\n objectTypeId: this.entityType()!.id,\n attributes\n };\n\n try {\n const result = await this.sparkService.update(this.type, this.id, po);\n this.isSaving.set(false);\n this.saved.emit(result as PersistentObject);\n this.router.navigate(['/po', this.type, this.id]);\n } catch (e) {\n this.isSaving.set(false);\n const error = e as HttpErrorResponse;\n // ⚠️ The errors live under `result`, because every endpoint wraps its body in a\n // ClientOperationEnvelope: `{ result: { errors: [...] }, operations: [] }`. Reading\n // `error.error.errors` matched nothing, so this branch was dead and EVERY save-time\n // validation failure fell through to the raw Angular HTTP string below.\n const errors = error.error?.result?.errors ?? error.error?.errors;\n if (error.status === 400 && errors) {\n this.validationErrors.set(errors);\n } else if (error.status === 409) {\n // Somebody saved this record between the load and this save. The server's own body says\n // only \"Concurrency conflict\" -- deliberately, since the real message carries the change\n // vector -- which is accurate, untranslated, and tells the user nothing to do about it.\n // The form keeps its values, so the typing is not lost.\n this.validationErrors.set([{\n attributeName: '',\n errorMessage: { en: this.language.t('common.concurrencyConflict') },\n ruleType: 'error'\n }]);\n } else {\n this.validationErrors.set([{\n attributeName: '',\n // Prefer the server's own message, as the load path already does. A refusal arrives as\n // 404 by design (an anti-oracle measure), and `error.message` renders that as\n // \"Http failure response for /spark/po/...: 404 Not Found\" inside the validation summary.\n errorMessage: { en: error.error?.result?.error || error.error?.error || error.message || 'An unexpected error occurred' },\n ruleType: 'error'\n }]);\n }\n }\n }\n\n onCancel(): void {\n this.cancelled.emit();\n this.router.navigate(['/po', this.type, this.id]);\n }\n}\n","<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage | resolveTranslation }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'common.edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type\"\n [objectId]=\"id\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n [parentId]=\"id\"\n [parentType]=\"type\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n","/**\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-edit.mjs","sources":["../../po-edit/src/spark-po-edit.component.ts","../../po-edit/src/spark-po-edit.component.html","../../po-edit/mintplayer-ng-spark-po-edit.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, SparkLanguageService } 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 nestedPoToDict,\n dictToNestedPo,\n EntityTypeResolver,\n isDateDataType,\n toDateInputValue,\n fromDateInputValue,\n wireDatesEqual,\n RefreshOverlay,\n applyOverlay,\n} from '@mintplayer/ng-spark/models';\n\n@Component({\n selector: 'spark-po-edit',\n imports: [CommonModule, BsAlertComponent, BsContainerComponent, BsSpinnerComponent, SparkPoFormComponent, ResolveTranslationPipe, TranslateKeyPipe],\n templateUrl: './spark-po-edit.component.html',\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class SparkPoEditComponent {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly sparkService = inject(SparkService);\n private readonly language = inject(SparkLanguageService);\n\n saved = output<PersistentObject>();\n cancelled = output<void>();\n\n colors = Color;\n entityType = signal<EntityType | null>(null);\n item = signal<PersistentObject | null>(null);\n type = '';\n id = '';\n formData = signal<Record<string, any>>({});\n /**\n * Bound two-way to the form, which is where refreshes land. Read by\n * {@link getEditableAttributes} so the save sees the object the user was actually shown.\n */\n refreshOverlay = signal<RefreshOverlay>({});\n validationErrors = signal<ValidationError[]>([]);\n isSaving = signal(false);\n // Cached list of every entity type — needed by the AsDetail save path to resolve\n // nested type schemas when rebuilding the nested PO wire shape from the flat form dict.\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 = params.get('type') || '';\n this.id = params.get('id') || '';\n\n try {\n const [types, item] = await Promise.all([\n this.sparkService.getEntityTypes(),\n this.sparkService.get(this.type, this.id)\n ]);\n\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.item.set(item);\n this.initFormData();\n } catch (e) {\n const error = e as HttpErrorResponse;\n this.validationErrors.set([{\n attributeName: '',\n errorMessage: { en: error.error?.error || error.message || 'An unexpected error occurred' },\n ruleType: 'error'\n }]);\n }\n }\n\n initFormData(): void {\n const data: Record<string, any> = {};\n const currentItem = this.item();\n this.getEditableAttributes().forEach(attr => {\n const itemAttr = currentItem?.attributes.find(a => a.name === attr.name);\n if (attr.dataType === 'Reference') {\n data[attr.name] = itemAttr?.value ?? null;\n } else if (attr.dataType === 'AsDetail') {\n // Server emits nested PO(s) in attr.object / attr.objects. Flatten back into the\n // Record<string, any> shape the form has always used so the rest of the component\n // tree stays unchanged.\n if (attr.isArray) {\n data[attr.name] = (itemAttr?.objects ?? []).map(po => nestedPoToDict(po));\n } else {\n data[attr.name] = itemAttr?.object ? nestedPoToDict(itemAttr.object) : {};\n }\n } else if (attr.dataType === 'boolean' && !attr.lookupReferenceType) {\n // `?? false` only for a real two-state checkbox. A lookup-backed boolean has a third state\n // that is expressed as the absence of a value, and coercing it here destroyed that BEFORE\n // the control rendered: merely opening the form and saving turned \"unset\" into an explicit\n // false, permanently and with nothing shown to the user.\n data[attr.name] = itemAttr?.value ?? false;\n } else if (isDateDataType(attr.dataType)) {\n // The wire carries a full ISO-8601 instant with an offset; a native date/time control accepts\n // only a bare local wall clock. Assigning the wire value directly does not fail loudly -- the\n // control just renders blank, and saving the untouched form writes that blank back.\n data[attr.name] = toDateInputValue(attr.dataType, itemAttr?.value);\n } else {\n data[attr.name] = itemAttr?.value ?? '';\n }\n });\n this.formData.set(data);\n }\n\n /**\n * Resolves a nested AsDetail type by CLR name, for rebuilding the nested PO wire shape on save.\n *\n * ⚠️ <b>`detailTypes` first, catalogue second.</b> The catalogue from `/spark/types` is\n * <b>Query-gated</b>, and an AsDetail row type usually has no rights of its own — nobody grants\n * `Query/GateSettings`, because a gate is edited through the Repository that owns it. So the\n * catalogue does not contain it, the resolver returned undefined, and the save quietly took the\n * scalar branch: the attribute went out as a raw dict under `value` instead of a nested PO under\n * `object`, the server could not map it, and `EntityMapper`'s conversion `catch` swallowed the\n * failure. The save reported success and wrote nothing.\n * <para>\n * `detailTypes` is the parent's own copy of its row types, carried on the type definition for\n * exactly this reason (#385 fixed the rendering half; this is the save half). It is gated on the\n * parent's right, which is the right that governs editing the row anyway.\n * </para>\n */\n private resolveEntityType(): EntityTypeResolver {\n const cache = this.allEntityTypes();\n const detailTypes = this.entityType()?.detailTypes ?? [];\n return (clrName: string) =>\n detailTypes.find(t => t.clrType === clrName) ?? cache.find(t => t.clrType === clrName);\n }\n\n /**\n * The attributes this page will read values from when it builds the save.\n *\n * ⚠️ <b>Overlaid before filtering, not after loading.</b> A refresh hook can reveal an attribute\n * that was hidden when the object was loaded, and the ordinary reason it does so is that the\n * attribute has just become required. Filtering on the loaded state left such an attribute out of\n * both {@link initFormData} and the save payload, so the user filled in a field whose value was\n * then dropped on the floor and refused by the server as missing — with no way out of the form.\n * The overlay is the form's, bound two-way, so the two halves cannot drift again.\n */\n getEditableAttributes() {\n const overlay = this.refreshOverlay();\n return this.entityType()?.attributes\n .map(a => applyOverlay(a, overlay[a.name]))\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 const currentItem = this.item();\n if (!this.entityType() || !currentItem) return;\n\n this.validationErrors.set([]);\n this.isSaving.set(true);\n\n const resolver = this.resolveEntityType();\n const attributes: PersistentObjectAttribute[] = currentItem.attributes.map(attr => {\n const editableAttr = this.getEditableAttributes().find(a => a.name === attr.name);\n\n // AsDetail: formData[name] is a flat dict (single) or array of dicts (array). Rebuild\n // the nested PO wire shape so the server's polymorphic converter hydrates it into a\n // PersistentObjectAttributeAsDetail.\n if (editableAttr?.dataType === 'AsDetail' && editableAttr.asDetailType) {\n const nestedType = resolver(editableAttr.asDetailType);\n if (nestedType) {\n const raw = this.formData()[attr.name];\n if (editableAttr.isArray) {\n const items: any[] = Array.isArray(raw) ? raw : [];\n return {\n ...attr,\n value: null,\n object: null,\n objects: items.map(item => dictToNestedPo((item ?? {}) as Record<string, any>, nestedType, resolver)),\n asDetailType: editableAttr.asDetailType,\n isValueChanged: true,\n };\n }\n return {\n ...attr,\n value: null,\n object: raw ? dictToNestedPo(raw as Record<string, any>, nestedType, resolver) : null,\n objects: null,\n asDetailType: editableAttr.asDetailType,\n isValueChanged: true,\n };\n }\n }\n\n // `in`, not a truthiness or `?? attr.value` check: an attribute the refresh revealed has no\n // slot until its control writes one, and an attribute the user cleared has a slot holding ''.\n // Coalescing would resurrect the loaded value on exactly the edit that removed it.\n const formData = this.formData();\n const rawValue = editableAttr && attr.name in formData ? formData[attr.name] : attr.value;\n\n if (editableAttr && isDateDataType(editableAttr.dataType)) {\n // Back out of the control's bare wall clock into a complete ISO-8601 instant, carrying the\n // viewer's offset for the entered date.\n const converted = fromDateInputValue(editableAttr.dataType, rawValue);\n // Compare by instant, not by text: the round trip rewrites the offset to the viewer's even\n // when nothing was edited.\n const changed = !wireDatesEqual(converted, attr.value);\n return {\n ...attr,\n // When the value did not actually change, send back exactly what was loaded. Sending the\n // re-converted string would preserve the instant but rewrite the stored offset to the\n // viewer's, so merely opening a record and saving it would relabel a Seattle registration\n // as a Brussels one. The offset is not business data (so the instant is what we guarantee),\n // but there is no reason to discard it on a save that changed nothing.\n value: changed ? converted : attr.value,\n isValueChanged: changed,\n };\n }\n\n const newValue = rawValue;\n return {\n ...attr,\n value: newValue,\n isValueChanged: editableAttr ? newValue !== attr.value : false\n };\n });\n\n const po: Partial<PersistentObject> = {\n id: currentItem.id,\n // Send back the token this object was loaded with. Left out, the server skips the\n // concurrency check entirely -- it is opt-in by presence -- and a save over somebody else's\n // edit succeeds silently. Left as undefined when the server sent none, which drops the key\n // from the JSON and restores exactly the old behaviour rather than sending an empty string\n // that could never match.\n etag: currentItem.etag,\n name: this.formData()['Name'] || currentItem.name,\n objectTypeId: this.entityType()!.id,\n attributes\n };\n\n try {\n const result = await this.sparkService.update(this.type, this.id, po);\n this.isSaving.set(false);\n this.saved.emit(result as PersistentObject);\n this.router.navigate(['/po', this.type, this.id]);\n } catch (e) {\n this.isSaving.set(false);\n const error = e as HttpErrorResponse;\n // ⚠️ The errors live under `result`, because every endpoint wraps its body in a\n // ClientOperationEnvelope: `{ result: { errors: [...] }, operations: [] }`. Reading\n // `error.error.errors` matched nothing, so this branch was dead and EVERY save-time\n // validation failure fell through to the raw Angular HTTP string below.\n const errors = error.error?.result?.errors ?? error.error?.errors;\n if (error.status === 400 && errors) {\n this.validationErrors.set(errors);\n } else if (error.status === 409) {\n // Somebody saved this record between the load and this save. The server's own body says\n // only \"Concurrency conflict\" -- deliberately, since the real message carries the change\n // vector -- which is accurate, untranslated, and tells the user nothing to do about it.\n // The form keeps its values, so the typing is not lost.\n this.validationErrors.set([{\n attributeName: '',\n errorMessage: { en: this.language.t('common.concurrencyConflict') },\n ruleType: 'error'\n }]);\n } else {\n this.validationErrors.set([{\n attributeName: '',\n // Prefer the server's own message, as the load path already does. A refusal arrives as\n // 404 by design (an anti-oracle measure), and `error.message` renders that as\n // \"Http failure response for /spark/po/...: 404 Not Found\" inside the validation summary.\n errorMessage: { en: error.error?.result?.error || error.error?.error || error.message || 'An unexpected error occurred' },\n ruleType: 'error'\n }]);\n }\n }\n }\n\n onCancel(): void {\n this.cancelled.emit();\n this.router.navigate(['/po', this.type, this.id]);\n }\n}\n","<bs-container>\n<div class=\"container\">\n @for (error of generalErrors(); track error.errorMessage) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">\n {{ error.errorMessage | resolveTranslation }}\n </bs-alert>\n }\n\n @if (entityType(); as et) {\n @if (item()) {\n <h2 class=\"mb-4\">{{ 'common.edit' | t }} {{ (et.description | resolveTranslation) || et.name }}</h2>\n\n <spark-po-form\n [entityType]=\"et\"\n [(formData)]=\"formData\"\n [(refreshOverlay)]=\"refreshOverlay\"\n [objectTypeId]=\"type\"\n [objectId]=\"id\"\n [validationErrors]=\"validationErrors()\"\n [showButtons]=\"true\"\n [isSaving]=\"isSaving()\"\n [parentId]=\"id\"\n [parentType]=\"type\"\n (save)=\"onSave()\"\n (cancel)=\"onCancel()\">\n </spark-po-form>\n }\n } @else {\n <div class=\"text-center p-5\">\n <bs-spinner />\n </div>\n }\n</div>\n</bs-container>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}