Skip to content

Commit

Permalink
Handle null related fields
Browse files Browse the repository at this point in the history
  • Loading branch information
allisonking committed Jan 23, 2025
1 parent 9495837 commit 7a509bb
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,17 @@ const componentInfo: Record<InputComponent, SchemaComponentData> = {
[InputComponent.textInput]: {
name: "Input",
placeholder: "For short text",
demoComponent: ({ element }) => (
<Input
placeholder={
element.schemaName === CoreSchemaType.String ? "For short text" : "For numbers"
}
type={element.schemaName === CoreSchemaType.String ? "text" : "number"}
/>
),
demoComponent: ({ element }) => {
const isText =
element.schemaName === CoreSchemaType.String ||
element.schemaName === CoreSchemaType.Email;
return (
<Input
placeholder={isText ? "For short text" : "For numbers"}
type={isText ? "text" : "number"}
/>
);
},
},
[InputComponent.checkbox]: { name: "Checkbox", demoComponent: () => <Checkbox checked /> },
[InputComponent.datePicker]: {
Expand Down
2 changes: 1 addition & 1 deletion core/app/components/forms/FormElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const FormElement = ({
return null;
}

if (!element.schemaName || !element.component) {
if (!element.schemaName) {
return null;
}

Expand Down
61 changes: 31 additions & 30 deletions core/app/components/forms/elements/RelatedPubsElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,21 @@ import { PubFieldFormElement } from "../PubFieldFormElement";
const RelatedPubBlock = ({
pub,
onRemove,
valueComponent,
valueComponentProps,
slug,
}: {
pub: Pick<GetPubsResult[number], "title" | "id">;
onRemove: () => void;
valueComponent: ReactNode;
valueComponentProps: PubFieldFormElementProps;
slug: string;
}) => {
const { title, id } = pub;
const { watch } = useFormContext();
const [isPopoverOpen, setPopoverIsOpen] = useState(false);
const value = watch(slug);
const showValue = value != null && value !== "" && !isPopoverOpen;

return (
<div className="flex items-center justify-between rounded border border-l-[12px] border-l-emerald-100 p-3">
<div className="flex flex-col items-start gap-1 text-sm">
<span className="font-semibold">{title || id}</span>
{showValue ? (
value.toString()
) : (
<Popover open={isPopoverOpen} onOpenChange={setPopoverIsOpen}>
<PopoverTrigger asChild>
<Button
variant="link"
size="sm"
className="flex h-4 gap-1 p-0 text-blue-500"
>
{/* TODO: the type of 'add', i.e. 'Add Role' */}
Add <Plus size={12} />
</Button>
</PopoverTrigger>
<PopoverContent side="bottom">{valueComponent}</PopoverContent>
</Popover>
)}
<ConfigureRelatedValue {...valueComponentProps} slug={slug} />
</div>
<div>
<Button
Expand All @@ -80,15 +61,38 @@ type FormValue = {
[slug: string]: FieldValue[];
};

export const InnerValue = ({
export const ConfigureRelatedValue = ({
slug,
element,
...props
}: PubFieldFormElementProps & { slug: string }) => {
const configLabel = "label" in element.config ? element.config.label : undefined;
const label = configLabel || element.label || slug;

return <PubFieldFormElement {...props} element={element} slug={slug} label={label} />;
const { watch } = useFormContext();
const [isPopoverOpen, setPopoverIsOpen] = useState(false);
const value = watch(slug);
const showValue = value != null && value !== "" && !isPopoverOpen;

if (element.component === null) {
return null;
}

return showValue ? (
// TODO: this should be more sophisticated for the more complex fields
value.toString()
) : (
<Popover open={isPopoverOpen} onOpenChange={setPopoverIsOpen}>
<PopoverTrigger asChild>
<Button variant="link" size="sm" className="flex h-4 gap-1 p-0 text-blue-500">
Add {label} <Plus size={12} />
</Button>
</PopoverTrigger>
<PopoverContent side="bottom">
<PubFieldFormElement {...props} element={element} slug={slug} label={label} />
</PopoverContent>
</Popover>
);
};

export const RelatedPubsElement = ({
Expand Down Expand Up @@ -170,11 +174,8 @@ export const RelatedPubsElement = ({
pub={pubsById[item.relatedPubId]}
onRemove={handleRemovePub}
slug={innerSlug}
valueComponent={
<InnerValue
{...valueComponentProps}
slug={innerSlug}
/>
valueComponentProps={
valueComponentProps
}
/>
);
Expand Down
26 changes: 13 additions & 13 deletions core/app/components/pubs/PubEditor/PubEditorClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,15 @@ const createSchemaFromElements = (
return [slug, undefined];
}

if (schema.type !== "string") {
return [slug, Type.Optional(schema)];
}

// this allows for empty strings, which happens when you enter something
// in an input field and then delete it
// Allow fields to be empty or optional. Special case for empty strings,
// which happens when you enter something in an input field and then delete it
// TODO: reevaluate whether this should be "" or undefined
const schemaWithAllowedEmpty = Type.Union([schema, Type.Literal("")], {
error: schema.error ?? "Invalid value",
});
const schemaAllowEmpty =
schema.type === "string"
? Type.Union([schema, Type.Literal("")], {
error: schema.error ?? "Invalid value",
})
: Type.Optional(schema);

if (isRelation) {
return [
Expand All @@ -132,15 +131,16 @@ const createSchemaFromElements = (
Type.Object(
{
relatedPubId: Type.String(),
value: schemaWithAllowedEmpty,
value: schemaAllowEmpty,
},
{ additionalProperties: true }
)
{ additionalProperties: true, error: "object error" }
),
{ error: "array error" }
),
];
}

return [slug, schemaWithAllowedEmpty];
return [slug, schemaAllowEmpty];
})
)
);
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ const FormMessage = React.forwardRef<
body = String(error.message);
}
if (Array.isArray(error)) {
body = error[0]?.message;
const firstErrorIndex = error.findIndex((e) => !!e);
const firstError = error[firstErrorIndex];
body = firstError?.message ?? `Error with value at index ${firstErrorIndex}`;
}
}

Expand Down

0 comments on commit 7a509bb

Please sign in to comment.