From 0870cc7fc1d4dade2fa785574e13fd193a5983a6 Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Wed, 11 Jan 2023 18:27:20 +0200 Subject: [PATCH] Add card field values preview (#27627) --- frontend/src/metabase-lib/Question.ts | 9 +++++ .../ValuesSourceTypeModal.tsx | 35 ++++++++++++++++--- .../dashboard-filters-source.cy.spec.js | 5 +++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/frontend/src/metabase-lib/Question.ts b/frontend/src/metabase-lib/Question.ts index f8a6bc72371..e35df2a87d5 100644 --- a/frontend/src/metabase-lib/Question.ts +++ b/frontend/src/metabase-lib/Question.ts @@ -555,6 +555,15 @@ class QuestionInner { return query.question().toUnderlyingRecords(); } + toFieldValues(field: Field): Question { + const query = this.composeThisQuery()?.query(); + if (query instanceof StructuredQuery) { + return query.setFields([field.reference()]).question(); + } + + return this; + } + toUnderlyingRecords(): Question { const query = this.query(); if (!(query instanceof StructuredQuery)) { diff --git a/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceTypeModal.tsx b/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceTypeModal.tsx index 92fe7333bd7..0b5bfb0029a 100644 --- a/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceTypeModal.tsx +++ b/frontend/src/metabase/parameters/components/ValuesSourceModal/ValuesSourceTypeModal.tsx @@ -10,6 +10,7 @@ import Select, { } from "metabase/core/components/Select"; import SelectButton from "metabase/core/components/SelectButton"; import ModalContent from "metabase/components/ModalContent"; +import QuestionResultLoader from "metabase/containers/QuestionResultLoader"; import Collections from "metabase/entities/collections"; import Fields from "metabase/entities/fields"; import Tables from "metabase/entities/tables"; @@ -17,6 +18,7 @@ import Questions from "metabase/entities/questions"; import { getMetadata } from "metabase/selectors/metadata"; import { Card, ValuesSourceConfig, ValuesSourceType } from "metabase-types/api"; import { Dispatch, State } from "metabase-types/store"; +import { Dataset } from "metabase-types/types/Dataset"; import Question from "metabase-lib/Question"; import Field from "metabase-lib/metadata/Field"; import { getQuestionVirtualTableId } from "metabase-lib/metadata/utils/saved-questions"; @@ -70,6 +72,10 @@ interface ModalDispatchProps { onFetchFieldValues: (fields: Field[]) => void; } +interface QuestionLoaderProps { + result?: Dataset; +} + type ModalProps = ModalOwnProps & ModalCardProps & ModalStateProps & @@ -91,7 +97,7 @@ const ValuesSourceTypeModal = ({ onClose, }: ModalProps): JSX.Element => { const allFieldValues = useMemo(() => { - return getUniqueFieldValues(fieldValues); + return getFieldValues(fieldValues); }, [fieldValues]); const handleTypeChange = useCallback( @@ -226,6 +232,10 @@ const CardSourceModal = ({ return getFieldByReference(fields, sourceConfig.value_field); }, [fields, sourceConfig]); + const fieldValuesQuestion = useMemo(() => { + return question && selectedField && question.toFieldValues(selectedField); + }, [question, selectedField]); + const handleFieldChange = useCallback( (event: SelectChangeEvent<Field>) => { onChangeSourceConfig({ @@ -288,7 +298,15 @@ const CardSourceModal = ({ ) : !selectedField ? ( <ModalEmptyState>{t`Pick a column`}</ModalEmptyState> ) : ( - <ModalTextArea readOnly fullWidth /> + <QuestionResultLoader question={fieldValuesQuestion}> + {({ result }: QuestionLoaderProps) => ( + <ModalTextArea + value={getValuesText(getDatasetValues(result))} + readOnly + fullWidth + /> + )} + </QuestionResultLoader> )} </ModalMain> </ModalBodyWithPane> @@ -345,9 +363,18 @@ const getValuesText = (values?: string[]) => { return values?.join(NEW_LINE) ?? ""; }; -const getUniqueFieldValues = (fieldsValues: string[][][]) => { +const getUniqueValues = (values: string[]) => { + return Array.from(new Set(values)); +}; + +const getFieldValues = (fieldsValues: string[][][]) => { const allValues = fieldsValues.flatMap(values => values.map(([key]) => key)); - return Array.from(new Set(allValues)); + return getUniqueValues(allValues); +}; + +const getDatasetValues = (dataset?: Dataset) => { + const allValues = dataset?.data.rows.map(([value]) => String(value)) ?? []; + return getUniqueValues(allValues); }; const getStaticValues = (value: string) => { 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 f927d5e5c08..16549cbd362 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 @@ -42,6 +42,7 @@ describe("scenarios > dashboard > filters", () => { beforeEach(() => { restore(); cy.signInAsAdmin(); + cy.intercept("POST", "/api/dataset").as("dataset"); cy.intercept("POST", "/api/dashboard/**/query").as("getCardQuery"); }); @@ -156,6 +157,8 @@ const setupStructuredQuestionSource = () => { }); modal().within(() => { + cy.wait("@dataset"); + cy.findByDisplayValue(/Gadget/).should("be.visible"); cy.button("Done").click(); }); }; @@ -180,6 +183,8 @@ const setupNativeQuestionSource = () => { }); modal().within(() => { + cy.wait("@dataset"); + cy.findByDisplayValue(/Gadget/).should("be.visible"); cy.button("Done").click(); }); }; -- GitLab