Skip to content

Commit 8cef956

Browse files
author
Ruben van Leeuwen
committed
1714: Fixes rendering elements
1 parent 6fd89c1 commit 8cef956

File tree

7 files changed

+66
-66
lines changed

7 files changed

+66
-66
lines changed

frontend/packages/pydantic-forms/src/components/componentMatcher.tsx

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,54 @@
1+
import { useForm } from 'react-hook-form';
2+
3+
import { z } from 'zod';
4+
5+
import defaultComponentMatchers from '@/components/defaultComponentMatchers';
16
import { TextField } from '@/components/fields';
2-
import { getMatcher } from '@/core/helper';
37
import type {
48
ElementMatch,
59
Properties,
10+
PydanticComponentMatcher,
611
PydanticFormComponents,
12+
PydanticFormField,
713
PydanticFormsContextConfig,
814
} from '@/types';
915

16+
export const getMatcher = (
17+
customComponentMatcher: PydanticFormsContextConfig['componentMatcher'],
18+
) => {
19+
const componentMatchers = customComponentMatcher
20+
? customComponentMatcher(defaultComponentMatchers)
21+
: defaultComponentMatchers;
22+
23+
return (field: PydanticFormField): PydanticComponentMatcher | undefined => {
24+
return componentMatchers.find(({ matcher }) => {
25+
return matcher(field);
26+
});
27+
};
28+
};
29+
30+
export const getClientSideValidationRule = (
31+
field: PydanticFormField,
32+
rhf?: ReturnType<typeof useForm>,
33+
customComponentMatcher?: PydanticFormsContextConfig['componentMatcher'],
34+
) => {
35+
const matcher = getMatcher(customComponentMatcher);
36+
37+
const componentMatch = matcher(field);
38+
39+
let validationRule = componentMatch?.validator?.(field, rhf) ?? z.string();
40+
41+
if (!field.required) {
42+
validationRule = validationRule.optional();
43+
}
44+
45+
if (field.validations.isNullable) {
46+
validationRule = validationRule.nullable();
47+
}
48+
49+
return validationRule;
50+
};
51+
1052
export const componentMatcher = (
1153
properties: Properties,
1254
customComponentMatcher: PydanticFormsContextConfig['componentMatcher'],

frontend/packages/pydantic-forms/src/components/fields/ObjectField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const ObjectField = ({
1515
pydanticFormField.properties || {},
1616
config?.componentMatcher,
1717
);
18-
console.log('components: ' + pydanticFormField.id, components);
18+
1919
return (
2020
<div>
2121
<h1>{pydanticFormField.title}</h1>

frontend/packages/pydantic-forms/src/components/render/FormRenderer.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import type { FormRenderer as Renderer } from '@/types';
66

77
export const FormRenderer: Renderer = ({ pydanticFormComponents }) => {
88
const formSections = getFieldBySection(pydanticFormComponents);
9-
console.log(formSections);
109
const sections = formSections.map((section) => (
1110
<RenderSections
1211
section={section}

frontend/packages/pydantic-forms/src/core/helper.ts

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66
import { ControllerRenderProps, FieldValues, useForm } from 'react-hook-form';
77

8-
import defaultComponentMatchers from '@/components/defaultComponentMatchers';
98
import {
109
Properties,
1110
PydanticFormApiResponse,
@@ -18,7 +17,6 @@ import {
1817
PydanticFormFieldValidations,
1918
PydanticFormPropertySchemaParsed,
2019
PydanticFormSchema,
21-
PydanticFormsContextConfig,
2220
} from '@/types';
2321

2422
/**
@@ -169,7 +167,6 @@ export const getFieldLabelById = (
169167
formSchema?: PydanticFormSchema,
170168
) => {
171169
const fieldMap = getFlatFieldMap(formSchema?.properties ?? {});
172-
console.log('fieldMap', fieldMap);
173170
return fieldMap.has(fieldId) ? fieldMap.get(fieldId)?.title : fieldId;
174171
};
175172

@@ -304,17 +301,14 @@ export const getFieldBySection = (components: PydanticFormComponents) => {
304301
*/
305302
export const getFormValuesFromFieldOrLabels = (
306303
pydanticFormSchema: PydanticFormSchema,
304+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
307305
labelData?: Record<string, any>,
308306
) => {
309-
// NOTE: PydanticFormSchema has recursive property ids at this point
310-
// The data in label data is flat so we need to take care of that
311-
312307
const fieldValues: Record<string, string> = {};
313308

314-
/*
315309
const includedFields: string[] = [];
316310

317-
for (const field of fields) {
311+
for (const [, field] of Object.entries(pydanticFormSchema.properties)) {
318312
includedFields.push(field.id);
319313

320314
if (typeof field.default === 'undefined') {
@@ -331,7 +325,6 @@ export const getFormValuesFromFieldOrLabels = (
331325
}
332326
}
333327
}
334-
*/
335328

336329
return fieldValues;
337330
};
@@ -384,17 +377,3 @@ export const rhfTriggerValidationsOnChange =
384377
// https://github.com/react-hook-form/react-hook-form/issues/10832
385378
rhf.trigger(field.name);
386379
};
387-
388-
export const getMatcher = (
389-
customComponentMatcher?: PydanticFormsContextConfig['componentMatcher'],
390-
) => {
391-
const componentMatchers = customComponentMatcher
392-
? customComponentMatcher(defaultComponentMatchers)
393-
: defaultComponentMatchers;
394-
395-
return (field: PydanticFormField) => {
396-
return componentMatchers.find(({ matcher }) => {
397-
return matcher(field);
398-
});
399-
};
400-
};

frontend/packages/pydantic-forms/src/core/hooks/useGetZodValidator.tsx

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,14 @@ import { useForm } from 'react-hook-form';
1212

1313
import { z } from 'zod';
1414

15-
import { getFlatFieldMap, getMatcher } from '@/core/helper';
15+
import { getClientSideValidationRule } from '@/components/componentMatcher';
16+
import { getFlatFieldMap } from '@/core/helper';
1617
import {
1718
CustomValidationRule,
18-
PydanticFormField,
1919
PydanticFormSchema,
2020
PydanticFormsContextConfig,
2121
} from '@/types';
2222

23-
type PropertyMap = Map<string, PydanticFormField>;
24-
25-
const getClientSideValidationRule = (
26-
field: PydanticFormField,
27-
rhf?: ReturnType<typeof useForm>,
28-
customComponentMatcher?: PydanticFormsContextConfig['componentMatcher'],
29-
) => {
30-
const matcher = getMatcher(customComponentMatcher);
31-
32-
const componentMatch = matcher(field);
33-
34-
let validationRule = componentMatch?.validator?.(field, rhf) ?? z.string();
35-
36-
if (!field.required) {
37-
validationRule = validationRule.optional();
38-
}
39-
40-
if (field.validations.isNullable) {
41-
validationRule = validationRule.nullable();
42-
}
43-
44-
return validationRule;
45-
};
46-
4723
export const useGetZodValidator = (
4824
pydanticFormSchema?: PydanticFormSchema,
4925
rhf?: ReturnType<typeof useForm>,
@@ -76,5 +52,5 @@ export const useGetZodValidator = (
7652
{},
7753
),
7854
);
79-
}, [customValidationRule, rhf, pydanticFormSchema]);
55+
}, [customValidationRule, rhf, pydanticFormSchema, customComponentMatcher]);
8056
};

frontend/packages/pydantic-forms/src/core/hooks/usePydanticFormParser.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ const parseProperties = (
4545
) => {
4646
if (!parsedSchema || !parsedSchema.properties) return {};
4747

48-
const p = Object.entries(parsedSchema.properties);
49-
const parsedProperties = p.reduce(
48+
const schemaProperties = Object.entries(parsedSchema.properties);
49+
const parsedProperties = schemaProperties.reduce(
5050
(propertiesObject: Properties, [propertyId, propertySchema]) => {
5151
const options = getFieldOptions(propertySchema);
5252
const fieldOptionsEntry = getFieldAllOfAnyOfEntry(propertySchema);
@@ -73,9 +73,13 @@ const parseProperties = (
7373
options: options.options,
7474
isEnumField: options.isOptionsField,
7575
default: propertySchema.default,
76-
required: !!parsedSchema.required?.includes(propertyId),
76+
// TODO: I think object properties should never be required only their properties are or aren't. Should we fix this in the backend?
77+
required:
78+
propertySchema.type === PydanticFormFieldType.OBJECT
79+
? false
80+
: !!parsedSchema.required?.includes(propertyId),
7781
attributes: getFieldAttributes(propertySchema),
78-
schemaProperty: propertySchema,
82+
schema: propertySchema,
7983
validations: getFieldValidation(propertySchema),
8084
columns: 6, // TODO: Is this still relevant?
8185
properties: parseProperties(
@@ -130,7 +134,7 @@ export const usePydanticFormParser = (
130134
return formStructureMutator
131135
? formStructureMutator(pydanticFormSchema)
132136
: pydanticFormSchema;
133-
}, [formStructureMutator, parsedSchema]);
137+
}, [formStructureMutator, parsedSchema, formLabels, fieldDetailProvider]);
134138

135139
return {
136140
pydanticFormSchema,

frontend/packages/pydantic-forms/src/types.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export interface PydanticFormField {
9393
columns: number;
9494
required: boolean;
9595
isEnumField: boolean;
96-
schemaProperty: PydanticFormPropertySchemaParsed;
96+
schema: PydanticFormPropertySchemaParsed;
9797
validations: PydanticFormFieldValidations;
9898
attributes: PydanticFormFieldAttributes;
9999

@@ -319,7 +319,8 @@ export type PydanticFormLabelProvider = ({
319319
}: {
320320
formKey: string;
321321
id?: string | null;
322-
}) => Promise<Record<string, string>>;
322+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
323+
}) => Promise<Record<string, any>>;
323324

324325
// will return column
325326
export type PydanticFormLayoutColumnProvider = (fieldId: string) => number;
@@ -368,6 +369,7 @@ export interface PydanticFormApiResponse {
368369

369370
export interface PydanticFormBaseSchema {
370371
title?: string;
372+
type: PydanticFormFieldType.OBJECT;
371373
description?: string;
372374
additionalProperties?: boolean;
373375
required?: string[];
@@ -380,23 +382,21 @@ export interface PydanticFormBaseSchema {
380382
};
381383
}
382384

383-
export interface PydanticFormSchema extends PydanticFormBaseSchema {
384-
type: PydanticFormFieldType.OBJECT;
385+
export interface PydanticFormSchema
386+
extends Omit<PydanticFormBaseSchema, '$defs'> {
385387
properties: Properties;
386388
}
387389

388390
export interface PydanticFormSchemaRawJson extends PydanticFormBaseSchema {
389-
type: PydanticFormFieldType.OBJECT;
390391
properties: RawJsonProperties;
391392
}
392393

393394
export interface PydanticFormSchemaParsed extends PydanticFormBaseSchema {
394-
type: 'object';
395395
properties: ParsedProperties;
396396
}
397397

398398
export interface PydanticFormPropertySchemaParsed
399-
extends PydanticFormBaseSchema,
399+
extends Omit<PydanticFormBaseSchema, 'type'>,
400400
PydanticFormFieldValidations {
401401
type: PydanticFormFieldType;
402402

@@ -444,7 +444,7 @@ export interface PydanticFormFieldAnyOfItemParsed
444444
}
445445

446446
export interface PydanticFormPropertySchemaRawJson
447-
extends PydanticFormBaseSchema,
447+
extends Omit<PydanticFormBaseSchema, 'type'>,
448448
PydanticFormFieldValidations,
449449
JsonSchemaRef {
450450
type: PydanticFormFieldType;

0 commit comments

Comments
 (0)