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