Skip to content
Snippets Groups Projects
Unverified Commit 74848ea3 authored by metabase-bot[bot]'s avatar metabase-bot[bot] Committed by GitHub
Browse files

Merge (#39935)

parent 10f8f285
Branches
Tags
No related merge requests found
......@@ -15,6 +15,9 @@ import {
describeEE,
setSearchBoxFilterType,
setTokenFeatures,
setDropdownFilterType,
getDashboardCard,
filterWidget,
} from "e2e/support/helpers";
const { PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE;
......@@ -110,6 +113,27 @@ describe("scenarios > dashboard > filters", { tags: "@slow" }, () => {
filterDashboard();
});
it("should be able to use a structured question source with string/contains parameter", () => {
cy.createQuestion(structuredSourceQuestion, { wrapId: true });
cy.createQuestionAndDashboard({
questionDetails: targetQuestion,
}).then(({ body: { dashboard_id } }) => {
visitDashboard(dashboard_id);
});
editDashboard();
setFilter("Text or Category", "Contains");
mapFilterToQuestion();
setDropdownFilterType();
setFilterQuestionSource({ question: "GUI source", field: "Category" });
saveDashboard();
getDashboardCard().findByText("200").should("be.visible");
filterWidget().click();
popover().findByText("Gizmo").click();
popover().button("Add filter").click();
getDashboardCard().findByText("51").should("be.visible");
});
});
describe("native question source", () => {
......
import type Field from "metabase-lib/metadata/Field";
import { isFuzzyOperator } from "metabase-lib/operators/utils";
import type {
Parameter,
ValuesQueryType,
......@@ -8,16 +9,24 @@ import type {
import type { ParameterWithTemplateTagTarget } from "../types";
import { deriveFieldOperatorFromParameter } from "./operators";
import { getFields } from "./parameter-fields";
import { getParameterSubType, getParameterType } from "./parameter-type";
import { getParameterType } from "./parameter-type";
export const getQueryType = (
parameter: ParameterWithTemplateTagTarget,
): ValuesQueryType => {
return parameter.values_query_type ?? getDefaultQueryType(parameter);
};
const getDefaultQueryType = (
parameter: ParameterWithTemplateTagTarget,
): ValuesQueryType => {
if (parameter.hasVariableTemplateTagTarget) {
return parameter.values_query_type ?? "none";
return "none";
} else {
return parameter.values_query_type ?? "list";
const operator = deriveFieldOperatorFromParameter(parameter);
return operator != null && isFuzzyOperator(operator) ? "none" : "list";
}
};
......@@ -31,12 +40,10 @@ export const getSourceConfig = (parameter: Parameter): ValuesSourceConfig => {
export const canUseCustomSource = (parameter: Parameter) => {
const type = getParameterType(parameter);
const subType = getParameterSubType(parameter);
switch (type) {
case "string":
case "location":
return subType === "=";
case "category":
return true;
default:
......@@ -96,6 +103,11 @@ export const canSearchParameterValues = (
parameter: Parameter,
disablePKRemapping = false,
) => {
const operator = deriveFieldOperatorFromParameter(parameter);
if (operator && isFuzzyOperator(operator) && !canUseCustomSource(parameter)) {
return false;
}
const queryType = getQueryType(parameter);
const sourceType = getSourceType(parameter);
const fields = getFields(parameter);
......
......@@ -6,6 +6,7 @@ import { createMockField } from "metabase-types/api/mocks";
import {
canListParameterValues,
canSearchParameterValues,
getQueryType,
} from "./parameter-source";
const LIST_FIELD_ID = 1;
......@@ -30,6 +31,54 @@ const searchField = metadata.field(SEARCH_FIELD_ID) as Field;
const searchField2 = metadata.field(SEARCH_FIELD_2_ID) as Field;
const noValuesField = metadata.field(NO_VALUES_FIELD_ID) as Field;
describe("getQueryType", () => {
describe.each(["string", "location"])("parameter type %s", type => {
it.each([
["=", "list"],
["!=", "list"],
["contains", "none"],
["does-not-contain", "none"],
["starts-with", "none"],
["ends-with", "none"],
])(
"and %s operator should return %s query type by default",
(operator, queryType) => {
const parameter = createMockUiParameter({
type: `${type}/${operator}`,
});
expect(getQueryType(parameter)).toBe(queryType);
},
);
});
describe.each(["number"])("parameter type %s", type => {
it.each([
["=", "list"],
["!=", "list"],
[">", "none"],
["<", "none"],
[">=", "none"],
["<=", "none"],
["between", "none"],
])(
"and %s operator should return %s query type by default",
(operator, queryType) => {
const parameter = createMockUiParameter({
type: `${type}/${operator}`,
});
expect(getQueryType(parameter)).toBe(queryType);
},
);
});
it('should return "list" query type by default for legacy parameter types', () => {
const parameter = createMockUiParameter({
type: "category",
});
expect(getQueryType(parameter)).toBe("list");
});
});
describe("canListParameterValues", () => {
it("should not list when it is disabled", () => {
const parameter = createMockUiParameter({
......@@ -145,4 +194,54 @@ describe("canSearchParameterValues", () => {
expect(canSearchParameterValues(parameter)).toBeFalsy();
});
it.each([
"=",
"!=",
"contains",
"does-not-contain",
"starts-with",
"ends-with",
])("should allow to search for %s string operator", operator => {
const parameter = createMockUiParameter({
type: `string/${operator}`,
fields: [searchField],
values_query_type: "search",
});
expect(canSearchParameterValues(parameter)).toBe(true);
});
it.each(["=", "!="])(
"should allow to search for %s numeric operator",
operator => {
const parameter = createMockUiParameter({
type: `number/${operator}`,
fields: [searchField],
});
expect(canSearchParameterValues(parameter)).toBe(true);
},
);
it.each([">", "<", ">=", "<=", "between"])(
"should not allow to search for %s numeric operator",
operator => {
const parameter = createMockUiParameter({
type: `number/${operator}`,
fields: [searchField],
});
expect(canSearchParameterValues(parameter)).toBe(false);
},
);
it("should allow to search for legacy parameter operators", () => {
const parameter = createMockUiParameter({
type: "location/state",
fields: [searchField],
});
expect(canSearchParameterValues(parameter)).toBe(true);
});
});
......@@ -13,7 +13,6 @@ import {
import {
getFilterArgumentFormatOptions,
isEqualsOperator,
isFuzzyOperator,
} from "metabase-lib/operators/utils";
import { deriveFieldOperatorFromParameter } from "metabase-lib/parameters/utils/operators";
......@@ -49,7 +48,6 @@ export default function ParameterFieldWidget({
const operator = deriveFieldOperatorFromParameter(parameter);
const { numFields = 1, multi = false, verboseName } = operator || {};
const isEqualsOp = isEqualsOperator(operator);
const disableSearch = operator && isFuzzyOperator(operator);
const hasValue = Array.isArray(value) ? value.length > 0 : value != null;
const supportsMultipleValues =
......@@ -91,7 +89,6 @@ export default function ParameterFieldWidget({
fields={fields}
autoFocus={index === 0}
multi={supportsMultipleValues}
disableSearch={disableSearch}
formatOptions={
operator && getFilterArgumentFormatOptions(operator, index)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment