Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion web-common/src/features/canvas/stores/filter-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import { goto } from "$app/navigation";
import { FilterState } from "./filter-state";
import { getDimensionDisplayName } from "../../dashboards/filters/getDisplayName";
import type { ParsedFilters } from "./filter-state";
import { createAndExpression } from "../../dashboards/stores/filter-utils";
import {
createAndExpression,
flattenInExpressionValues,
} from "../../dashboards/stores/filter-utils";

export type UIFilters = {
dimensionFilters: Map<string, DimensionFilterItem>;
Expand Down Expand Up @@ -864,6 +867,9 @@ export function flattenExpression(
// Recursively flatten all nested ANDs, preserving order
rootCond.exprs = flattenAndExprs(rootCond.exprs);

// Normalize array-valued IN/NIN expressions into individual value expressions
rootCond.exprs = rootCond.exprs.map(flattenInExpressionValues);

return root;
}

Expand Down
2 changes: 2 additions & 0 deletions web-common/src/features/canvas/stores/filter-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ export class FilterState {
const { expr, dimensionsWithInlistFilter: dimensionsWithInListFilter } =
getFiltersFromText(filterString ?? "");

console.log({ expr, dimensionsWithInListFilter, filterString });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove log


return this.parseFilter({ expr, filterString, dimensionsWithInListFilter });
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { createAndExpression } from "@rilldata/web-common/features/dashboards/stores/filter-utils";
import {
createAndExpression,
flattenInExpressionValues,
} from "@rilldata/web-common/features/dashboards/stores/filter-utils";
import { convertFilterParamToExpression } from "@rilldata/web-common/features/dashboards/url-state/filters/converters";
import { V1Operation } from "@rilldata/web-common/runtime-client";

Expand Down Expand Up @@ -45,6 +48,12 @@ export function getFiltersFromText(filterText: string) {
) {
sanitisedExpr = createAndExpression([sanitisedExpr]);
}
// Normalize array-valued IN/NIN expressions into individual value expressions
if (sanitisedExpr.cond?.exprs) {
sanitisedExpr.cond.exprs = sanitisedExpr.cond.exprs.map(
flattenInExpressionValues,
);
}
return { expr: sanitisedExpr, dimensionsWithInlistFilter };
} catch (e) {
console.error("Error parsing filter text:", e);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { describe, it, expect } from "vitest";
import { splitDimensionSearchText } from "web-common/src/features/dashboards/filters/dimension-filters/dimension-search-text-utils";
import {
getFiltersFromText,
splitDimensionSearchText,
} from "web-common/src/features/dashboards/filters/dimension-filters/dimension-search-text-utils";
import { V1Operation } from "web-common/src/runtime-client";

describe("splitDimensionSearchText", () => {
it("should split by comma and return trimmed parts", () => {
Expand All @@ -22,3 +26,51 @@ describe("splitDimensionSearchText", () => {
expect(result).toEqual(["facebook , google", "rill"]);
});
});

describe("getFiltersFromText", () => {
it("should flatten array-wrapped values in IN expressions", () => {
const { expr } = getFiltersFromText("username IN (['Ashwani Yadav'])");
const inExpr = expr.cond?.exprs?.[0];
expect(inExpr?.cond?.op).toBe(V1Operation.OPERATION_IN);
expect(inExpr?.cond?.exprs).toEqual([
{ ident: "username" },
{ val: "Ashwani Yadav" },
]);
});

it("should flatten array-wrapped values in NIN expressions", () => {
const { expr } = getFiltersFromText("username NIN (['Ashwani Yadav'])");
const ninExpr = expr.cond?.exprs?.[0];
expect(ninExpr?.cond?.op).toBe(V1Operation.OPERATION_NIN);
expect(ninExpr?.cond?.exprs).toEqual([
{ ident: "username" },
{ val: "Ashwani Yadav" },
]);
});

it("should flatten multi-value array-wrapped IN expressions", () => {
const { expr } = getFiltersFromText(
"username IN (['Ashwani Yadav','John Doe'])",
);
const inExpr = expr.cond?.exprs?.[0];
expect(inExpr?.cond?.op).toBe(V1Operation.OPERATION_IN);
expect(inExpr?.cond?.exprs).toEqual([
{ ident: "username" },
{ val: "Ashwani Yadav" },
{ val: "John Doe" },
]);
});

it("should leave non-array IN expressions unchanged", () => {
const { expr } = getFiltersFromText(
"username IN ('Ashwani Yadav','John Doe')",
);
const inExpr = expr.cond?.exprs?.[0];
expect(inExpr?.cond?.op).toBe(V1Operation.OPERATION_IN);
expect(inExpr?.cond?.exprs).toEqual([
{ ident: "username" },
{ val: "Ashwani Yadav" },
{ val: "John Doe" },
]);
});
});
4 changes: 2 additions & 2 deletions web-local/tests/canvas/default-filters.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test.describe("canvas time filters", () => {
await page.waitForSelector('button:has-text("Viewing default state")');

expect(page.url()).toContain(
"?tr=PT24H&compare_tr=rill-PP&f.AdBids_metrics=domain+IN+%28%5B%27facebook.com%27%2C%27google.com%27%2C%27msn.com%27%5D%29",
"?tr=PT24H&compare_tr=rill-PP&f.AdBids_metrics=domain+IN+%28%27facebook.com%27%2C%27google.com%27%2C%27msn.com%27%29",
);

// navigate to code view
Expand Down Expand Up @@ -83,7 +83,7 @@ test.describe("canvas time filters", () => {

await page.waitForTimeout(1000);
expect(page.url()).toContain(
"?tr=PT24H&compare_tr=rill-PP&f.AdBids_metrics=domain+IN+%28%5B%27facebook.com%27%2C%27google.com%27%2C%27msn.com%27%5D%29",
"?tr=PT24H&compare_tr=rill-PP&f.AdBids_metrics=domain+IN+%28%27facebook.com%27%2C%27google.com%27%2C%27msn.com%27%29",
);
});

Expand Down
Loading