2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-01 04:56:45 +00:00

[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(() => { useEffect(() => {
// Provide initial form data // Provide initial form data
Object.entries(props.fields ?? {}).forEach(([fieldName, field]) => { 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({ form.setValues({
[fieldName]: field.value [fieldName]: v
});
} else if (field.default !== undefined) {
form.setValues({
[fieldName]: field.default
}); });
} }
}); });

View File

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

View File

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

View File

@ -37,16 +37,18 @@ export function RelatedModelField({
// Extract field definition from provided data // Extract field definition from provided data
// Where user has provided specific data, override the API definition // Where user has provided specific data, override the API definition
const definition: ApiFormFieldType = useMemo( const definition: ApiFormFieldType = useMemo(() => {
() => let def = constructField({
constructField({ form: form,
form: form, field: field,
field: field, fieldName: fieldName,
fieldName: fieldName, definitions: definitions
definitions: definitions });
}),
[form.values, field, 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 // Keep track of the primary key value for this field
const [pk, setPk] = useState<number | null>(null); 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 ( return (
<Input.Wrapper {...definition} error={error}> <Input.Wrapper {...fieldDefinition} error={error}>
<Select <Select
id={fieldId} id={fieldId}
value={pk != null && data.find((item) => item.value == pk)} value={pk != null && data.find((item) => item.value == pk)}

View File

@ -69,8 +69,12 @@ export function extractAvailableFields(
name: fieldName, name: fieldName,
field_type: field.type, field_type: field.type,
description: field.help_text, 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; return fields;

View File

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