Skip to content
Snippets Groups Projects
Unverified Commit bcd1a90c authored by Kamil Mielnik's avatar Kamil Mielnik Committed by GitHub
Browse files

Refactor parameters filters utils to TS (#46719)

* Refactor filter utils to TS

* Remove type casts

* Improve dimension instantiation

* Fix typing
parent eca4bb5f
No related branches found
No related tags found
No related merge requests found
import * as Lib from "metabase-lib";
import type Dimension from "metabase-lib/v1/Dimension";
import type Field from "metabase-lib/v1/metadata/Field";
import { getParameterOperatorName } from "metabase-lib/v1/parameters/utils/operators";
import {
getParameterType,
getParameterSubType,
getParameterType,
} from "metabase-lib/v1/parameters/utils/parameter-type";
import TemplateTagVariable from "metabase-lib/v1/variables/TemplateTagVariable";
import type Variable from "metabase-lib/v1/variables/Variable";
import type { Parameter, TemplateTag } from "metabase-types/api";
export function fieldFilterForParameter(parameter) {
export function fieldFilterForParameter(
parameter: Parameter | string,
): (field: Field) => boolean {
const type = getParameterType(parameter);
switch (type) {
case "date":
......@@ -26,7 +32,11 @@ export function fieldFilterForParameter(parameter) {
return () => false;
}
export function columnFilterForParameter(query, stageIndex, parameter) {
export function columnFilterForParameter(
query: Lib.Query,
stageIndex: number,
parameter: Parameter | string,
): (column: Lib.ColumnMetadata) => boolean {
const type = getParameterType(parameter);
switch (type) {
......@@ -50,17 +60,19 @@ export function columnFilterForParameter(query, stageIndex, parameter) {
return () => false;
}
export function dimensionFilterForParameter(parameter) {
export function dimensionFilterForParameter(parameter: Parameter | string) {
const fieldFilter = fieldFilterForParameter(parameter);
return dimension => fieldFilter(dimension.field());
return (dimension: Dimension) => fieldFilter(dimension.field());
}
export function getTagOperatorFilterForParameter(parameter) {
export function getTagOperatorFilterForParameter(
parameter: Parameter | string,
) {
const subtype = getParameterSubType(parameter);
const parameterOperatorName = getParameterOperatorName(subtype);
return tag => {
const { "widget-type": widgetType } = tag;
return (tag: TemplateTag) => {
const { "widget-type": widgetType = "" } = tag;
const subtype = getParameterSubType(widgetType);
const tagOperatorName = getParameterOperatorName(subtype);
......@@ -68,9 +80,9 @@ export function getTagOperatorFilterForParameter(parameter) {
};
}
export function variableFilterForParameter(parameter) {
export function variableFilterForParameter(parameter: Parameter | string) {
const tagFilter = tagFilterForParameter(parameter);
return variable => {
return (variable: Variable) => {
if (variable instanceof TemplateTagVariable) {
const tag = variable.tag();
return tag ? tagFilter(tag) : false;
......@@ -79,7 +91,9 @@ export function variableFilterForParameter(parameter) {
};
}
function tagFilterForParameter(parameter) {
function tagFilterForParameter(
parameter: Parameter | string,
): (tag: TemplateTag) => boolean {
const type = getParameterType(parameter);
const subtype = getParameterSubType(parameter);
const operator = getParameterOperatorName(subtype);
......
import { createMockMetadata } from "__support__/metadata";
import { checkNotNull } from "metabase/lib/types";
import Dimension from "metabase-lib/v1/Dimension";
import Field from "metabase-lib/v1/metadata/Field";
import {
createMockParameter,
createMockTemplateTag,
} from "metabase-types/api/mocks";
import { PRODUCTS } from "metabase-types/api/mocks/presets";
import {
dimensionFilterForParameter,
getTagOperatorFilterForParameter,
......@@ -5,7 +15,7 @@ import {
describe("parameters/utils/field-filters", () => {
describe("dimensionFilterForParameter", () => {
const field = {
const field = createMockField({
isDate: () => false,
isID: () => false,
isCategory: () => false,
......@@ -16,10 +26,11 @@ describe("parameters/utils/field-filters", () => {
isNumber: () => false,
isString: () => false,
isLocation: () => false,
};
const typelessDimension = {
});
const typelessDimension = createMockDimension({
field: () => field,
};
});
[
[
......@@ -99,55 +110,75 @@ describe("parameters/utils/field-filters", () => {
],
].forEach(([parameter, dimension]) => {
it(`should return a predicate that evaluates to true for a ${dimension.type} dimension when given a ${parameter.type} parameter`, () => {
const predicate = dimensionFilterForParameter(parameter);
const predicate = dimensionFilterForParameter(
createMockParameter(parameter),
);
expect(predicate(typelessDimension)).toBe(false);
expect(predicate(dimension)).toBe(true);
expect(predicate(createMockDimension(dimension))).toBe(true);
});
});
it("should return a predicate that evaluates to false for a coordinate dimension when given a number parameter", () => {
const coordinateDimension = {
const coordinateDimension = createMockDimension({
field: () => ({
...field,
isNumber: () => true,
isCoordinate: () => true,
}),
};
});
const predicate = dimensionFilterForParameter({ type: "number/between" });
const predicate = dimensionFilterForParameter(
createMockParameter({ type: "number/between" }),
);
expect(predicate(coordinateDimension)).toBe(false);
});
it("should return a predicate that evaluates to false for a location dimension when given a category parameter", () => {
const locationDimension = {
const locationDimension = createMockDimension({
field: () => ({
...field,
isLocation: () => true,
}),
};
});
const predicate = dimensionFilterForParameter({ type: "category" });
const predicate = dimensionFilterForParameter(
createMockParameter({ type: "category" }),
);
expect(predicate(locationDimension)).toBe(false);
});
});
describe("getTagOperatorFilterForParameter", () => {
it("should return a predicate that evaluates to true for a template tag that has the same subtype operator as the given parameter", () => {
const predicate = getTagOperatorFilterForParameter({
type: "string/starts-with",
});
const templateTag1 = {
const predicate = getTagOperatorFilterForParameter(
createMockParameter({
type: "string/starts-with",
}),
);
const templateTag1 = createMockTemplateTag({
"widget-type": "string/starts-with",
};
const templateTag2 = {
});
const templateTag2 = createMockTemplateTag({
"widget-type": "foo/starts-with",
};
const templateTag3 = {
});
const templateTag3 = createMockTemplateTag({
"widget-type": "string/ends-with",
};
});
expect(predicate(templateTag1)).toBe(true);
expect(predicate(templateTag2)).toBe(true);
expect(predicate(templateTag3)).toBe(false);
});
});
});
function createMockField(mocks: Record<string, unknown>): Field {
return Object.assign(new Field(), mocks);
}
function createMockDimension(mocks: Record<string, unknown>): Dimension {
const metadata = createMockMetadata({});
const dimension = checkNotNull(
Dimension.parseMBQL(["field", PRODUCTS.CREATED_AT, null], metadata),
);
return Object.assign({}, dimension, mocks);
}
......@@ -9,7 +9,7 @@ export function getParameterType(parameter: Parameter | string) {
: parameter.sectionId || splitType(parameter)[0];
}
export function getParameterSubType(parameter: Parameter) {
export function getParameterSubType(parameter: Parameter | string) {
const [, subtype] = splitType(parameter);
return subtype;
}
......
import { t } from "ttag";
import type Field from "metabase-lib/v1/metadata/Field";
import type { TemplateTag, ParameterOptions } from "metabase-types/api";
import type { ParameterOptions, TemplateTag } from "metabase-types/api";
import { createMockParameter } from "metabase-types/api/mocks";
import {
ID_OPTION,
......@@ -32,7 +33,9 @@ export function getParameterOptions() {
export function getParameterOptionsForField(field: Field) {
return getParameterOptions()
.filter(option => fieldFilterForParameter(option)(field))
.filter(option =>
fieldFilterForParameter(createMockParameter(option))(field),
)
.map(option => {
return {
...option,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment