Skip to content

Commit

Permalink
Add support for empty and non_empty operator
Browse files Browse the repository at this point in the history
  • Loading branch information
dyang415 committed Oct 2, 2023
1 parent 8709576 commit 6d15857
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 39 deletions.
4 changes: 3 additions & 1 deletion backend/app/insight/services/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,15 @@ class MetricInsight:
class FilterOperator(StrEnum):
EQ = "eq"
NEQ = "neq"
EMPTY = "empty"
NON_EMPTY = "non_empty"


@dataclass
class Filter:
column: str
operator: FilterOperator
values: list[str | float | bool | date]
values: Optional[list[str | float | bool | date]] = None


def build_polars_agg(name: str | Expr, method: AggregateMethod):
Expand Down
6 changes: 5 additions & 1 deletion backend/app/insight/services/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,12 @@ def get_filter_expression(filters: list[Filter]) -> Expr:
expr = pl.col(filter.column).cast(pl.Utf8)
if filter.operator == FilterOperator.EQ:
expr = expr.is_in(filter.values)
else:
elif filter.operator == FilterOperator.NEQ:
expr = expr.is_in(filter.values).is_not()
elif filter.operator == FilterOperator.EMPTY:
expr = expr.is_null() | expr.len().eq(0)
elif filter.operator == FilterOperator.NON_EMPTY:
expr = expr.is_not_null() & expr.len().gt(0)

filter_expr = filter_expr & expr

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export interface DimensionSliceInfo {
confidence: number;
}

export type FilterOperator = "eq" | "neq";
export type FilterOperator = "eq" | "neq" | "empty" | "non_empty";
export interface Filter {
values?: string[];
operator?: FilterOperator;
Expand Down
77 changes: 41 additions & 36 deletions frontend/src/components/common/FiltersDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,7 @@ export const FiltersDropDown = forwardRef(function FiltersDropDown(
}));

function sanitizeFiltersAndCallOnFiltersChanged(filters: Filter[]) {
onFiltersChanged(
filters.filter(
(filter) =>
filter.column &&
filter.operator &&
filter.values &&
filter.values.length > 0
)
);
onFiltersChanged(filters.filter(isFilterValid));
}

function getColumns(filter: Filter) {
Expand Down Expand Up @@ -105,24 +97,27 @@ export const FiltersDropDown = forwardRef(function FiltersDropDown(
return s1.toLowerCase().localeCompare(s2.toLowerCase());
}

function isFilterValid(filter: Filter): boolean {
if (filter.operator === "eq" || filter.operator === "neq") {
return (
filter.column != null &&
filter.operator != null &&
filter.values != null &&
filter.values.length > 0
);
} else if (filter.operator === "empty" || filter.operator === "non_empty") {
return filter.column != null;
}
return false;
}

return (
<div className="dropdown w-full">
<div
tabIndex={0}
className="flex cursor-pointer w-full outline-none text-left whitespace-nowrap truncate rounded-tremor-default focus:ring-2 transition duration-100 shadow-tremor-input focus:border-tremor-brand-subtle focus:ring-tremor-brand-muted dark:shadow-dark-tremor-input dark:focus:border-dark-tremor-brand-subtle dark:focus:ring-dark-tremor-brand-muted pl-4 pr-8 py-2 border bg-tremor-background dark:bg-dark-tremor-background hover:bg-tremor-background-muted dark:hover:bg-dark-tremor-background-muted text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis border-tremor-border dark:border-dark-tremor-border"
>
<Flex>
{
localFilters.filter(
(filter) =>
filter.column &&
filter.operator &&
filter.values &&
filter.values.length > 0
).length
}{" "}
selected
</Flex>
<Flex>{localFilters.filter(isFilterValid).length} selected</Flex>
<span className="absolute inset-y-0 right-0 flex items-center mr-2.5">
<svg
className="tremor-MultiSelect-arrowDownIcon flex-none text-tremor-content-subtle dark:text-dark-tremor-content-subtle h-4 w-4"
Expand Down Expand Up @@ -178,32 +173,42 @@ export const FiltersDropDown = forwardRef(function FiltersDropDown(
</TableCell>
<TableCell className="align-top">
<SingleSelector
labels={["equal", "not equal"]}
values={["eq", "neq"]}
labels={["equal", "not equal", "is empty", "is not empty"]}
values={["eq", "neq", "empty", "non_empty"]}
selectedValue={filter.operator ?? ""}
onValueChange={(value) =>
updateFilter(index, {
...filter,
operator: value as FilterOperator,
values:
value === "eq" || value === "neq"
? filter.values
: undefined,
})
}
disabled={!filter.column}
/>
</TableCell>
<TableCell className="align-top">
<MultiSelector
includeSelectAll={true}
labels={getValues(filter)}
values={getValues(filter)}
selectedValues={filter.values ?? []}
onValueChange={(values) => {
updateFilter(index, {
...filter,
values,
});
}}
disabled={!filter.column}
/>
{filter.operator === "eq" || filter.operator === "neq" ? (
<MultiSelector
includeSelectAll={true}
labels={getValues(filter)}
values={getValues(filter)}
selectedValues={filter.values ?? []}
onValueChange={(values) => {
updateFilter(index, {
...filter,
values,
});
}}
disabled={!filter.column}
/>
) : (
<Flex justifyContent="center">
<Text>N/A</Text>
</Flex>
)}
</TableCell>
</TableRow>
))}
Expand Down

0 comments on commit 6d15857

Please sign in to comment.