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:
parent
cb33705e44
commit
3349013646
@ -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
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
|
|
||||||
|
@ -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)}
|
||||||
|
@ -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;
|
||||||
|
@ -180,7 +180,7 @@ export default function PartDetail() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [part]);
|
}, [id, part]);
|
||||||
|
|
||||||
const breadcrumbs = useMemo(
|
const breadcrumbs = useMemo(
|
||||||
() => [
|
() => [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user