From e97ae5798d566959b6b7b3315c7fc60f2688fdc6 Mon Sep 17 00:00:00 2001 From: Ruben van Leeuwen Date: Tue, 18 Mar 2025 12:58:38 +0100 Subject: [PATCH 1/6] Fixes applying labels --- .../src/components/fields/FieldWrap.tsx | 8 +------- .../src/components/fields/FormRow.tsx | 20 +++++++++---------- .../src/core/PydanticFormContextProvider.tsx | 4 ++-- .../src/core/hooks/useLabelProvider.tsx | 7 +++++-- .../src/core/hooks/usePydanticFormParser.tsx | 11 +++++----- frontend/packages/pydantic-forms/src/types.ts | 10 +++++++--- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx b/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx index 5915678..4d1c886 100644 --- a/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx +++ b/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx @@ -10,7 +10,6 @@ import React from 'react'; import type { ControllerFieldState } from 'react-hook-form'; -import ResetNullableFieldTrigger from '@/components/form/ResetNullableFieldTrigger'; import { usePydanticFormContext } from '@/core'; import { PydanticFormField } from '@/types'; @@ -36,12 +35,7 @@ export const FieldWrap = ({ return ( - {pydanticFormField.title} - - - } + title={pydanticFormField.title} description={pydanticFormField.description} required={pydanticFormField.required} isInvalid={!!isInvalid} diff --git a/frontend/packages/pydantic-forms/src/components/fields/FormRow.tsx b/frontend/packages/pydantic-forms/src/components/fields/FormRow.tsx index fc79d36..2d73e57 100644 --- a/frontend/packages/pydantic-forms/src/components/fields/FormRow.tsx +++ b/frontend/packages/pydantic-forms/src/components/fields/FormRow.tsx @@ -3,7 +3,7 @@ import type { HTMLAttributes, ReactElement, ReactNode } from 'react'; type FormRowProps = { children: ReactElement; - label?: ReactNode; + title: string; isInvalid?: boolean; error?: ReactNode | ReactNode[]; description?: string; @@ -12,19 +12,17 @@ type FormRowProps = { export const FormRow = ({ children, - label, - isInvalid, + title, error, - ...rest + description, + required, }: FormRowProps) => { - // TODO: readd required, description, classname return ( -
)}> - {label && ( - - )} +
+ + {description &&
{description}
} {children} {error}
diff --git a/frontend/packages/pydantic-forms/src/core/PydanticFormContextProvider.tsx b/frontend/packages/pydantic-forms/src/core/PydanticFormContextProvider.tsx index 2a69f5d..9734c28 100644 --- a/frontend/packages/pydantic-forms/src/core/PydanticFormContextProvider.tsx +++ b/frontend/packages/pydantic-forms/src/core/PydanticFormContextProvider.tsx @@ -135,7 +135,7 @@ function PydanticFormContextProvider({ const { pydanticFormSchema, isLoading: isParsingSchema } = usePydanticFormParser( rawSchema, - formLabels, + formLabels?.labels, fieldDetailProvider, formStructureMutator, ); @@ -223,7 +223,7 @@ function PydanticFormContextProvider({ } const initialData = getFormValuesFromFieldOrLabels(pydanticFormSchema, { - ...formLabels, + ...formLabels?.data, ...customData, }); diff --git a/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx b/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx index 70b67ae..3c8a901 100644 --- a/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx +++ b/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx @@ -16,7 +16,10 @@ */ import useSWR, { SWRConfiguration } from 'swr'; -import { PydanticFormLabelProvider } from '@/types'; +import { + PydanticFormLabelProvider, + PydanticFormLabelProviderResponse, +} from '@/types'; export function useLabelProvider( labelProvider?: PydanticFormLabelProvider, @@ -25,7 +28,7 @@ export function useLabelProvider( cacheKey?: number, swrConfig?: SWRConfiguration, ) { - return useSWR | undefined>( + return useSWR( // cache key [labelProvider, formKey, id, swrConfig, cacheKey], diff --git a/frontend/packages/pydantic-forms/src/core/hooks/usePydanticFormParser.tsx b/frontend/packages/pydantic-forms/src/core/hooks/usePydanticFormParser.tsx index 8fc0e6e..c398280 100644 --- a/frontend/packages/pydantic-forms/src/core/hooks/usePydanticFormParser.tsx +++ b/frontend/packages/pydantic-forms/src/core/hooks/usePydanticFormParser.tsx @@ -54,11 +54,12 @@ const parseProperties = ( const parsedProperty: PydanticFormField = { id, - title: translateLabel( - propertyId, - propertySchema.title, - formLabels, - ), + title: + translateLabel( + propertyId, + propertySchema.title, + formLabels, + ) || propertyId, description: translateLabel( `${propertyId}_info`, propertySchema.description, diff --git a/frontend/packages/pydantic-forms/src/types.ts b/frontend/packages/pydantic-forms/src/types.ts index da2973e..e9aaf11 100644 --- a/frontend/packages/pydantic-forms/src/types.ts +++ b/frontend/packages/pydantic-forms/src/types.ts @@ -83,7 +83,7 @@ export enum PydanticFormState { export interface PydanticFormField { id: string; - title?: string; + title: string; description?: string; type: PydanticFormFieldType; format: PydanticFormFieldFormat; @@ -320,8 +320,7 @@ export type PydanticFormLabelProvider = ({ }: { formKey: string; id?: string | null; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -}) => Promise>; +}) => Promise; // will return column export type PydanticFormLayoutColumnProvider = (fieldId: string) => number; @@ -360,6 +359,11 @@ export type PydanticFormCustomValidationRuleFn = ( rhf?: ReturnType, ) => Zod.ZodTypeAny | undefined; +export interface PydanticFormLabelProviderResponse { + labels: Record; + data: Record; +} + export interface PydanticFormApiResponse { detail?: string; status: number; From 58ac9d857dbc0774704290ac2c726dd02a5b5dcd Mon Sep 17 00:00:00 2001 From: Ruben van Leeuwen Date: Tue, 18 Mar 2025 13:23:23 +0100 Subject: [PATCH 2/6] Removes some anys --- frontend/packages/pydantic-forms/src/core/helper.ts | 3 +-- .../pydantic-forms/src/core/hooks/useApiProvider.tsx | 9 +-------- .../src/core/hooks/useCustomDataProvider.tsx | 7 +++++-- .../pydantic-forms/src/core/hooks/useLabelProvider.tsx | 2 -- frontend/packages/pydantic-forms/src/types.ts | 8 +++----- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/frontend/packages/pydantic-forms/src/core/helper.ts b/frontend/packages/pydantic-forms/src/core/helper.ts index 550d606..a77bc5f 100644 --- a/frontend/packages/pydantic-forms/src/core/helper.ts +++ b/frontend/packages/pydantic-forms/src/core/helper.ts @@ -301,8 +301,7 @@ export const getFieldBySection = (components: PydanticFormComponents) => { */ export const getFormValuesFromFieldOrLabels = ( pydanticFormSchema: PydanticFormSchema, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - labelData?: Record, + labelData?: Record, ) => { const fieldValues: Record = {}; diff --git a/frontend/packages/pydantic-forms/src/core/hooks/useApiProvider.tsx b/frontend/packages/pydantic-forms/src/core/hooks/useApiProvider.tsx index 126b687..c6496e8 100644 --- a/frontend/packages/pydantic-forms/src/core/hooks/useApiProvider.tsx +++ b/frontend/packages/pydantic-forms/src/core/hooks/useApiProvider.tsx @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - /** * Pydantic Forms * @@ -22,12 +20,7 @@ import type { PydanticFormMetaData, } from '@/types'; -const ignoreApiErrors = async ( - req: Promise, - // ignoreCodes: number[], - // eslint-disable-next-line @typescript-eslint/no-explicit-any -): Promise => { - // TODO: What to use these for: ignoreCodes +const ignoreApiErrors = async (req: Promise): Promise => { try { return await req; } catch (error) { diff --git a/frontend/packages/pydantic-forms/src/core/hooks/useCustomDataProvider.tsx b/frontend/packages/pydantic-forms/src/core/hooks/useCustomDataProvider.tsx index b10782c..7c45d12 100644 --- a/frontend/packages/pydantic-forms/src/core/hooks/useCustomDataProvider.tsx +++ b/frontend/packages/pydantic-forms/src/core/hooks/useCustomDataProvider.tsx @@ -1,12 +1,15 @@ import useSWR from 'swr'; -import { PydanticFormCustomDataProvider, PydanticFormLabels } from '@/types'; +import { + PydanticFormCustomDataProvider, + PydanticFormLabelProviderResponse, +} from '@/types'; export const useCustomDataProvider = ( customDataProviderCacheKey: number, customDataProvider?: PydanticFormCustomDataProvider, ) => { - return useSWR( + return useSWR( // cache key [`pydanticFormsDataProvider-${customDataProviderCacheKey}`], diff --git a/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx b/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx index 3c8a901..f7e9de9 100644 --- a/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx +++ b/frontend/packages/pydantic-forms/src/core/hooks/useLabelProvider.tsx @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ - /** * Pydantic Forms * diff --git a/frontend/packages/pydantic-forms/src/types.ts b/frontend/packages/pydantic-forms/src/types.ts index e9aaf11..6bc0c94 100644 --- a/frontend/packages/pydantic-forms/src/types.ts +++ b/frontend/packages/pydantic-forms/src/types.ts @@ -308,11 +308,9 @@ interface PydanticFormComponent { export type PydanticFormComponents = PydanticFormComponent[]; -export type PydanticFormCustomDataProvider = () => Promise; - -export interface PydanticFormLabels { - [key: string]: string[] | number[] | string | number | null; -} +export type PydanticFormCustomDataProvider = () => Promise< + PydanticFormLabelProviderResponse['data'] +>; export type PydanticFormLabelProvider = ({ formKey, From 839fb768547378339e97f80c674b79f8f20f13d3 Mon Sep 17 00:00:00 2001 From: Ruben van Leeuwen Date: Tue, 18 Mar 2025 13:23:39 +0100 Subject: [PATCH 3/6] Adds Changeset --- frontend/.changeset/khaki-schools-move.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 frontend/.changeset/khaki-schools-move.md diff --git a/frontend/.changeset/khaki-schools-move.md b/frontend/.changeset/khaki-schools-move.md new file mode 100644 index 0000000..3efbd4f --- /dev/null +++ b/frontend/.changeset/khaki-schools-move.md @@ -0,0 +1,5 @@ +--- +'pydantic-forms': patch +--- + +Fixes form labels From 5e61af33e87066dde42b1e5efba7ad84bf33bde4 Mon Sep 17 00:00:00 2001 From: Ruben van Leeuwen Date: Tue, 18 Mar 2025 15:37:32 +0100 Subject: [PATCH 4/6] 1719: Makes rowRenderer configurable --- .../src/components/fields/FieldWrap.tsx | 16 ++++++---------- .../src/components/render/RenderForm.tsx | 4 +++- .../pydantic-forms/src/core/WrapFieldElement.tsx | 7 ++----- frontend/packages/pydantic-forms/src/types.ts | 10 ++++++++++ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx b/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx index 4d1c886..fe2e243 100644 --- a/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx +++ b/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx @@ -17,24 +17,20 @@ import { FormRow } from './FormRow'; interface FieldWrapProps { pydanticFormField: PydanticFormField; - fieldState: ControllerFieldState; children: React.ReactNode; } -export const FieldWrap = ({ - pydanticFormField, - fieldState, - children, -}: FieldWrapProps) => { - const { errorDetails } = usePydanticFormContext(); - +export const FieldWrap = ({ pydanticFormField, children }: FieldWrapProps) => { + const { errorDetails, rhf, config } = usePydanticFormContext(); + const RowRenderer = config?.rowRenderer ? config.rowRenderer : FormRow; + const fieldState = rhf.getFieldState(pydanticFormField.id); const errorMsg = errorDetails?.mapped?.[pydanticFormField.id]?.msg ?? fieldState.error?.message; const isInvalid = errorMsg ?? fieldState.invalid; return ( -
{children}
-
+ ); }; diff --git a/frontend/packages/pydantic-forms/src/components/render/RenderForm.tsx b/frontend/packages/pydantic-forms/src/components/render/RenderForm.tsx index e2d4ecb..f3fa168 100644 --- a/frontend/packages/pydantic-forms/src/components/render/RenderForm.tsx +++ b/frontend/packages/pydantic-forms/src/components/render/RenderForm.tsx @@ -67,7 +67,9 @@ const RenderForm = (contextProps: PydanticFormContextProps) => { return (
- {title !== false &&

{title ?? pydanticFormSchema.title}

} + {title !== false && title !== 'undefined' && ( +

{title ?? pydanticFormSchema.title}

+ )} {headerComponent} diff --git a/frontend/packages/pydantic-forms/src/core/WrapFieldElement.tsx b/frontend/packages/pydantic-forms/src/core/WrapFieldElement.tsx index b9aab3f..f96f47f 100644 --- a/frontend/packages/pydantic-forms/src/core/WrapFieldElement.tsx +++ b/frontend/packages/pydantic-forms/src/core/WrapFieldElement.tsx @@ -18,7 +18,7 @@ export const WrapFieldElement = ({ { + render={({ field }) => { const { onChange, onBlur, value, name, ref } = field; const onChangeHandle = (val: string) => { onChange(val); @@ -30,10 +30,7 @@ export const WrapFieldElement = ({ }; return ( - + , ) => z.ZodTypeAny; +export type RowRenderer = React.JSXElementConstructor<{ + title: string; + description?: string; + required?: boolean; + isInvalid?: boolean; + error?: string; + children: React.ReactNode; +}>; + export interface PydanticFormZodValidationPresets { [type: string]: PydanticFormZodValidationFn; } @@ -286,6 +295,7 @@ export interface PydanticFormsContextConfig { formRenderer?: FormRenderer; footerRenderer?: React.JSXElementConstructor; + rowRenderer?: RowRenderer; // Extend field definitions fieldDetailProvider?: PydanticFormFieldDetailProvider; From 6878fbe52590eceb12c513e448574a5203cf4d18 Mon Sep 17 00:00:00 2001 From: Ruben van Leeuwen Date: Tue, 18 Mar 2025 15:38:20 +0100 Subject: [PATCH 5/6] Adds changeset --- frontend/.changeset/loose-boxes-fetch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 frontend/.changeset/loose-boxes-fetch.md diff --git a/frontend/.changeset/loose-boxes-fetch.md b/frontend/.changeset/loose-boxes-fetch.md new file mode 100644 index 0000000..fd24dcf --- /dev/null +++ b/frontend/.changeset/loose-boxes-fetch.md @@ -0,0 +1,5 @@ +--- +'pydantic-forms': patch +--- + +Makes rowRenderer configurable From 4300f25423c10c058d263a4babc505dea1bc3d55 Mon Sep 17 00:00:00 2001 From: Ruben van Leeuwen Date: Tue, 18 Mar 2025 15:43:21 +0100 Subject: [PATCH 6/6] 1719: Fixes linting error --- .../packages/pydantic-forms/src/components/fields/FieldWrap.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx b/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx index fe2e243..b7745c7 100644 --- a/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx +++ b/frontend/packages/pydantic-forms/src/components/fields/FieldWrap.tsx @@ -8,7 +8,6 @@ * */ import React from 'react'; -import type { ControllerFieldState } from 'react-hook-form'; import { usePydanticFormContext } from '@/core'; import { PydanticFormField } from '@/types';