Skip to content

Commit

Permalink
Showing 2 changed files with 91 additions and 174 deletions.
83 changes: 42 additions & 41 deletions packages/filter/src/filter-rule/index.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,76 @@
import {
isEqualPath,
type FilterField,
type LooseFilterRule,
type StandardFnSchema,
} from "@fn-sphere/core";
import { Delete as DeleteIcon } from "@mui/icons-material";
import { type LooseFilterRule } from "@fn-sphere/core";
import { Delete as DeleteIcon, Error as ErrorIcon } from "@mui/icons-material";
import { Button, IconButton } from "@mui/material";
import { defaultMapFieldName, defaultMapFilterName } from "../utils.js";
import { useFilterRule } from "../hooks/use-filter-rule.js";
import { useRootRule } from "../hooks/use-root-rule.js";
import { createEmptyFilterGroup } from "../utils.js";
import { FieldSelect } from "./field-select.js";
import { FilterDataInput } from "./filter-data-input.js";
import { FilterSelect } from "./filter-select.js";

type FilterRuleProps = {
rule: LooseFilterRule;
filterFields: FilterField[];
mapFieldName?: (field: FilterField) => string;
mapFilterName?: (
filterSchema: StandardFnSchema,
field: FilterField,
) => string;
onChange: (rule: LooseFilterRule) => void;
onAddFilter: () => void;
onAddGroup: (operator: "and" | "or") => void;
onRemove: () => void;
};

