From 6c439596c18ac92110474697a85894e7d8fefbc3 Mon Sep 17 00:00:00 2001
From: Alexander Polyankin <alexander.polyankin@metabase.com>
Date: Thu, 12 Jan 2023 14:58:03 +0200
Subject: [PATCH] Add ability to choose between Dropdown/Search/Input for
 String parameters (#27610)

---
 frontend/src/metabase-lib/metadata/Field.ts   | 36 ++++++-----
 .../src/metabase-lib/metadata/utils/fields.ts |  4 --
 frontend/src/metabase-lib/mocks.ts            | 12 ----
 .../src/metabase-lib/parameters/constants.ts  |  2 +-
 frontend/src/metabase-lib/parameters/mock.ts  |  3 +
 .../parameters/utils/parameter-fields.ts      |  6 +-
 .../parameters/utils/parameter-source.ts      |  2 +-
 .../parameters/utils/template-tags.ts         |  3 +
 .../utils/template-tags.unit.spec.js          | 15 +++++
 .../metabase-types/api/mocks/parameters.ts    |  3 +
 frontend/src/metabase-types/api/parameters.ts |  7 +-
 .../metabase/dashboard/actions/parameters.js  | 13 ++++
 .../components/DashboardSidebars.jsx          |  3 +
 .../ParameterSettings/ParameterSettings.tsx   | 13 +++-
 .../ParameterSidebar/ParameterSidebar.tsx     | 14 ++++
 .../ParameterSourceSettings/index.ts          |  1 -
 .../ValuesSourceModal/ValuesSourceModal.tsx   |  7 +-
 .../ValuesSourceSettings.styled.tsx}          |  0
 .../ValuesSourceSettings.tsx}                 | 64 +++++++++++++++----
 .../components/ValuesSourceSettings/index.ts  |  1 +
 .../metabase/parameters/utils/dashboards.ts   | 16 ++---
 .../parameters/utils/dashboards.unit.spec.js  |  9 +++
 .../utils/parameter-type.unit.spec.ts         | 28 +++-----
 .../metabase-lib/lib/Question.unit.spec.js    |  6 ++
 .../dashboard-filters-location.cy.spec.js     |  2 +-
 .../dashboard-filters-location.js             |  2 +-
 .../dashboard-filters-source.cy.spec.js       |  8 +--
 .../dashboard-filters-sql-location.cy.spec.js |  4 +-
 .../dashboard-filters-sql-location.js         | 10 +--
 ...board-filters-sql-text-category.cy.spec.js |  8 +--
 .../dashboard-filters-sql-text-category.js    | 10 +--
 ...dashboard-filters-text-category.cy.spec.js |  4 +-
 .../dashboard-filters-text-category.js        |  2 +-
 .../dashboard-filters/parameters.cy.spec.js   |  2 +-
 .../dashboard/chained-filters.cy.spec.js      |  4 +-
 .../scenarios/dashboard/dashboard.cy.spec.js  |  2 +-
 .../dashboard_data_permissions.cy.spec.js     |  2 +-
 .../scenarios/dashboard/text-box.cy.spec.js   |  2 +-
 ...-apply-dash-filter-native-model.cy.spec.js |  2 +-
 .../helpers/e2e-field-filter-helpers.js       |  2 +-
 .../scenarios/sharing/public.cy.spec.js       |  2 +-
 ...dates-after-changing-parameters.cy.spec.js |  2 +-
 .../sharing/subscriptions.cy.spec.js          |  4 +-
 43 files changed, 215 insertions(+), 127 deletions(-)
 delete mode 100644 frontend/src/metabase/parameters/components/ParameterSourceSettings/index.ts
 rename frontend/src/metabase/parameters/components/{ParameterSourceSettings/ParameterSourceSettings.styled.tsx => ValuesSourceSettings/ValuesSourceSettings.styled.tsx} (100%)
 rename frontend/src/metabase/parameters/components/{ParameterSourceSettings/ParameterSourceSettings.tsx => ValuesSourceSettings/ValuesSourceSettings.tsx} (53%)
 create mode 100644 frontend/src/metabase/parameters/components/ValuesSourceSettings/index.ts

diff --git a/frontend/src/metabase-lib/metadata/Field.ts b/frontend/src/metabase-lib/metadata/Field.ts
index df429c93004..6869d187688 100644
--- a/frontend/src/metabase-lib/metadata/Field.ts
+++ b/frontend/src/metabase-lib/metadata/Field.ts
@@ -11,30 +11,30 @@ import type {
 } from "metabase-types/api";
 import type { Field as FieldRef } from "metabase-types/types/Query";
 import {
-  isDate,
-  isDateWithoutTime,
-  isTime,
-  isNumber,
-  isNumeric,
+  isAddress,
   isBoolean,
-  isString,
-  isSummable,
-  isScope,
   isCategory,
-  isAddress,
   isCity,
-  isState,
-  isZipCode,
-  isCountry,
+  isComment,
   isCoordinate,
-  isLocation,
+  isCountry,
+  isDate,
+  isDateWithoutTime,
   isDescription,
-  isComment,
   isDimension,
+  isEntityName,
+  isFK,
+  isLocation,
   isMetric,
+  isNumber,
+  isNumeric,
   isPK,
-  isFK,
-  isEntityName,
+  isScope,
+  isState,
+  isString,
+  isSummable,
+  isTime,
+  isZipCode,
 } from "metabase-lib/types/utils/isa";
 import { getFilterOperators } from "metabase-lib/operators/utils";
 import { getFieldValues } from "metabase-lib/queries/utils/field";
@@ -488,6 +488,10 @@ class FieldInner extends Base {
     return this.dimension().foreign(foreignField.dimension());
   }
 
