Implementing union enum when mutlifields are all enums
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
import validator from "@rjsf/validator-ajv8";
|
import validator from "@rjsf/validator-ajv8";
|
||||||
import Form from "@rjsf/mui";
|
import Form from "@rjsf/mui";
|
||||||
import { RegistryWidgetsType } from "@rjsf/utils";
|
import {RegistryFieldsType, RegistryWidgetsType} from "@rjsf/utils";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { jsonschemaProvider } from "../../providers/jsonschema-provider";
|
import { jsonschemaProvider } from "../../providers/jsonschema-provider";
|
||||||
import { useForm } from "@refinedev/core";
|
import { useForm } from "@refinedev/core";
|
||||||
//import TextWidget from "@rjsf/core/src/components/widgets/TextWidget";
|
|
||||||
import CrudTextWidget from "./widgets/crud-text-widget";
|
import CrudTextWidget from "./widgets/crud-text-widget";
|
||||||
|
import UnionEnumField from "./fields/union-enum";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
schemaName: string,
|
schemaName: string,
|
||||||
@@ -14,7 +14,13 @@ type Props = {
|
|||||||
//onSubmit: (data: IChangeEvent, event: FormEvent<any>) => void
|
//onSubmit: (data: IChangeEvent, event: FormEvent<any>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const customWidgets: RegistryWidgetsType = { TextWidget: CrudTextWidget };
|
const customWidgets: RegistryWidgetsType = {
|
||||||
|
TextWidget: CrudTextWidget
|
||||||
|
};
|
||||||
|
|
||||||
|
const customFields: RegistryFieldsType = {
|
||||||
|
AnyOfField: UnionEnumField
|
||||||
|
}
|
||||||
|
|
||||||
export const CrudForm: React.FC<Props> = ({schemaName, resource, id}) => {
|
export const CrudForm: React.FC<Props> = ({schemaName, resource, id}) => {
|
||||||
const { onFinish, query, formLoading } = useForm({
|
const { onFinish, query, formLoading } = useForm({
|
||||||
@@ -53,6 +59,7 @@ export const CrudForm: React.FC<Props> = ({schemaName, resource, id}) => {
|
|||||||
validator={validator}
|
validator={validator}
|
||||||
omitExtraData={true}
|
omitExtraData={true}
|
||||||
widgets={customWidgets}
|
widgets={customWidgets}
|
||||||
|
fields={customFields}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
78
gui/app/src/common/crud/fields/union-enum.tsx
Normal file
78
gui/app/src/common/crud/fields/union-enum.tsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import { ERRORS_KEY, FieldProps, getUiOptions } from "@rjsf/utils";
|
||||||
|
import AnyOfField from "@rjsf/core/lib/components/fields/MultiSchemaField";
|
||||||
|
import { UnionEnumWidget } from "../widgets/union-enum";
|
||||||
|
import get from 'lodash/get';
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
import omit from 'lodash/omit';
|
||||||
|
|
||||||
|
const UnionEnumField = (props: FieldProps) => {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
disabled = false,
|
||||||
|
errorSchema = {},
|
||||||
|
formContext,
|
||||||
|
formData,
|
||||||
|
onChange,
|
||||||
|
onBlur,
|
||||||
|
onFocus,
|
||||||
|
registry,
|
||||||
|
schema,
|
||||||
|
uiSchema,
|
||||||
|
options,
|
||||||
|
idSchema,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const enumOptions: any[] = []
|
||||||
|
for (let opt of options) {
|
||||||
|
if (!opt.hasOwnProperty('enum')) {
|
||||||
|
return (<AnyOfField {...props} />)
|
||||||
|
}
|
||||||
|
for (let val of opt.enum) {
|
||||||
|
enumOptions.push({
|
||||||
|
title: val,
|
||||||
|
value: val,
|
||||||
|
type: opt.title
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { globalUiOptions, schemaUtils } = registry;
|
||||||
|
const {
|
||||||
|
placeholder,
|
||||||
|
autofocus,
|
||||||
|
autocomplete,
|
||||||
|
title = schema.title,
|
||||||
|
...uiOptions
|
||||||
|
} = getUiOptions(uiSchema, globalUiOptions);
|
||||||
|
|
||||||
|
const rawErrors = get(errorSchema, ERRORS_KEY, []);
|
||||||
|
const fieldErrorSchema = omit(errorSchema, [ERRORS_KEY]);
|
||||||
|
const displayLabel = schemaUtils.getDisplayLabel(schema, uiSchema, globalUiOptions);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UnionEnumWidget
|
||||||
|
id={`${idSchema.$id}${schema.oneOf ? '__oneof_select' : '__anyof_select'}`}
|
||||||
|
name={`${name}${schema.oneOf ? '__oneof_select' : '__anyof_select'}`}
|
||||||
|
schema={schema}
|
||||||
|
uiSchema={uiSchema}
|
||||||
|
onChange={onChange}
|
||||||
|
onBlur={onBlur}
|
||||||
|
onFocus={onFocus}
|
||||||
|
disabled={disabled || isEmpty(options)}
|
||||||
|
multiple={false}
|
||||||
|
rawErrors={rawErrors}
|
||||||
|
errorSchema={fieldErrorSchema}
|
||||||
|
value={formData}
|
||||||
|
options={{enumOptions}}
|
||||||
|
registry={registry}
|
||||||
|
formContext={formContext}
|
||||||
|
placeholder={placeholder}
|
||||||
|
autocomplete={autocomplete}
|
||||||
|
autofocus={autofocus}
|
||||||
|
label={title ?? name}
|
||||||
|
hideLabel={!displayLabel}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UnionEnumField;
|
||||||
40
gui/app/src/common/crud/widgets/union-enum.tsx
Normal file
40
gui/app/src/common/crud/widgets/union-enum.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import {FieldProps, WidgetProps} from "@rjsf/utils";
|
||||||
|
import AnyOfField from "@rjsf/core/lib/components/fields/MultiSchemaField";
|
||||||
|
import {ListSubheader, MenuItem, Select} from "@mui/material";
|
||||||
|
import {useState} from "react";
|
||||||
|
import Autocomplete from "@mui/material/Autocomplete";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
|
||||||
|
export const UnionEnumWidget = (props: WidgetProps) => {
|
||||||
|
const {
|
||||||
|
options,
|
||||||
|
value,
|
||||||
|
} = props;
|
||||||
|
const [selectedValue, setSelectedValue] = useState(null);
|
||||||
|
|
||||||
|
|
||||||
|
if (! selectedValue && value && options.enumOptions) {
|
||||||
|
for (const opt of options.enumOptions){
|
||||||
|
if (opt.value == value) {
|
||||||
|
setSelectedValue(opt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Autocomplete
|
||||||
|
value={selectedValue}
|
||||||
|
onChange={(event, newValue) => {
|
||||||
|
setSelectedValue(newValue);
|
||||||
|
props.onChange(newValue.value);
|
||||||
|
}}
|
||||||
|
options={options.enumOptions}
|
||||||
|
groupBy={(option) => option.type}
|
||||||
|
getOptionLabel={(option) => option.title}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField {...params} label={ props.label } variant="outlined" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user