@mintplayer/ng-spark 22.18.0 → 22.20.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.
@@ -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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"}