+  isVirtual() {
+    return typeof this.id !== "number";
+  }
+
   /**
    * @private
    * @param {number} id
diff --git a/frontend/src/metabase-lib/metadata/utils/fields.ts b/frontend/src/metabase-lib/metadata/utils/fields.ts
index c9e1367893a..545df4ffccf 100644
--- a/frontend/src/metabase-lib/metadata/utils/fields.ts
+++ b/frontend/src/metabase-lib/metadata/utils/fields.ts
@@ -49,7 +49,3 @@ function getFieldIdentifier(field: Field): number | string {
 
   return id || name;
 }
-
-export function isVirtualFieldId(id: Field["id"]) {
-  return typeof id !== "number";
-}
diff --git a/frontend/src/metabase-lib/mocks.ts b/frontend/src/metabase-lib/mocks.ts
index b07fe64d73d..1915d7f5164 100644
--- a/frontend/src/metabase-lib/mocks.ts
+++ b/frontend/src/metabase-lib/mocks.ts
@@ -16,7 +16,6 @@ import Question from "metabase-lib/Question";
 import NativeQuery from "metabase-lib/queries/NativeQuery";
 import StructuredQuery from "metabase-lib/queries/StructuredQuery";
 import Query from "metabase-lib/queries/Query";
-import { UiParameter } from "metabase-lib/parameters/types";
 
 export type NativeSavedCard = SavedCard<NativeDatasetQuery>;
 export type NativeUnsavedCard = UnsavedCard<NativeDatasetQuery>;
@@ -141,14 +140,3 @@ export function getComposedModel(
 
   return question;
 }
-
-export const createMockUiParameter = (
-  opts?: Partial<UiParameter>,
-): UiParameter => ({
-  id: "1",
-  name: "text",
-  type: "string/=",
-  slug: "text",
-  fields: [],
-  ...opts,
-});
diff --git a/frontend/src/metabase-lib/parameters/constants.ts b/frontend/src/metabase-lib/parameters/constants.ts
index 45475c9e223..d448c568104 100644
--- a/frontend/src/metabase-lib/parameters/constants.ts
+++ b/frontend/src/metabase-lib/parameters/constants.ts
@@ -32,7 +32,7 @@ export const PARAMETER_OPERATOR_TYPES = {
     {
       type: "string/=",
       operator: "=",
-      name: t`Dropdown`,
+      name: t`Is`,
       description: t`Select one or more values from a list or search box.`,
     },
     {
diff --git a/frontend/src/metabase-lib/parameters/mock.ts b/frontend/src/metabase-lib/parameters/mock.ts
index e09816fbc63..68e6a3f163d 100644
--- a/frontend/src/metabase-lib/parameters/mock.ts
+++ b/frontend/src/metabase-lib/parameters/mock.ts
@@ -7,5 +7,8 @@ export const createMockUiParameter = (
   slug: "slug",
   name: "Name",
   type: "string/=",
+  values_query_type: "list",
+  values_source_type: null,
+  values_source_config: {},
   ...opts,
 });
diff --git a/frontend/src/metabase-lib/parameters/utils/parameter-fields.ts b/frontend/src/metabase-lib/parameters/utils/parameter-fields.ts
index 60238fffa54..11eb28f375d 100644
--- a/frontend/src/metabase-lib/parameters/utils/parameter-fields.ts
+++ b/frontend/src/metabase-lib/parameters/utils/parameter-fields.ts
@@ -1,4 +1,4 @@
-import { isVirtualFieldId } from "metabase-lib/metadata/utils/fields";
+import Field from "metabase-lib/metadata/Field";
 import {
   FieldFilterUiParameter,
   UiParameter,
@@ -10,7 +10,7 @@ export const hasFields = (
   return (parameter as FieldFilterUiParameter).fields != null;
 };
 
-export const getFields = (parameter: UiParameter) => {
+export const getFields = (parameter: UiParameter): Field[] => {
   if (hasFields(parameter)) {
     return parameter.fields;
   } else {
@@ -19,5 +19,5 @@ export const getFields = (parameter: UiParameter) => {
 };
 
 export const getNonVirtualFields = (parameter: UiParameter) => {
-  return getFields(parameter).filter(field => !isVirtualFieldId(field.id));
+  return getFields(parameter).filter(field => !field.isVirtual());
 };
diff --git a/frontend/src/metabase-lib/parameters/utils/parameter-source.ts b/frontend/src/metabase-lib/parameters/utils/parameter-source.ts
index 3d04f6c013f..5f2663948de 100644
--- a/frontend/src/metabase-lib/parameters/utils/parameter-source.ts
+++ b/frontend/src/metabase-lib/parameters/utils/parameter-source.ts
@@ -17,7 +17,7 @@ export const isValidSourceConfig = (
 export const getDefaultSourceConfig = (
   sourceType: ValuesSourceType,
   sourceValues?: string[],
-) => {
+): ValuesSourceConfig => {
   switch (sourceType) {
     case "static-list":
       return { values: sourceValues };
diff --git a/frontend/src/metabase-lib/parameters/utils/template-tags.ts b/frontend/src/metabase-lib/parameters/utils/template-tags.ts
index 60a687e3dd8..9cab3d66964 100644
--- a/frontend/src/metabase-lib/parameters/utils/template-tags.ts
+++ b/frontend/src/metabase-lib/parameters/utils/template-tags.ts
@@ -38,6 +38,9 @@ export function getTemplateTagParameter(tag: TemplateTag): ParameterWithTarget {
     name: tag["display-name"],
     slug: tag.name,
     default: tag.default,
+    values_query_type: "list",
+    values_source_type: null,
+    values_source_config: {},
   };
 }
 
diff --git a/frontend/src/metabase-lib/parameters/utils/template-tags.unit.spec.js b/frontend/src/metabase-lib/parameters/utils/template-tags.unit.spec.js
index 9c91b3c79e6..f0c798ae6b4 100644
--- a/frontend/src/metabase-lib/parameters/utils/template-tags.unit.spec.js
+++ b/frontend/src/metabase-lib/parameters/utils/template-tags.unit.spec.js
@@ -122,6 +122,9 @@ describe("parameters/utils/cards", () => {
           slug: "a",
           target: ["variable", ["template-tag", "a"]],
           type: "foo",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
         {
           default: undefined,
@@ -130,6 +133,9 @@ describe("parameters/utils/cards", () => {
           slug: "b",
           target: ["variable", ["template-tag", "b"]],
           type: "string/=",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
         {
           default: undefined,
@@ -138,6 +144,9 @@ describe("parameters/utils/cards", () => {
           slug: "c",
           target: ["variable", ["template-tag", "c"]],
           type: "number/=",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
         {
           default: undefined,
@@ -146,6 +155,9 @@ describe("parameters/utils/cards", () => {
           slug: "d",
           target: ["variable", ["template-tag", "d"]],
           type: "date/single",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
         {
           default: undefined,
@@ -154,6 +166,9 @@ describe("parameters/utils/cards", () => {
           slug: "e",
           target: ["dimension", ["template-tag", "e"]],
           type: "foo",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
       ];
 
diff --git a/frontend/src/metabase-types/api/mocks/parameters.ts b/frontend/src/metabase-types/api/mocks/parameters.ts
index ce15e590580..ec11c75415e 100644
--- a/frontend/src/metabase-types/api/mocks/parameters.ts
+++ b/frontend/src/metabase-types/api/mocks/parameters.ts
@@ -5,5 +5,8 @@ export const createMockParameter = (opts?: Partial<Parameter>): Parameter => ({
   name: "text",
   type: "string/=",
   slug: "text",
+  values_query_type: "none",
+  values_source_type: null,
+  values_source_config: {},
   ...opts,
 });
diff --git a/frontend/src/metabase-types/api/parameters.ts b/frontend/src/metabase-types/api/parameters.ts
index ff3330c1b06..618b9e47834 100644
--- a/frontend/src/metabase-types/api/parameters.ts
+++ b/frontend/src/metabase-types/api/parameters.ts
@@ -42,10 +42,13 @@ export interface Parameter {
   filteringParameters?: ParameterId[];
   isMultiSelect?: boolean;
   value?: any;
-  values_source_type?: ValuesSourceType;
-  values_source_config?: ValuesSourceConfig;
+  values_query_type: ValuesQueryType;
+  values_source_type: ValuesSourceType;
+  values_source_config: ValuesSourceConfig;
 }
 
+export type ValuesQueryType = "list" | "search" | "none";
+
 export type ValuesSourceType = null | "card" | "static-list";
 
 export interface ValuesSourceConfig {
diff --git a/frontend/src/metabase/dashboard/actions/parameters.js b/frontend/src/metabase/dashboard/actions/parameters.js
index 003e8cdbc3c..a495e45c4e6 100644
--- a/frontend/src/metabase/dashboard/actions/parameters.js
+++ b/frontend/src/metabase/dashboard/actions/parameters.js
@@ -194,6 +194,19 @@ export const setParameterIsMultiSelect = createThunkAction(
   },
 );
 
+export const SET_PARAMETER_QUERY_TYPE =
+  "metabase/dashboard/SET_PARAMETER_QUERY_TYPE";
+export const setParameterQueryType = createThunkAction(
+  SET_PARAMETER_QUERY_TYPE,
+  (parameterId, queryType) => (dispatch, getState) => {
+    updateParameter(dispatch, getState, parameterId, parameter => ({
+      ...parameter,
+      values_query_type: queryType,
+    }));
+    return { id: parameterId, queryType };
+  },
+);
+
 export const SET_PARAMETER_SOURCE_TYPE =
   "metabase/dashboard/SET_PARAMETER_SOURCE_TYPE";
 export const setParameterSourceType = createThunkAction(
diff --git a/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx b/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx
index b757a135d17..b38f8796cb4 100644
--- a/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx
+++ b/frontend/src/metabase/dashboard/components/DashboardSidebars.jsx
@@ -27,6 +27,7 @@ DashboardSidebars.propTypes = {
   setParameterName: PropTypes.func.isRequired,
   setParameterDefaultValue: PropTypes.func.isRequired,
   setParameterIsMultiSelect: PropTypes.func.isRequired,
+  setParameterQueryType: PropTypes.func.isRequired,
   setParameterSourceType: PropTypes.func.isRequired,
   setParameterSourceConfig: PropTypes.func.isRequired,
   setParameterFilteringParameters: PropTypes.func.isRequired,
@@ -59,6 +60,7 @@ export function DashboardSidebars({
   setParameterName,
   setParameterDefaultValue,
   setParameterIsMultiSelect,
+  setParameterQueryType,
   setParameterSourceType,
   setParameterSourceConfig,
   setParameterFilteringParameters,
@@ -124,6 +126,7 @@ export function DashboardSidebars({
           onChangeName={setParameterName}
           onChangeDefaultValue={setParameterDefaultValue}
           onChangeIsMultiSelect={setParameterIsMultiSelect}
+          onChangeQueryType={setParameterQueryType}
           onChangeSourceType={setParameterSourceType}
           onChangeSourceConfig={setParameterSourceConfig}
           onChangeFilteringParameters={setParameterFilteringParameters}
diff --git a/frontend/src/metabase/parameters/components/ParameterSettings/ParameterSettings.tsx b/frontend/src/metabase/parameters/components/ParameterSettings/ParameterSettings.tsx
index 1e0dd14780a..e89a395635e 100644
--- a/frontend/src/metabase/parameters/components/ParameterSettings/ParameterSettings.tsx
+++ b/frontend/src/metabase/parameters/components/ParameterSettings/ParameterSettings.tsx
@@ -2,14 +2,18 @@ import React, { ChangeEvent, useCallback } from "react";
 import { t } from "ttag";
 import InputBlurChange from "metabase/components/InputBlurChange";
 import Radio from "metabase/core/components/Radio";
-import { ValuesSourceConfig, ValuesSourceType } from "metabase-types/api";
+import {
+  ValuesQueryType,
+  ValuesSourceConfig,
+  ValuesSourceType,
+} from "metabase-types/api";
 import { UiParameter } from "metabase-lib/parameters/types";
 import { getIsMultiSelect } from "../../utils/dashboards";
 import {
   canUseCustomSource,
   isSingleOrMultiSelectable,
 } from "../../utils/parameter-type";
-import ParameterSourceSettings from "../ParameterSourceSettings";
+import ValuesSourceSettings from "../ValuesSourceSettings";
 import {
   SettingLabel,
   SettingRemoveButton,
@@ -28,6 +32,7 @@ export interface ParameterSettingsProps {
   onChangeName: (name: string) => void;
   onChangeDefaultValue: (value: unknown) => void;
   onChangeIsMultiSelect: (isMultiSelect: boolean) => void;
+  onChangeQueryType: (queryType: ValuesQueryType) => void;
   onChangeSourceType: (sourceType: ValuesSourceType) => void;
   onChangeSourceConfig: (sourceOptions: ValuesSourceConfig) => void;
   onRemoveParameter: () => void;
@@ -38,6 +43,7 @@ const ParameterSettings = ({
   onChangeName,
   onChangeDefaultValue,
   onChangeIsMultiSelect,
+  onChangeQueryType,
   onChangeSourceType,
   onChangeSourceConfig,
   onRemoveParameter,
@@ -61,8 +67,9 @@ const ParameterSettings = ({
       {canUseCustomSource(parameter) && (
         <SettingSection>
           <SettingLabel>{t`How should users filter on this column?`}</SettingLabel>
-          <ParameterSourceSettings
+          <ValuesSourceSettings
             parameter={parameter}
+            onChangeQueryType={onChangeQueryType}
             onChangeSourceType={onChangeSourceType}
             onChangeSourceConfig={onChangeSourceConfig}
           />
diff --git a/frontend/src/metabase/parameters/components/ParameterSidebar/ParameterSidebar.tsx b/frontend/src/metabase/parameters/components/ParameterSidebar/ParameterSidebar.tsx
index 60d9cea10ab..fee77458a80 100644
--- a/frontend/src/metabase/parameters/components/ParameterSidebar/ParameterSidebar.tsx
+++ b/frontend/src/metabase/parameters/components/ParameterSidebar/ParameterSidebar.tsx
@@ -4,6 +4,7 @@ import Radio from "metabase/core/components/Radio";
 import Sidebar from "metabase/dashboard/components/Sidebar";
 import {
   ParameterId,
+  ValuesQueryType,
   ValuesSourceConfig,
   ValuesSourceType,
 } from "metabase-types/api";
@@ -22,6 +23,10 @@ export interface ParameterSidebarProps {
     parameterId: ParameterId,
     isMultiSelect: boolean,
   ) => void;
+  onChangeQueryType: (
+    parameterId: ParameterId,
+    sourceType: ValuesQueryType,
+  ) => void;
   onChangeSourceType: (
     parameterId: ParameterId,
     sourceType: ValuesSourceType,
@@ -45,6 +50,7 @@ const ParameterSidebar = ({
   onChangeName,
   onChangeDefaultValue,
   onChangeIsMultiSelect,
+  onChangeQueryType,
   onChangeSourceType,
   onChangeSourceConfig,
   onChangeFilteringParameters,
@@ -77,6 +83,13 @@ const ParameterSidebar = ({
     [parameterId, onChangeIsMultiSelect],
   );
 
+  const handleQueryTypeChange = useCallback(
+    (queryType: ValuesQueryType) => {
+      onChangeQueryType(parameterId, queryType);
+    },
+    [parameterId, onChangeQueryType],
+  );
+
   const handleSourceTypeChange = useCallback(
     (sourceType: ValuesSourceType) => {
       onChangeSourceType(parameterId, sourceType);
@@ -120,6 +133,7 @@ const ParameterSidebar = ({
             onChangeName={handleNameChange}
             onChangeDefaultValue={handleDefaultValueChange}
             onChangeIsMultiSelect={handleIsMultiSelectChange}
+            onChangeQueryType={handleQueryTypeChange}
             onChangeSourceType={handleSourceTypeChange}
             onChangeSourceConfig={handleSourceConfigChange}
             onRemoveParameter={handleRemove}
diff --git a/frontend/src/metabase/parameters/components/ParameterSourceSettings/index.ts b/frontend/src/metabase/parameters/components/ParameterSourceSettings/index.ts
deleted file mode 100644
index cad1d725724..00000000000
--- a/frontend/src/metabase/parameters/components/ParameterSourceSettings/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from "./ParameterSourceSettings";
diff --git a/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceModal.tsx b/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceModal.tsx
index 7c8a8c69ff5..db95cb5c247 100644
--- a/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceModal.tsx
+++ b/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceModal.tsx
@@ -2,7 +2,6 @@ import React, { useCallback, useMemo, useState } from "react";
 import { ValuesSourceConfig, ValuesSourceType } from "metabase-types/api";
 import { getNonVirtualFields } from "metabase-lib/parameters/utils/parameter-fields";
 import { UiParameter } from "metabase-lib/parameters/types";
-import { getSourceConfig, getSourceType } from "../../utils/dashboards";
 import ValuesSourceTypeModal from "./ValuesSourceTypeModal";
 import ValuesSourceCardModal from "./ValuesSourceCardModal";
 
@@ -23,8 +22,10 @@ const ValuesSourceModal = ({
   onClose,
 }: ModalProps): JSX.Element => {
   const [step, setStep] = useState<ModalStep>("main");
-  const [sourceType, setSourceType] = useState(getSourceType(parameter));
-  const [sourceConfig, setSourceConfig] = useState(getSourceConfig(parameter));
+  const [sourceType, setSourceType] = useState(parameter.values_source_type);
+  const [sourceConfig, setSourceConfig] = useState(
+    parameter.values_source_config,
+  );
 
   const fields = useMemo(() => {
     return getNonVirtualFields(parameter);
diff --git a/frontend/src/metabase/parameters/components/ParameterSourceSettings/ParameterSourceSettings.styled.tsx b/frontend/src/metabase/parameters/components/ValuesSourceSettings/ValuesSourceSettings.styled.tsx
similarity index 100%
rename from frontend/src/metabase/parameters/components/ParameterSourceSettings/ParameterSourceSettings.styled.tsx
rename to frontend/src/metabase/parameters/components/ValuesSourceSettings/ValuesSourceSettings.styled.tsx
diff --git a/frontend/src/metabase/parameters/components/ParameterSourceSettings/ParameterSourceSettings.tsx b/frontend/src/metabase/parameters/components/ValuesSourceSettings/ValuesSourceSettings.tsx
similarity index 53%
rename from frontend/src/metabase/parameters/components/ParameterSourceSettings/ParameterSourceSettings.tsx
rename to frontend/src/metabase/parameters/components/ValuesSourceSettings/ValuesSourceSettings.tsx
index cdc5e3f6a51..22b1a8d8afe 100644
--- a/frontend/src/metabase/parameters/components/ParameterSourceSettings/ParameterSourceSettings.tsx
+++ b/frontend/src/metabase/parameters/components/ValuesSourceSettings/ValuesSourceSettings.tsx
@@ -2,31 +2,38 @@ import React, { useCallback, useMemo, useState } from "react";
 import { t } from "ttag";
 import Radio from "metabase/core/components/Radio/Radio";
 import Modal from "metabase/components/Modal";
-import { ValuesSourceConfig, ValuesSourceType } from "metabase-types/api";
+import {
+  ValuesQueryType,
+  ValuesSourceConfig,
+  ValuesSourceType,
+} from "metabase-types/api";
 import { UiParameter } from "metabase-lib/parameters/types";
 import ValuesSourceModal from "../ValuesSourceModal";
 import {
   RadioLabelButton,
   RadioLabelRoot,
   RadioLabelTitle,
-} from "./ParameterSourceSettings.styled";
+} from "./ValuesSourceSettings.styled";
 
-export interface ParameterSourceSettingsProps {
+export interface ValuesSourceSettingsProps {
   parameter: UiParameter;
+  onChangeQueryType: (queryType: ValuesQueryType) => void;
   onChangeSourceType: (sourceType: ValuesSourceType) => void;
   onChangeSourceConfig: (sourceConfig: ValuesSourceConfig) => void;
 }
 
-const ParameterSourceSettings = ({
+const ValuesSourceSettings = ({
   parameter,
+  onChangeQueryType,
   onChangeSourceType,
   onChangeSourceConfig,
-}: ParameterSourceSettingsProps): JSX.Element => {
+}: ValuesSourceSettingsProps): JSX.Element => {
+  const queryType = parameter.values_query_type;
   const [isModalOpened, setIsModalOpened] = useState(false);
 
   const radioOptions = useMemo(() => {
-    return getRadioOptions(() => setIsModalOpened(true));
-  }, []);
+    return getRadioOptions(queryType, () => setIsModalOpened(true));
+  }, [queryType]);
 
   const handleSubmit = useCallback(
     (sourceType: ValuesSourceType, sourceConfig: ValuesSourceConfig) => {
@@ -42,7 +49,12 @@ const ParameterSourceSettings = ({
 
   return (
     <>
-      <Radio value="list" options={radioOptions} vertical />
+      <Radio
+        value={queryType}
+        options={radioOptions}
+        vertical
+        onChange={onChangeQueryType}
+      />
       {isModalOpened && (
         <Modal medium onClose={handleModalClose}>
           <ValuesSourceModal
@@ -58,25 +70,49 @@ const ParameterSourceSettings = ({
 
 interface RadioLabelProps {
   title: string;
-  onEditClick: () => void;
+  isSelected?: boolean;
+  onEditClick?: () => void;
 }
 
-const RadioLabel = ({ title, onEditClick }: RadioLabelProps): JSX.Element => {
+const RadioLabel = ({
+  title,
+  isSelected,
+  onEditClick,
+}: RadioLabelProps): JSX.Element => {
   return (
     <RadioLabelRoot>
       <RadioLabelTitle>{title}</RadioLabelTitle>
-      <RadioLabelButton onClick={onEditClick}>{t`Edit`}</RadioLabelButton>
+      {isSelected && (
+        <RadioLabelButton onClick={onEditClick}>{t`Edit`}</RadioLabelButton>
+      )}
     </RadioLabelRoot>
   );
 };
 
-const getRadioOptions = (onEditClick: () => void) => {
+const getRadioOptions = (
+  queryType: ValuesQueryType,
+  onEditClick: () => void,
+) => {
   return [
     {
-      name: <RadioLabel title={t`Dropdown list`} onEditClick={onEditClick} />,
+      name: (
+        <RadioLabel
+          title={t`Dropdown list`}
+          isSelected={queryType === "list"}
+          onEditClick={onEditClick}
+        />
+      ),
       value: "list",
     },
+    {
+      name: <RadioLabel title={t`Search box`} />,
+      value: "search",
+    },
+    {
+      name: <RadioLabel title={t`Input box`} />,
+      value: "none",
+    },
   ];
 };
 
-export default ParameterSourceSettings;
+export default ValuesSourceSettings;
diff --git a/frontend/src/metabase/parameters/components/ValuesSourceSettings/index.ts b/frontend/src/metabase/parameters/components/ValuesSourceSettings/index.ts
new file mode 100644
index 00000000000..8d5586d9228
--- /dev/null
+++ b/frontend/src/metabase/parameters/components/ValuesSourceSettings/index.ts
@@ -0,0 +1 @@
+export { default } from "./ValuesSourceSettings";
diff --git a/frontend/src/metabase/parameters/utils/dashboards.ts b/frontend/src/metabase/parameters/utils/dashboards.ts
index 8e6e5040d28..3f798412186 100644
--- a/frontend/src/metabase/parameters/utils/dashboards.ts
+++ b/frontend/src/metabase/parameters/utils/dashboards.ts
@@ -8,8 +8,6 @@ import type {
   Dashboard,
   DashboardParameterMapping,
   DashboardOrderedCard,
-  ValuesSourceType,
-  ValuesSourceConfig,
   Parameter,
 } from "metabase-types/api";
 import { isFieldFilterParameter } from "metabase-lib/parameters/utils/parameter-type";
@@ -41,13 +39,17 @@ export function createParameter(
     name = (option.combinedName || option.name) + " " + ++nameIndex;
   }
 
-  const parameter = {
+  const parameter: Parameter = {
     name: "",
     slug: "",
     id: generateParameterId(),
     type: option.type,
     sectionId: option.sectionId,
+    values_query_type: "list",
+    values_source_type: null,
+    values_source_config: {},
   };
+
   return setParameterName(parameter, name);
 }
 
@@ -66,14 +68,6 @@ export function setParameterName(
   };
 }
 
-export function getSourceType(parameter: Parameter): ValuesSourceType {
-  return parameter.values_source_type ?? null;
-}
-
-export function getSourceConfig(parameter: Parameter): ValuesSourceConfig {
-  return parameter.values_source_config ?? {};
-}
-
 export function getIsMultiSelect(parameter: Parameter): boolean {
   return parameter.isMultiSelect == null ? true : parameter.isMultiSelect;
 }
diff --git a/frontend/src/metabase/parameters/utils/dashboards.unit.spec.js b/frontend/src/metabase/parameters/utils/dashboards.unit.spec.js
index 4728c636bc4..93fc4360249 100644
--- a/frontend/src/metabase/parameters/utils/dashboards.unit.spec.js
+++ b/frontend/src/metabase/parameters/utils/dashboards.unit.spec.js
@@ -30,6 +30,9 @@ describe("metabase/parameters/utils/dashboards", () => {
         sectionId: "abc",
         slug: "foo_bar",
         type: "category",
+        values_query_type: "list",
+        values_source_type: null,
+        values_source_config: {},
       });
     });
 
@@ -50,6 +53,9 @@ describe("metabase/parameters/utils/dashboards", () => {
         sectionId: "abc",
         slug: "foo_bar_baz",
         type: "category",
+        values_query_type: "list",
+        values_source_type: null,
+        values_source_config: {},
       });
     });
 
@@ -78,6 +84,9 @@ describe("metabase/parameters/utils/dashboards", () => {
         sectionId: "abc",
         slug: "foo_bar_1",
         type: "category",
+        values_query_type: "list",
+        values_source_type: null,
+        values_source_config: {},
       });
     });
   });
diff --git a/frontend/src/metabase/parameters/utils/parameter-type.unit.spec.ts b/frontend/src/metabase/parameters/utils/parameter-type.unit.spec.ts
index b45f56c2ede..04a90210878 100644
--- a/frontend/src/metabase/parameters/utils/parameter-type.unit.spec.ts
+++ b/frontend/src/metabase/parameters/utils/parameter-type.unit.spec.ts
@@ -1,37 +1,27 @@
+import { createMockParameter } from "metabase-types/api/mocks";
 import { isSingleOrMultiSelectable } from "./parameter-type";
 
-const requiredParameterAttributes = {
-  id: "1",
-  name: "Name",
-  slug: "slug",
-  type: "a type",
-};
-
 describe("isSingleOrMultiSelectable", () => {
   it("is false for parameters with types not included", () => {
-    const parameter = {
-      ...requiredParameterAttributes,
+    const parameter = createMockParameter({
       sectionId: "number",
-      subType: "!=",
-    };
+    });
     expect(isSingleOrMultiSelectable(parameter)).toBe(false);
   });
 
   it("is false for parameters with acceptable types and rejected subTypes", () => {
-    const parameter = {
-      ...requiredParameterAttributes,
+    const parameter = createMockParameter({
+      type: "a type",
       sectionId: "string",
-      subType: "ends-with",
-    };
+    });
     expect(isSingleOrMultiSelectable(parameter)).toBe(false);
   });
 
   it("is true for parameters with acceptable types and corresponding subTypes", () => {
-    const parameter = {
-      ...requiredParameterAttributes,
-      sectionId: "location",
+    const parameter = createMockParameter({
       type: "string/=",
-    };
+      sectionId: "location",
+    });
     expect(isSingleOrMultiSelectable(parameter)).toBe(true);
   });
 });
diff --git a/frontend/test/metabase-lib/lib/Question.unit.spec.js b/frontend/test/metabase-lib/lib/Question.unit.spec.js
index 6aad50d7e4a..8d94fbc54ad 100644
--- a/frontend/test/metabase-lib/lib/Question.unit.spec.js
+++ b/frontend/test/metabase-lib/lib/Question.unit.spec.js
@@ -1130,6 +1130,9 @@ describe("Question", () => {
           slug: "foo",
           target: ["dimension", ["template-tag", "foo"]],
           type: "category",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
         {
           default: undefined,
@@ -1139,6 +1142,9 @@ describe("Question", () => {
           slug: "bar",
           target: ["variable", ["template-tag", "bar"]],
           type: "category",
+          values_query_type: "list",
+          values_source_type: null,
+          values_source_config: {},
         },
       ]);
     });
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.cy.spec.js
index 6b0ccaa78c1..a9946ea4dfe 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.cy.spec.js
@@ -47,7 +47,7 @@ describe("scenarios > dashboard > filters > location", () => {
   });
 
   it(`should work when set as the default filter`, () => {
-    setFilter("Location", "Dropdown");
+    setFilter("Location", "Is");
     cy.findByText("Select…").click();
     popover().contains("City").click();
 
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.js
index 6eab1fc6d87..d6bc2a17c91 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-location.js
@@ -1,5 +1,5 @@
 export const DASHBOARD_LOCATION_FILTERS = {
-  Dropdown: {
+  Is: {
     value: "Abbeville",
     representativeResult: "1510",
   },
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-source.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-source.cy.spec.js
index 16549cbd362..ed5c51229a5 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-source.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-source.cy.spec.js
@@ -55,7 +55,7 @@ describe("scenarios > dashboard > filters", () => {
     });
 
     editDashboard();
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
     mapFilterToQuestion();
     editDropdown();
     setupStructuredQuestionSource();
@@ -72,7 +72,7 @@ describe("scenarios > dashboard > filters", () => {
     });
 
     editDashboard();
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
     mapFilterToQuestion();
     editDropdown();
     setupNativeQuestionSource();
@@ -88,7 +88,7 @@ describe("scenarios > dashboard > filters", () => {
     });
 
     editDashboard();
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
     mapFilterToQuestion();
     editDropdown();
     setupCustomList();
@@ -110,7 +110,7 @@ describe("scenarios > dashboard > filters", () => {
     });
 
     editDashboard();
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
     mapFilterToQuestion();
     editDropdown();
     setupStructuredQuestionSource();
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.cy.spec.js
index 36c06d47948..2777dd6f8ca 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.cy.spec.js
@@ -56,10 +56,10 @@ describe("scenarios > dashboard > filters > location", () => {
   });
 
   it(`should work when set as the default filter`, () => {
-    setFilter("Location", "Dropdown");
+    setFilter("Location", "Is");
 
     cy.findByText("Select…").click();
-    popover().contains("Dropdown").click();
+    popover().contains("Is").click();
 
     cy.findByText("Default value").next().click();
 
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.js
index 3fc700b5be8..c26af717ce2 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-location.js
@@ -6,12 +6,12 @@ export const questionDetails = {
   name: "SQL with Field Filter",
   native: {
     query:
-      "select PEOPLE.NAME, PEOPLE.CITY from PEOPLE where true \n[[AND {{dropdown}}]] \n[[AND {{not}}]] \n[[AND {{contains}}]] \n[[AND {{doesntcontain}}]] \n[[AND {{startswith}}]] \n[[AND {{endswith}}]] limit 10",
+      "select PEOPLE.NAME, PEOPLE.CITY from PEOPLE where true \n[[AND {{is}}]] \n[[AND {{not}}]] \n[[AND {{contains}}]] \n[[AND {{doesntcontain}}]] \n[[AND {{startswith}}]] \n[[AND {{endswith}}]] limit 10",
     "template-tags": {
-      dropdown: {
+      is: {
         id: "bcd8b984-2e16-ffa4-82fc-2895ac8570f9",
-        name: "dropdown",
-        "display-name": "Dropdown",
+        name: "is",
+        "display-name": "Is",
         type: "dimension",
         dimension: ["field", PEOPLE.CITY, null],
         "widget-type": "string/=",
@@ -67,7 +67,7 @@ export const questionDetails = {
 };
 
 export const DASHBOARD_SQL_LOCATION_FILTERS = {
-  Dropdown: {
+  Is: {
     sqlFilter: "string/=",
     value: "Rye",
     representativeResult: "Arnold Adams",
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.cy.spec.js
index 315e1a5dc29..23bd1d752c3 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.cy.spec.js
@@ -58,14 +58,14 @@ describe("scenarios > dashboard > filters > SQL > text/category", () => {
   });
 
   it(`should work when set as the default filter and when that filter is removed (metabase#20493)`, () => {
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
 
     cy.findByText("Select…").click();
-    popover().contains("Dropdown").click();
+    popover().contains("Is").click();
 
     cy.findByText("Default value").next().click();
 
-    applyFilterByType("Dropdown", "Gizmo");
+    applyFilterByType("Is", "Gizmo");
 
     saveDashboard();
 
@@ -79,7 +79,7 @@ describe("scenarios > dashboard > filters > SQL > text/category", () => {
 
     filterWidget().click();
 
-    applyFilterByType("Dropdown", "Doohickey");
+    applyFilterByType("Is", "Doohickey");
 
     cy.findByText("Rustic Paper Wallet").should("not.exist");
   });
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.js
index 233037a276e..12db381c7a7 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-sql-text-category.js
@@ -3,7 +3,7 @@ import { SAMPLE_DATABASE } from "__support__/e2e/cypress_sample_database";
 const { PRODUCTS } = SAMPLE_DATABASE;
 
 export const DASHBOARD_SQL_TEXT_FILTERS = {
-  Dropdown: {
+  Is: {
     sqlFilter: "string/=",
     value: "Gizmo",
     representativeResult: "Rustic Paper Wallet",
@@ -39,12 +39,12 @@ export const questionDetails = {
   name: "SQL with Field Filter",
   native: {
     query:
-      "select * from PRODUCTS where true \n[[AND {{dropdown}}]] \n[[AND {{not}}]] \n[[AND {{contains}}]] \n[[AND {{doesntcontain}}]] \n[[AND {{startswith}}]] \n[[AND {{endswith}}]]",
+      "select * from PRODUCTS where true \n[[AND {{is}}]] \n[[AND {{not}}]] \n[[AND {{contains}}]] \n[[AND {{doesntcontain}}]] \n[[AND {{startswith}}]] \n[[AND {{endswith}}]]",
     "template-tags": {
-      dropdown: {
+      is: {
         id: "bcd8b984-2e16-ffa4-82fc-2895ac8570f9",
-        name: "dropdown",
-        "display-name": "Dropdown",
+        name: "is",
+        "display-name": "Is",
         type: "dimension",
         dimension: ["field", PRODUCTS.CATEGORY, null],
         "widget-type": "string/=",
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.cy.spec.js
index 66341843200..2cab532361e 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.cy.spec.js
@@ -48,14 +48,14 @@ describe("scenarios > dashboard > filters > text/category", () => {
   });
 
   it(`should work when set as the default filter which (if cleared) should not be preserved on reload (metabase#13960)`, () => {
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
 
     cy.findByText("Select…").click();
     popover().contains("Source").click();
 
     cy.findByText("Default value").next().click();
 
-    applyFilterByType("Dropdown", "Organic");
+    applyFilterByType("Is", "Organic");
 
     // We need to add another filter only to reproduce metabase#13960
     setFilter("ID");
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.js b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.js
index c5528cf8d82..88336ad7d13 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/dashboard-filters-text-category.js
@@ -1,5 +1,5 @@
 export const DASHBOARD_TEXT_FILTERS = {
-  Dropdown: {
+  Is: {
     value: "Organic",
     representativeResult: "39.58",
   },
diff --git a/frontend/test/metabase/scenarios/dashboard-filters/parameters.cy.spec.js b/frontend/test/metabase/scenarios/dashboard-filters/parameters.cy.spec.js
index a72e43bae12..42b4f946c1f 100644
--- a/frontend/test/metabase/scenarios/dashboard-filters/parameters.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard-filters/parameters.cy.spec.js
@@ -37,7 +37,7 @@ describe("scenarios > dashboard > parameters", () => {
     // add a category filter
     cy.icon("filter").click();
     cy.contains("Text or Category").click();
-    cy.findByText("Dropdown").click();
+    cy.findByText("Is").click();
     cy.findByText("A single value").click();
 
     // connect it to people.name and product.category
diff --git a/frontend/test/metabase/scenarios/dashboard/chained-filters.cy.spec.js b/frontend/test/metabase/scenarios/dashboard/chained-filters.cy.spec.js
index 4fcda2dc0db..d2fe17b0bc2 100644
--- a/frontend/test/metabase/scenarios/dashboard/chained-filters.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard/chained-filters.cy.spec.js
@@ -25,7 +25,7 @@ describe("scenarios > dashboard > chained filter", () => {
       cy.icon("filter").click();
       popover().within(() => {
         cy.findByText("Location").click();
-        cy.findByText("Dropdown").click();
+        cy.findByText("Is").click();
       });
 
       // connect that to people.state
@@ -43,7 +43,7 @@ describe("scenarios > dashboard > chained filter", () => {
       cy.findByText("add another dashboard filter").click();
       popover().within(() => {
         cy.findByText("Location").click();
-        cy.findByText("Dropdown").click();
+        cy.findByText("Is").click();
       });
 
       // connect that to person.city
diff --git a/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js b/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js
index ef07f6b2e12..1ff6ff8a190 100644
--- a/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js
@@ -145,7 +145,7 @@ describe("scenarios > dashboard", () => {
     // Adding location/state doesn't make much sense for this case,
     // but we're testing just that the filter is added to the dashboard
     cy.findByText("Location").click();
-    cy.findByText("Dropdown").click();
+    cy.findByText("Is").click();
     cy.findByText("Select…").click();
 
     popover().within(() => {
diff --git a/frontend/test/metabase/scenarios/dashboard/dashboard_data_permissions.cy.spec.js b/frontend/test/metabase/scenarios/dashboard/dashboard_data_permissions.cy.spec.js
index d29814adf89..11b9e4c2db2 100644
--- a/frontend/test/metabase/scenarios/dashboard/dashboard_data_permissions.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard/dashboard_data_permissions.cy.spec.js
@@ -42,7 +42,7 @@ describe("support > permissions (metabase#8472)", () => {
     cy.icon("filter").click();
     popover().contains("Text or Category").click();
 
-    popover().contains("Dropdown").click();
+    popover().contains("Is").click();
 
     // Filter the first card by User Address
     selectDashboardFilter(cy.get(".DashCard").first(), "Address");
diff --git a/frontend/test/metabase/scenarios/dashboard/text-box.cy.spec.js b/frontend/test/metabase/scenarios/dashboard/text-box.cy.spec.js
index 97c3282576f..106c5dd2db0 100644
--- a/frontend/test/metabase/scenarios/dashboard/text-box.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard/text-box.cy.spec.js
@@ -128,7 +128,7 @@ describe("scenarios > dashboard > text-box", () => {
     cy.icon("filter").click();
     popover().within(() => {
       cy.findByText("Text or Category").click();
-      cy.findByText("Dropdown").click();
+      cy.findByText("Is").click();
     });
     cy.findByText("Save").click();
 
diff --git a/frontend/test/metabase/scenarios/models/reproductions/23024-cannot-apply-dash-filter-native-model.cy.spec.js b/frontend/test/metabase/scenarios/models/reproductions/23024-cannot-apply-dash-filter-native-model.cy.spec.js
index eadb80ac678..39d58cee088 100644
--- a/frontend/test/metabase/scenarios/models/reproductions/23024-cannot-apply-dash-filter-native-model.cy.spec.js
+++ b/frontend/test/metabase/scenarios/models/reproductions/23024-cannot-apply-dash-filter-native-model.cy.spec.js
@@ -46,7 +46,7 @@ describe.skip("issue 23024", () => {
     cy.icon("filter").click();
 
     cy.findByText("Text or Category").click();
-    cy.findByText("Dropdown").click();
+    cy.findByText("Is").click();
 
     cy.findByText("Column to filter on")
       .parent()
diff --git a/frontend/test/metabase/scenarios/native-filters/helpers/e2e-field-filter-helpers.js b/frontend/test/metabase/scenarios/native-filters/helpers/e2e-field-filter-helpers.js
index 071998fbac8..131ca2ce21f 100644
--- a/frontend/test/metabase/scenarios/native-filters/helpers/e2e-field-filter-helpers.js
+++ b/frontend/test/metabase/scenarios/native-filters/helpers/e2e-field-filter-helpers.js
@@ -49,7 +49,7 @@ export function selectFilterValueFromList(value) {
  */
 
 export function applyFilterByType(filter, value) {
-  if (["Dropdown", "Is not"].includes(filter)) {
+  if (["Is", "Is not"].includes(filter)) {
     selectFilterValueFromList(value);
   } else {
     addWidgetStringFilter(value);
diff --git a/frontend/test/metabase/scenarios/sharing/public.cy.spec.js b/frontend/test/metabase/scenarios/sharing/public.cy.spec.js
index 2a2791004b5..e32b10b3b04 100644
--- a/frontend/test/metabase/scenarios/sharing/public.cy.spec.js
+++ b/frontend/test/metabase/scenarios/sharing/public.cy.spec.js
@@ -80,7 +80,7 @@ describe("scenarios > public", () => {
 
       popover().within(() => {
         cy.findByText("Text or Category").click();
-        cy.findByText("Dropdown").click();
+        cy.findByText("Is").click();
       });
 
       cy.contains("Select…").click();
diff --git a/frontend/test/metabase/scenarios/sharing/reproductions/22524-public-dashboard-updates-after-changing-parameters.cy.spec.js b/frontend/test/metabase/scenarios/sharing/reproductions/22524-public-dashboard-updates-after-changing-parameters.cy.spec.js
index 6bde1f33f01..14936b8003f 100644
--- a/frontend/test/metabase/scenarios/sharing/reproductions/22524-public-dashboard-updates-after-changing-parameters.cy.spec.js
+++ b/frontend/test/metabase/scenarios/sharing/reproductions/22524-public-dashboard-updates-after-changing-parameters.cy.spec.js
@@ -36,7 +36,7 @@ describe("issue 22524", () => {
     );
 
     editDashboard();
-    setFilter("Text or Category", "Dropdown");
+    setFilter("Text or Category", "Is");
 
     cy.findByText("Select…").click();
     popover().contains("City").click();
diff --git a/frontend/test/metabase/scenarios/sharing/subscriptions.cy.spec.js b/frontend/test/metabase/scenarios/sharing/subscriptions.cy.spec.js
index 7bc27a91058..8f0b0a60ead 100644
--- a/frontend/test/metabase/scenarios/sharing/subscriptions.cy.spec.js
+++ b/frontend/test/metabase/scenarios/sharing/subscriptions.cy.spec.js
@@ -375,7 +375,7 @@ function addParametersToDashboard() {
   // add Category > Dropdown "Name" filter
   cy.icon("filter").click();
   cy.findByText("Text or Category").click();
-  cy.findByText("Dropdown").click();
+  cy.findByText("Is").click();
 
   cy.findByText("Select…").click();
   popover().within(() => {
@@ -391,7 +391,7 @@ function addParametersToDashboard() {
   // add Category > Dropdown "Category" filter
   cy.icon("filter").click();
   cy.findByText("Text or Category").click();
-  cy.findByText("Dropdown").click();
+  cy.findByText("Is").click();
   cy.findByText("Select…").click();
   popover().within(() => {
     cy.findByText("Category").click();
-- 
GitLab