[React] Improvements to API forms (#5742)

* Remove read_only field from API OPTIONS

- 'read_only' is a reserved field for some Mantine components

* Fixing further errors for related field model

* Handle bad values for numericalValue

* Fix for default values for API forms

* Fix for choice field

- Do not set form default value when constructing element

* Tweak for PartDetail page
This commit is contained in:
Oliver 2023-10-18 14:45:03 +11:00 committed by GitHub
parent cb33705e44
commit 3349013646
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 61 additions and 24 deletions

View File

@ -136,13 +136,19 @@ export function ApiForm({
useEffect(() => {
// Provide initial form data
Object.entries(props.fields ?? {}).forEach(([fieldName, field]) => {
if (field.value !== undefined) {
// fieldDefinition is supplied by the API, and can serve as a backup
let fieldDefinition = fieldDefinitions[fieldName] ?? {};
let v =
field.value ??
field.default ??
fieldDefinition.value ??
fieldDefinition.default ??
undefined;
if (v !== undefined) {
form.setValues({
[fieldName]: field.value
});
} else if (field.default !== undefined) {
form.setValues({
[fieldName]: field.default
[fieldName]: v
});
}
});

View File

@ -68,6 +68,7 @@ export type ApiFormFieldType = {
choices?: any[];
hidden?: boolean;
disabled?: boolean;
read_only?: boolean;
placeholder?: string;
description?: string;
preFieldContent?: JSX.Element | (() => JSX.Element);
@ -115,6 +116,10 @@ export function constructField({
break;
}
// Clear out the 'read_only' attribute
def.disabled = def.disabled ?? def.read_only ?? false;
delete def['read_only'];
return def;
}
@ -190,16 +195,26 @@ export function ApiFormField({
// Coerce the value to a numerical value
const numericalValue: number | undefined = useMemo(() => {
let val = 0;
switch (definition.field_type) {
case 'integer':
return parseInt(value);
val = parseInt(value) ?? 0;
break;
case 'decimal':
case 'float':
case 'number':
return parseFloat(value);
val = parseFloat(value) ?? 0;
break;
default:
return undefined;
break;
}
if (isNaN(val) || !isFinite(val)) {
val = 0;
}
return val;
}, [value]);
// Construct the individual field

View File

@ -34,8 +34,6 @@ export function ChoiceField({
definitions: definitions
});
form.setValues({ [fieldName]: def.value ?? def.default });
return def;
}, [fieldName, field, definitions]);

View File

@ -37,16 +37,18 @@ export function RelatedModelField({
// Extract field definition from provided data
// Where user has provided specific data, override the API definition
const definition: ApiFormFieldType = useMemo(
() =>
constructField({
form: form,
field: field,
fieldName: fieldName,
definitions: definitions
}),
[form.values, field, definitions]
);
const definition: ApiFormFieldType = useMemo(() => {
let def = constructField({
form: form,
field: field,
fieldName: fieldName,
definitions: definitions
});
// Remove the 'read_only' attribute (causes issues with Mantine)
delete def['read_only'];
return def;
}, [form.values, field, definitions]);
// Keep track of the primary key value for this field
const [pk, setPk] = useState<number | null>(null);
@ -170,8 +172,20 @@ export function RelatedModelField({
}
}
/* Construct a "cut-down" version of the definition,
* which does not include any attributes that the lower components do not recognize
*/
const fieldDefinition = useMemo(() => {
return {
...definition,
onValueChange: undefined,
adjustFilters: undefined,
read_only: undefined
};
}, [definition]);
return (
<Input.Wrapper {...definition} error={error}>
<Input.Wrapper {...fieldDefinition} error={error}>
<Select
id={fieldId}
value={pk != null && data.find((item) => item.value == pk)}

View File

@ -69,8 +69,12 @@ export function extractAvailableFields(
name: fieldName,
field_type: field.type,
description: field.help_text,
value: field.value ?? field.default
value: field.value ?? field.default,
disabled: field.read_only ?? false
};
// Remove the 'read_only' field - plays havoc with react components
delete fields['read_only'];
}
return fields;

View File

@ -180,7 +180,7 @@ export default function PartDetail() {
)
}
];
}, [part]);
}, [id, part]);
const breadcrumbs = useMemo(
() => [