export const FilterRule = ({
rule,
filterFields,
mapFieldName = defaultMapFieldName,
mapFilterName = defaultMapFilterName,
onChange,
onAddFilter,
onAddGroup,
onRemove,
}: FilterRuleProps) => {
const selectedField = filterFields.find((field) =>
rule.path ? isEqualPath(field.path, rule.path) : false,
);
const selectedFilter = selectedField?.filterList.find(
(filter) => filter.name === rule.name,
);
export const FilterRule = ({ rule }: FilterRuleProps) => {
const {
ruleState: { isValid },
filterableFields,
selectedField,
selectedFilter,
mapFieldName,
mapFilterName,
updateRule,
removeRule,
appendRule,
} = useFilterRule(rule);
const { getRootRule, updateRootRule } = useRootRule();

return (
<div>
<FieldSelect
rule={rule}
filterFields={filterFields}
filterableFields={filterableFields}
mapFieldName={mapFieldName}
onChange={onChange}
onChange={updateRule}
/>
<FilterSelect
selectedField={selectedField}
selectedFilter={selectedFilter}
rule={rule}
mapFilterName={mapFilterName}
onChange={onChange}
onChange={updateRule}
/>
<FilterDataInput
rule={rule}
filterSchema={selectedFilter}
onChange={onChange}
onChange={updateRule}
/>

<Button size="small" onClick={onAddFilter}>
{isValid ? null : <ErrorIcon />}
<Button
size="small"
onClick={() => {
appendRule();
}}
>
And
</Button>
<Button size="small" onClick={() => onAddGroup("and")}>
<Button
size="small"
onClick={() => {
const rootRule = getRootRule();
rootRule.conditions.push(createEmptyFilterGroup("and"));
updateRootRule(rootRule);
}}
>
Or
</Button>
<IconButton aria-label="delete" size="small" onClick={onRemove}>
<IconButton
aria-label="delete"
size="small"
onClick={() => removeRule(true)}
>
<DeleteIcon />
</IconButton>
</div>
182 changes: 49 additions & 133 deletions packages/filter/src/flatten-filter-builder.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import {
countNumberOfRules,
findFilterField,
genFilterId,
type LooseFilterGroup,
} from "@fn-sphere/core";
import { countNumberOfRules, type LooseFilterGroup } from "@fn-sphere/core";
import { Button } from "@mui/material";
import { Fragment } from "react";
import { FilterRule } from "./filter-rule/index.js";
import { FilterProvider } from "./hooks/filter-provider.js";
import type { BasicFilterProps } from "./types.js";
import { FilterGroupContainer, FilterRuleJoiner } from "./ui.js";
import {
EMPTY_ROOT_FILTER,
createEmptyRule,
defaultMapFieldName,
defaultMapFilterName,
isFlattenFilterGroup,
@@ -66,133 +61,54 @@ export const FlattenFilterBuilder = <Data,>({
);
}

const filterFields = findFilterField({
schema,
filterList,
maxDeep: deepLimit,
});

return (
<div className="filter-builder-container">
<FilterGroupContainer isRoot filterGroup={filterGroup}>
{filterGroup.conditions.map((andGroup, groupIdx) => {
return (
<Fragment key={andGroup.id}>
{groupIdx > 0 && (
<FilterRuleJoiner
operator={filterGroup.op}
joinBetween={[filterGroup.conditions[groupIdx - 1], andGroup]}
/>
)}
<FilterGroupContainer isRoot={false} filterGroup={andGroup}>
{andGroup.conditions.map((rule, ruleIdx) => (
<Fragment key={rule.id}>
{ruleIdx > 0 && (
<FilterRuleJoiner
operator={andGroup.op}
joinBetween={[andGroup.conditions[ruleIdx - 1], rule]}
/>
)}
<div className="rule-container">
{
<FilterRule
rule={rule}
filterFields={filterFields}
mapFieldName={mapFieldName}
mapFilterName={mapFilterName}
onChange={(rule) => {
onChange?.({
...filterGroup,
conditions: [
...filterGroup.conditions.slice(0, groupIdx),
{
...andGroup,
conditions: [
...andGroup.conditions.slice(0, ruleIdx),
rule,
...andGroup.conditions.slice(ruleIdx + 1),
],
},
...filterGroup.conditions.slice(groupIdx + 1),
],
});
}}
onAddFilter={() => {
andGroup.conditions = [
...andGroup.conditions.slice(0, ruleIdx + 1),
createEmptyRule(),
...andGroup.conditions.slice(ruleIdx + 1),
];
onChange?.({
...filterGroup,
});
return;
}}
onAddGroup={(operator) => {
if (operator === "or") {
throw new Error(
"Not supported adding OR group in flatten filter builder",
);
}
filterGroup.conditions = [
...filterGroup.conditions.slice(0, groupIdx + 1),
{
id: genFilterId(),
type: "FilterGroup",
op: "and",
conditions: [createEmptyRule()],
},
...filterGroup.conditions.slice(groupIdx + 1),
];
onChange?.({
...filterGroup,
});
}}
onRemove={() => {
if (andGroup.conditions.length === 1) {
if (filterGroup.conditions.length === 1) {
// onChange?.(EMPTY_FILTER_GROUP);
onChange?.({
...filterGroup,
conditions: [],
});
return;
}
onChange?.({
...filterGroup,
conditions: [
...filterGroup.conditions.slice(0, groupIdx),
...filterGroup.conditions.slice(groupIdx + 1),
],
});
return;
}
onChange?.({
...filterGroup,
conditions: [
...filterGroup.conditions.slice(0, groupIdx),
{
...andGroup,
conditions: [
...andGroup.conditions.slice(0, ruleIdx),
...andGroup.conditions.slice(ruleIdx + 1),
],
},
...filterGroup.conditions.slice(groupIdx + 1),
],
});
}}
<FilterProvider
value={{
schema,
filterList,
filterRule: filterGroup,
onRuleChange: onChange,

mapFieldName,
mapFilterName,
deepLimit,
}}
>
<div className="filter-builder-container">
<FilterGroupContainer isRoot filterGroup={filterGroup}>
{filterGroup.conditions.map((andGroup, groupIdx) => {
return (
<Fragment key={andGroup.id}>
{groupIdx > 0 && (
<FilterRuleJoiner
operator={filterGroup.op}
joinBetween={[
filterGroup.conditions[groupIdx - 1],
andGroup,
]}
/>
)}
<FilterGroupContainer isRoot={false} filterGroup={andGroup}>
{andGroup.conditions.map((rule, ruleIdx) => (
<Fragment key={rule.id}>
{ruleIdx > 0 && (
<FilterRuleJoiner
operator={andGroup.op}
joinBetween={[andGroup.conditions[ruleIdx - 1], rule]}
/>
}
</div>
</Fragment>
))}
</FilterGroupContainer>
</Fragment>
);
})}
</FilterGroupContainer>
</div>
)}
<div className="rule-container">
{<FilterRule rule={rule} />}
</div>
</Fragment>
))}
</FilterGroupContainer>
</Fragment>
);
})}
</FilterGroupContainer>
</div>
</FilterProvider>
);
};
FlattenFilterBuilder.displayName = "FilterBuilder";
FlattenFilterBuilder.displayName = "FlattenFilterBuilder";

0 comments on commit 896cc2b

Please sign in to comment.