Skip to content

Commit

Permalink
Support removing all conditions in filters
Browse files Browse the repository at this point in the history
  • Loading branch information
synzen committed Dec 24, 2024
1 parent a46fa4e commit cddb44f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import {
Button,
CloseButton,
Flex,
FormControl,
FormErrorMessage,
Menu,
MenuButton,
MenuItem,
MenuList,
Stack,
Text,
} from "@chakra-ui/react";
import { useFieldArray, useFormContext, useWatch } from "react-hook-form";
import { FieldError, useFieldArray, useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { useEffect } from "react";
import {
FilterExpression,
FilterExpressionType,
Expand All @@ -26,6 +29,7 @@ import {
} from "../../types";
import { AnyAllSelector } from "./AnyAllSelector";
import { Condition } from "./Condition";
import { getNestedField } from "../../../../utils/getNestedField";

interface Props {
onDeleted: () => void;
Expand All @@ -34,15 +38,34 @@ interface Props {
}

export const LogicalExpressionForm = ({ onDeleted, prefix = "", containerProps }: Props) => {
const { control, setValue } = useFormContext();
const {
control,
setValue,
setError,
clearErrors,
formState: { errors },
} = useFormContext();
const childrenName = `${prefix}children`;
const childrenError = getNestedField<FieldError>(errors, childrenName);
const { fields, append, remove, insert } = useFieldArray({
control,
name: `${prefix}children`,
name: childrenName,
});
const operator: LogicalExpressionOperator = useWatch({
control,
name: `${prefix}op`,
});
// console.log("🚀 ~ LogicalExpressionForm ~ errors:", errors);
// console.log("🚀 ~ useEffect ~ childrenName:", childrenName);
useEffect(() => {
if (fields.length === 0) {
setError(childrenName, {
type: "required",
});
} else if (childrenError?.type === "required") {
clearErrors(childrenName);
}
}, [fields.length, childrenError?.type]);

const { t } = useTranslation();

Expand Down Expand Up @@ -111,15 +134,6 @@ export const LogicalExpressionForm = ({ onDeleted, prefix = "", containerProps }
append(toInsert);
};

const numberOfRelational =
(
fields as Array<
FilterExpression & {
id: string;
}
>
)?.filter((child) => child?.type === FilterExpressionType.Relational).length || 0;

return (
<Stack {...containerProps}>
<Box
Expand All @@ -144,35 +158,40 @@ export const LogicalExpressionForm = ({ onDeleted, prefix = "", containerProps }
<CloseButton aria-label="Delete condition group" onClick={onDeleted} />
</Flex>
<Stack>
<Stack spacing={2} marginTop={4} width="100%">
{(fields as Array<FilterExpression & { id: string }>)?.map((child, childIndex) => {
if (child?.type === FilterExpressionType.Logical) {
return (
<LogicalExpressionForm
key={child.id}
onDeleted={() => onChildDeleted(childIndex)}
prefix={`${prefix}children.${childIndex}.`}
/>
);
}

if (child?.type === FilterExpressionType.Relational) {
return (
<Condition
key={child.id}
onDelete={() => onChildDeleted(childIndex)}
prefix={`${prefix}children.${childIndex}.`}
deletable={numberOfRelational > 1}
/>
);
}

return null;
})}
</Stack>
{!!fields.length && (
<Stack spacing={2} marginTop={4} width="100%">
{(fields as Array<FilterExpression & { id: string }>)?.map((child, childIndex) => {
if (child?.type === FilterExpressionType.Logical) {
return (
<LogicalExpressionForm
key={child.id}
onDeleted={() => onChildDeleted(childIndex)}
prefix={`${prefix}children.${childIndex}.`}
/>
);
}

if (child?.type === FilterExpressionType.Relational) {
return (
<Condition
key={child.id}
onDelete={() => onChildDeleted(childIndex)}
prefix={`${prefix}children.${childIndex}.`}
deletable
/>
);
}

return null;
})}
</Stack>
)}
<FormControl isInvalid={childrenError?.type === "required"}>
<FormErrorMessage my={4}>At least one condition is required.</FormErrorMessage>
</FormControl>
<Box>
<Menu>
<MenuButton as={Button} rightIcon={<ChevronDownIcon />} variant="ghost">
<MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
{t("features.feedConnections.components.filtersForm.addButtonText")}
</MenuButton>
<MenuList>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const FiltersForm = ({
resetField,
reset,
} = formMethods;

// @ts-ignore cyclical references in typescript types
const watchedExpression = useWatch({
control,
Expand All @@ -67,10 +68,12 @@ export const FiltersForm = ({
};

const onSaveExpression = async ({ expression: finalExpression }: FormData) => {
await onSave(finalExpression);
reset({
expression: finalExpression,
});
try {
await onSave(finalExpression);
reset({
expression: finalExpression,
});
} catch (err) {}
};

const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
Expand Down
2 changes: 1 addition & 1 deletion services/backend-api/client/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -873,7 +873,7 @@ const handlers = [
rest.patch("/api/v1/user-feeds/:feedId/connections/discord-channels/:id", (req, res, ctx) => {
return res(
ctx.delay(500),
ctx.status(400),
ctx.status(200),
ctx.json<UpdateDiscordChannelConnectionOutput>({
result: mockFeedChannelConnections[0],
})
Expand Down

0 comments on commit cddb44f

Please sign in to comment.