Customizing ArrayField template to control numbers of items per row (in a json schema stardardish way)
This commit is contained in:
@@ -159,7 +159,7 @@ class Contract(CrudDocument):
|
|||||||
title: str = Field(title="Titre")
|
title: str = Field(title="Titre")
|
||||||
parties: List[Party] = Field(title="Parties")
|
parties: List[Party] = Field(title="Parties")
|
||||||
provisions: List[Provision] = Field(
|
provisions: List[Provision] = Field(
|
||||||
props={"items-per-row": "1", "numbered": True},
|
props={"items_per_row": "1", "numbered": True},
|
||||||
title='Clauses'
|
title='Clauses'
|
||||||
)
|
)
|
||||||
status: ContractStatus = Field(default=ContractStatus.published, title="Statut")
|
status: ContractStatus = Field(default=ContractStatus.published, title="Statut")
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class ContractDraftCreate(Writer):
|
|||||||
title: str = Field(title='Titre')
|
title: str = Field(title='Titre')
|
||||||
parties: List[DraftParty] = Field(title='Parties')
|
parties: List[DraftParty] = Field(title='Parties')
|
||||||
provisions: List[DraftProvision] = Field(
|
provisions: List[DraftProvision] = Field(
|
||||||
props={"items-per-row": "1", "numbered": True},
|
props={"items_per_row": "1", "numbered": True},
|
||||||
title='Clauses'
|
title='Clauses'
|
||||||
)
|
)
|
||||||
variables: List[DictionaryEntry] = Field(
|
variables: List[DictionaryEntry] = Field(
|
||||||
@@ -59,7 +59,10 @@ class PartyRead(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class ContractRead(Reader, Contract):
|
class ContractRead(Reader, Contract):
|
||||||
parties: List[PartyRead]
|
parties: List[PartyRead] = Field(
|
||||||
|
props={"items_per_row": "2"},
|
||||||
|
title='Parties'
|
||||||
|
)
|
||||||
lawyer: ForeignEntityRead
|
lawyer: ForeignEntityRead
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Individual(EntityType):
|
|||||||
lastname: Indexed(str) = Field(title='Nom de famille')
|
lastname: Indexed(str) = Field(title='Nom de famille')
|
||||||
surnames: List[Indexed(str)] = Field(
|
surnames: List[Indexed(str)] = Field(
|
||||||
default=[],
|
default=[],
|
||||||
props={"items-per-row": "4", "numbered": True},
|
props={"items_per_row": "4", "numbered": True},
|
||||||
title="Surnoms"
|
title="Surnoms"
|
||||||
)
|
)
|
||||||
day_of_birth: Optional[date] = Field(default=None, title='Date de naissance')
|
day_of_birth: Optional[date] = Field(default=None, title='Date de naissance')
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class ContractTemplateCreate(Writer):
|
|||||||
parties: List[PartyTemplate] = Field(default=[], title="Parties")
|
parties: List[PartyTemplate] = Field(default=[], title="Parties")
|
||||||
provisions: List[ProvisionTemplateReference] = Field(
|
provisions: List[ProvisionTemplateReference] = Field(
|
||||||
default=[],
|
default=[],
|
||||||
props={"items-per-row": "1", "numbered": True},
|
props={"items_per_row": "1", "numbered": True},
|
||||||
title="Clauses"
|
title="Clauses"
|
||||||
)
|
)
|
||||||
variables: List[DictionaryEntry] = Field(
|
variables: List[DictionaryEntry] = Field(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import Form from "@rjsf/mui";
|
|||||||
import { RegistryFieldsType, RegistryWidgetsType, RJSFSchema, UiSchema } from "@rjsf/utils";
|
import { RegistryFieldsType, RegistryWidgetsType, RJSFSchema, UiSchema } from "@rjsf/utils";
|
||||||
import CrudTextWidget from "./widgets/crud-text-widget";
|
import CrudTextWidget from "./widgets/crud-text-widget";
|
||||||
import UnionEnumField from "./fields/union-enum";
|
import UnionEnumField from "./fields/union-enum";
|
||||||
|
import ArrayFieldTemplate from "./templates/ArrayFieldTemplate"
|
||||||
import { ResourceContext } from "../contexts/ResourceContext";
|
import { ResourceContext } from "../contexts/ResourceContext";
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
@@ -24,6 +25,10 @@ export const customFields: RegistryFieldsType = {
|
|||||||
AnyOfField: UnionEnumField
|
AnyOfField: UnionEnumField
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const customTemplates = {
|
||||||
|
ArrayFieldTemplate
|
||||||
|
}
|
||||||
|
|
||||||
export const BaseForm: React.FC<BaseFormProps> = (props) => {
|
export const BaseForm: React.FC<BaseFormProps> = (props) => {
|
||||||
const { schema, uiSchema, resourceBasePath, formData, children, onSubmit, onChange } = props;
|
const { schema, uiSchema, resourceBasePath, formData, children, onSubmit, onChange } = props;
|
||||||
|
|
||||||
@@ -38,6 +43,7 @@ export const BaseForm: React.FC<BaseFormProps> = (props) => {
|
|||||||
omitExtraData={true}
|
omitExtraData={true}
|
||||||
widgets={customWidgets}
|
widgets={customWidgets}
|
||||||
fields={customFields}
|
fields={customFields}
|
||||||
|
templates={customTemplates}
|
||||||
onChange={(e, id) => onChange != undefined && onChange(e.formData)}
|
onChange={(e, id) => onChange != undefined && onChange(e.formData)}
|
||||||
children={children}
|
children={children}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Grid2 from '@mui/material/Grid2';
|
||||||
|
import Paper from '@mui/material/Paper';
|
||||||
|
import {
|
||||||
|
getTemplate,
|
||||||
|
getUiOptions,
|
||||||
|
ArrayFieldTemplateProps,
|
||||||
|
ArrayFieldTemplateItemType,
|
||||||
|
FormContextType,
|
||||||
|
} from '@rjsf/utils';
|
||||||
|
import { CrudTextRJSFSchema } from "../widgets/crud-text-widget";
|
||||||
|
|
||||||
|
/** The `ArrayFieldTemplate` component is the template used to render all items in an array.
|
||||||
|
*
|
||||||
|
* @param props - The `ArrayFieldTemplateItemType` props for the component
|
||||||
|
*/
|
||||||
|
export default function ArrayFieldTemplate<
|
||||||
|
T = any,
|
||||||
|
S extends CrudTextRJSFSchema = CrudTextRJSFSchema,
|
||||||
|
F extends FormContextType = any
|
||||||
|
>(props: ArrayFieldTemplateProps<T, S, F>) {
|
||||||
|
const { canAdd, disabled, idSchema, uiSchema, items, onAddClick, readonly, registry, required, schema, title } =
|
||||||
|
props;
|
||||||
|
|
||||||
|
let gridSize = 12;
|
||||||
|
if (schema.props) {
|
||||||
|
if (schema.props.hasOwnProperty("items_per_row")) {
|
||||||
|
gridSize = gridSize / schema.props.items_per_row;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const uiOptions = getUiOptions<T, S, F>(uiSchema);
|
||||||
|
const ArrayFieldDescriptionTemplate = getTemplate<'ArrayFieldDescriptionTemplate', T, S, F>(
|
||||||
|
'ArrayFieldDescriptionTemplate',
|
||||||
|
registry,
|
||||||
|
uiOptions
|
||||||
|
);
|
||||||
|
const ArrayFieldItemTemplate = getTemplate<'ArrayFieldItemTemplate', T, S, F>(
|
||||||
|
'ArrayFieldItemTemplate',
|
||||||
|
registry,
|
||||||
|
uiOptions
|
||||||
|
);
|
||||||
|
const ArrayFieldTitleTemplate = getTemplate<'ArrayFieldTitleTemplate', T, S, F>(
|
||||||
|
'ArrayFieldTitleTemplate',
|
||||||
|
registry,
|
||||||
|
uiOptions
|
||||||
|
);
|
||||||
|
// Button templates are not overridden in the uiSchema
|
||||||
|
const {
|
||||||
|
ButtonTemplates: { AddButton },
|
||||||
|
} = registry.templates;
|
||||||
|
return (
|
||||||
|
<Paper elevation={2}>
|
||||||
|
<Box p={2}>
|
||||||
|
<ArrayFieldTitleTemplate
|
||||||
|
idSchema={idSchema}
|
||||||
|
title={uiOptions.title || title}
|
||||||
|
schema={schema}
|
||||||
|
uiSchema={uiSchema}
|
||||||
|
required={required}
|
||||||
|
registry={registry}
|
||||||
|
/>
|
||||||
|
<ArrayFieldDescriptionTemplate
|
||||||
|
idSchema={idSchema}
|
||||||
|
description={uiOptions.description || schema.description}
|
||||||
|
schema={schema}
|
||||||
|
uiSchema={uiSchema}
|
||||||
|
registry={registry}
|
||||||
|
/>
|
||||||
|
<Grid2 container justifyContent='flex-end'>
|
||||||
|
{items &&
|
||||||
|
items.map(({ key, ...itemProps }: ArrayFieldTemplateItemType<T, S, F>) => (
|
||||||
|
<Grid2 key={key} size={gridSize} ><ArrayFieldItemTemplate key={key} {...itemProps} /></Grid2>
|
||||||
|
))}
|
||||||
|
</Grid2>
|
||||||
|
{canAdd && (
|
||||||
|
<Grid2 container justifyContent='flex-end'>
|
||||||
|
<Grid2>
|
||||||
|
<Box mt={2}>
|
||||||
|
<AddButton
|
||||||
|
className='array-item-add'
|
||||||
|
onClick={onAddClick}
|
||||||
|
disabled={disabled || readonly}
|
||||||
|
uiSchema={uiSchema}
|
||||||
|
registry={registry}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user