diff --git a/frontend/src/app/shared/components/fields/edit/edit-form/edit-form.ts b/frontend/src/app/shared/components/fields/edit/edit-form/edit-form.ts index 9688885d8ff..d3a4d3e334b 100644 --- a/frontend/src/app/shared/components/fields/edit/edit-form/edit-form.ts +++ b/frontend/src/app/shared/components/fields/edit/edit-form/edit-form.ts @@ -44,6 +44,7 @@ import isNewResource from 'core-app/features/hal/helpers/is-new-resource'; import { HalError } from 'core-app/features/hal/services/hal-error'; import { FormResource } from 'core-app/features/hal/resources/form-resource'; import { HalResourceEditFieldHandler } from 'core-app/shared/components/fields/edit/field-handler/hal-resource-edit-field-handler'; +import { ISchemaProxy } from 'core-app/features/hal/schemas/schema-proxy'; export const activeFieldContainerClassName = 'inline-edit--active-field'; export const activeFieldClassName = 'inline-edit--field'; @@ -294,48 +295,46 @@ export abstract class EditForm { * @param fieldName */ protected loadFieldSchema(fieldName:string, noWarnings = false):Promise { - return new Promise((resolve, reject) => { - this.loadFormAndCheck(fieldName, noWarnings); - const fieldSchema:IFieldSchema = this.change.schema.ofProperty(fieldName); - + return this.getFormFieldSchema(fieldName).then((fieldSchema) => { if (!fieldSchema) { + this.closeEditFields([fieldName]); + throw new Error(); } - resolve(fieldSchema); + if (!fieldSchema.writable && !noWarnings) { + this.halNotification.showEditingBlockedError(fieldSchema.name || fieldName); + this.closeEditFields([fieldName]); + } + + return fieldSchema; }); } /** - * Ensure the form gets loaded and we show an error when the field cannot be opened + * Load the form and return the field schema, reloading the form once if the schema is + * not present in the cached version (e.g. after a type change). + * Returns null if the schema is still absent after a forced reload. * @param fieldName - * @param noWarnings */ - private loadFormAndCheck(fieldName:string, noWarnings = false) { - // Ensure the form is being loaded if necessary - this.change - .getForm() - .then(() => { - // Look up whether we're actually editable - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const fieldSchema = this.change.schema.ofProperty(fieldName); + private getFormFieldSchema(fieldName:string):Promise { + return this.change.getForm() + .then(():Promise => { + const fieldSchema:IFieldSchema|null = (this.change.schema as ISchemaProxy).ofProperty(fieldName); - // If the type changed while we tried to activate the form - // silently close the field as it will no longer be writable - if (!fieldSchema) { - this.closeEditFields([fieldName]); - return; + if (fieldSchema) { + return Promise.resolve(fieldSchema); } - if (!fieldSchema.writable && !noWarnings) { - this.halNotification.showEditingBlockedError(fieldSchema.name || fieldName); - this.closeEditFields([fieldName]); - } + // The cached form may be stale (e.g. type just changed); force a reload and retry once. + return this.change.getForm(true).then( + ():IFieldSchema|null => (this.change.schema as ISchemaProxy).ofProperty(fieldName), + ); }) - .catch((error:any) => { + .catch((error:unknown) => { console.error('Failed to build edit field: %o', error); this.halNotification.handleRawError(error, this.resource); - this.closeEditFields([fieldName]); + return null; }); } diff --git a/spec/features/work_packages/table/switch_types_spec.rb b/spec/features/work_packages/table/switch_types_spec.rb index beb36715440..acc23f69da6 100644 --- a/spec/features/work_packages/table/switch_types_spec.rb +++ b/spec/features/work_packages/table/switch_types_spec.rb @@ -121,20 +121,19 @@ RSpec.describe "Switching types in work package table", :js do # Switch type type_field.activate! - type_field.set_value type_bug.name + type_field.set_select_field_value type_bug.name wp_table.expect_and_dismiss_toaster( type: :error, message: "#{cf_req_text.name} can't be blank." ) - # Required CF requires activation + # After a failed type switch, the required CF field is auto-opened in edit mode req_text_field.expect_active! # Now switch back to a type without the required CF type_field.activate! - type_field.openSelectField - type_field.set_value type_task.name + type_field.set_select_field_value type_task.name wp_table.expect_and_dismiss_toaster( message: "Successful update."