From 0b9bfbd21d1d012f0755149438a2d954c7c85084 Mon Sep 17 00:00:00 2001 From: Oisin Coveney <oisin@metabase.com> Date: Fri, 21 Jun 2024 15:38:01 +0300 Subject: [PATCH] Split `FilterModal` components into separate files and folders (#44530) --- .../BooleanFilterEditor.tsx | 0 .../BooleanFilterEditor.unit.spec.tsx | 0 .../BooleanFilterEditor/index.ts | 0 .../ColumnFilterSection.tsx | 0 .../ColumnFilterSection/index.ts | 0 .../CoordinateFilterEditor.tsx | 0 .../CoordinateFilterEditor.unit.spec.tsx | 0 .../CoordinateFilterEditor/index.ts | 0 .../DateFilterEditor.styled.tsx | 0 .../DateFilterEditor/DateFilterEditor.tsx | 0 .../DateFilterEditor.unit.spec.tsx | 0 .../DateFilterEditor/constants.ts | 0 .../DateFilterEditor/index.ts | 0 .../DateFilterEditor/utils.ts | 0 .../EmptyFilterEditor/EmptyFilterEditor.tsx | 0 .../EmptyFilterEditor/index.ts | 0 .../FilterColumnName/FilterColumnName.tsx | 0 .../FilterColumnName/index.ts | 0 .../FilterOperatorPicker.tsx | 0 .../FilterOperatorPicker/index.ts | 0 .../FilterSearchInput.styled.tsx | 0 .../FilterSearchInput/FilterSearchInput.tsx | 0 .../FilterSearchInput/index.ts | 0 .../FilterTitle/FilterTitle.tsx | 0 .../FilterTitle/index.tsx | 0 .../NumberFilterEditor/NumberFilterEditor.tsx | 0 .../NumberFilterEditor.unit.spec.tsx | 0 .../NumberFilterEditor/index.ts | 0 .../SegmentFilterEditor.tsx | 0 .../SegmentFilterEditor.unit.spec.tsx | 0 .../SegmentFilterEditor/index.ts | 0 .../StringFilterEditor/StringFilterEditor.tsx | 0 .../StringFilterEditor.unit.spec.tsx | 0 .../StringFilterEditor/index.ts | 0 .../FilterContent/TabContent/TabContent.tsx | 46 +++ .../FilterContent/TabContent/index.ts | 1 + .../FilterContent/TabList/TabList.styled.tsx | 8 + .../FilterContent/TabList/TabList.tsx | 26 ++ .../components/FilterContent/TabList/index.ts | 1 + .../TabPanel/TabPanel.styled.tsx | 7 + .../FilterContent/TabPanel/TabPanel.tsx | 46 +++ .../FilterContent/TabPanel/index.ts | 1 + .../TabPanelColumn/TabPanelColumnItem.tsx | 49 +++ .../TabPanelColumn/TabPanelColumnItemList.tsx | 41 +++ .../FilterContent/TabPanelColumn/columns.ts | 22 ++ .../FilterContent/TabPanelColumn/index.ts | 1 + .../TabPanelColumn}/sorting.ts | 0 .../TabPanelItem/TabPanelFilterItem.tsx | 50 +++ .../TabPanelItem/TabPanelItem.styled.tsx | 22 ++ .../TabPanelItem/TabPanelSegmentItem.tsx | 38 +++ .../FilterContent/TabPanelItem/index.ts | 2 + .../FilterContent/TabPanelItem/segments.ts | 32 ++ .../TimeFilterEditor/TimeFilterEditor.tsx | 0 .../TimeFilterEditor.unit.spec.tsx | 0 .../TimeFilterEditor/index.ts | 0 .../components/FilterContent/index.ts | 3 + .../{FilterModal => FilterContent}/types.ts | 0 .../FilterModal/FilterEmptyState.tsx | 12 + .../FilterModal/FilterModal.styled.tsx | 31 +- .../components/FilterModal/FilterModal.tsx | 301 +----------------- .../components/FilterModal/utils/filters.ts | 53 +-- .../components/FilterModal/utils/index.ts | 4 - .../components/FilterModal/utils/modal.ts | 2 +- .../components/FilterModal/utils/search.ts | 3 +- frontend/src/metabase/querying/index.ts | 4 + 65 files changed, 428 insertions(+), 378 deletions(-) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/BooleanFilterEditor/BooleanFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/BooleanFilterEditor/BooleanFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/BooleanFilterEditor/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/ColumnFilterSection/ColumnFilterSection.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/ColumnFilterSection/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/CoordinateFilterEditor/CoordinateFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/CoordinateFilterEditor/CoordinateFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/CoordinateFilterEditor/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/DateFilterEditor/DateFilterEditor.styled.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/DateFilterEditor/DateFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/DateFilterEditor/DateFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/DateFilterEditor/constants.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/DateFilterEditor/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/DateFilterEditor/utils.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/EmptyFilterEditor/EmptyFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/EmptyFilterEditor/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterColumnName/FilterColumnName.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterColumnName/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterOperatorPicker/FilterOperatorPicker.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterOperatorPicker/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterSearchInput/FilterSearchInput.styled.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterSearchInput/FilterSearchInput.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterSearchInput/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterTitle/FilterTitle.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/FilterTitle/index.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/NumberFilterEditor/NumberFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/NumberFilterEditor/NumberFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/NumberFilterEditor/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/SegmentFilterEditor/SegmentFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/SegmentFilterEditor/SegmentFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/SegmentFilterEditor/index.ts (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/StringFilterEditor/StringFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/StringFilterEditor/StringFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/StringFilterEditor/index.ts (100%) create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabContent/TabContent.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabContent/index.ts create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabList/TabList.styled.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabList/TabList.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabList/index.ts create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.styled.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanel/index.ts create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItem.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItemList.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/columns.ts create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/index.ts rename frontend/src/metabase/querying/components/{FilterModal/utils => FilterContent/TabPanelColumn}/sorting.ts (100%) create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelFilterItem.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelItem.styled.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelSegmentItem.tsx create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelItem/index.ts create mode 100644 frontend/src/metabase/querying/components/FilterContent/TabPanelItem/segments.ts rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/TimeFilterEditor/TimeFilterEditor.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/TimeFilterEditor/TimeFilterEditor.unit.spec.tsx (100%) rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/TimeFilterEditor/index.ts (100%) create mode 100644 frontend/src/metabase/querying/components/FilterContent/index.ts rename frontend/src/metabase/querying/components/{FilterModal => FilterContent}/types.ts (100%) create mode 100644 frontend/src/metabase/querying/components/FilterModal/FilterEmptyState.tsx delete mode 100644 frontend/src/metabase/querying/components/FilterModal/utils/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/BooleanFilterEditor/BooleanFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/BooleanFilterEditor/BooleanFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/BooleanFilterEditor/BooleanFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/BooleanFilterEditor/BooleanFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/BooleanFilterEditor/BooleanFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/BooleanFilterEditor/BooleanFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/BooleanFilterEditor/BooleanFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/BooleanFilterEditor/BooleanFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/BooleanFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/BooleanFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/BooleanFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/BooleanFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/ColumnFilterSection/ColumnFilterSection.tsx b/frontend/src/metabase/querying/components/FilterContent/ColumnFilterSection/ColumnFilterSection.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/ColumnFilterSection/ColumnFilterSection.tsx rename to frontend/src/metabase/querying/components/FilterContent/ColumnFilterSection/ColumnFilterSection.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/ColumnFilterSection/index.ts b/frontend/src/metabase/querying/components/FilterContent/ColumnFilterSection/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/ColumnFilterSection/index.ts rename to frontend/src/metabase/querying/components/FilterContent/ColumnFilterSection/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/CoordinateFilterEditor/CoordinateFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/CoordinateFilterEditor/CoordinateFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/CoordinateFilterEditor/CoordinateFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/CoordinateFilterEditor/CoordinateFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/CoordinateFilterEditor/CoordinateFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/CoordinateFilterEditor/CoordinateFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/CoordinateFilterEditor/CoordinateFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/CoordinateFilterEditor/CoordinateFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/CoordinateFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/CoordinateFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/CoordinateFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/CoordinateFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/DateFilterEditor.styled.tsx b/frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/DateFilterEditor.styled.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/DateFilterEditor.styled.tsx rename to frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/DateFilterEditor.styled.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/DateFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/DateFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/DateFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/DateFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/DateFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/DateFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/DateFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/DateFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/constants.ts b/frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/constants.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/constants.ts rename to frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/constants.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/utils.ts b/frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/utils.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/DateFilterEditor/utils.ts rename to frontend/src/metabase/querying/components/FilterContent/DateFilterEditor/utils.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/EmptyFilterEditor/EmptyFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/EmptyFilterEditor/EmptyFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/EmptyFilterEditor/EmptyFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/EmptyFilterEditor/EmptyFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/EmptyFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/EmptyFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/EmptyFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/EmptyFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterColumnName/FilterColumnName.tsx b/frontend/src/metabase/querying/components/FilterContent/FilterColumnName/FilterColumnName.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterColumnName/FilterColumnName.tsx rename to frontend/src/metabase/querying/components/FilterContent/FilterColumnName/FilterColumnName.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterColumnName/index.ts b/frontend/src/metabase/querying/components/FilterContent/FilterColumnName/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterColumnName/index.ts rename to frontend/src/metabase/querying/components/FilterContent/FilterColumnName/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterOperatorPicker/FilterOperatorPicker.tsx b/frontend/src/metabase/querying/components/FilterContent/FilterOperatorPicker/FilterOperatorPicker.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterOperatorPicker/FilterOperatorPicker.tsx rename to frontend/src/metabase/querying/components/FilterContent/FilterOperatorPicker/FilterOperatorPicker.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterOperatorPicker/index.ts b/frontend/src/metabase/querying/components/FilterContent/FilterOperatorPicker/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterOperatorPicker/index.ts rename to frontend/src/metabase/querying/components/FilterContent/FilterOperatorPicker/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterSearchInput/FilterSearchInput.styled.tsx b/frontend/src/metabase/querying/components/FilterContent/FilterSearchInput/FilterSearchInput.styled.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterSearchInput/FilterSearchInput.styled.tsx rename to frontend/src/metabase/querying/components/FilterContent/FilterSearchInput/FilterSearchInput.styled.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterSearchInput/FilterSearchInput.tsx b/frontend/src/metabase/querying/components/FilterContent/FilterSearchInput/FilterSearchInput.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterSearchInput/FilterSearchInput.tsx rename to frontend/src/metabase/querying/components/FilterContent/FilterSearchInput/FilterSearchInput.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterSearchInput/index.ts b/frontend/src/metabase/querying/components/FilterContent/FilterSearchInput/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterSearchInput/index.ts rename to frontend/src/metabase/querying/components/FilterContent/FilterSearchInput/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterTitle/FilterTitle.tsx b/frontend/src/metabase/querying/components/FilterContent/FilterTitle/FilterTitle.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterTitle/FilterTitle.tsx rename to frontend/src/metabase/querying/components/FilterContent/FilterTitle/FilterTitle.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterTitle/index.tsx b/frontend/src/metabase/querying/components/FilterContent/FilterTitle/index.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/FilterTitle/index.tsx rename to frontend/src/metabase/querying/components/FilterContent/FilterTitle/index.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/NumberFilterEditor/NumberFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/NumberFilterEditor/NumberFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/NumberFilterEditor/NumberFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/NumberFilterEditor/NumberFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/NumberFilterEditor/NumberFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/NumberFilterEditor/NumberFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/NumberFilterEditor/NumberFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/NumberFilterEditor/NumberFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/NumberFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/NumberFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/NumberFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/NumberFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/SegmentFilterEditor/SegmentFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/SegmentFilterEditor/SegmentFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/SegmentFilterEditor/SegmentFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/SegmentFilterEditor/SegmentFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/SegmentFilterEditor/SegmentFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/SegmentFilterEditor/SegmentFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/SegmentFilterEditor/SegmentFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/SegmentFilterEditor/SegmentFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/SegmentFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/SegmentFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/SegmentFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/SegmentFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/StringFilterEditor/StringFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/StringFilterEditor/StringFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/StringFilterEditor/StringFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/StringFilterEditor/StringFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/StringFilterEditor/StringFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/StringFilterEditor/StringFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/StringFilterEditor/StringFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/StringFilterEditor/StringFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/StringFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/StringFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/StringFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/StringFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterContent/TabContent/TabContent.tsx b/frontend/src/metabase/querying/components/FilterContent/TabContent/TabContent.tsx new file mode 100644 index 00000000000..358e1e163d0 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabContent/TabContent.tsx @@ -0,0 +1,46 @@ +import { Flex, Tabs } from "metabase/ui"; +import type * as Lib from "metabase-lib"; + +import { TabList } from "../TabList"; +import { TabPanel } from "../TabPanel"; +import type { GroupItem } from "../types"; + +export interface TabContentProps { + query: Lib.Query; + groupItems: GroupItem[]; + tab: string | null; + version: number; + isSearching: boolean; + onChange: (query: Lib.Query) => void; + onInput: () => void; + onTabChange: (tab: string | null) => void; +} + +export function TabContent({ + query, + groupItems, + tab, + version, + isSearching, + onChange, + onInput, + onTabChange, +}: TabContentProps) { + return ( + <Tabs value={tab} onTabChange={onTabChange} orientation="vertical" h="100%"> + <Flex direction="row" w="100%"> + {groupItems.length > 1 && <TabList groupItems={groupItems} />} + {groupItems.map(groupItem => ( + <TabPanel + key={`${groupItem.key}:${version}`} + query={query} + groupItem={groupItem} + isSearching={isSearching} + onChange={onChange} + onInput={onInput} + /> + ))} + </Flex> + </Tabs> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabContent/index.ts b/frontend/src/metabase/querying/components/FilterContent/TabContent/index.ts new file mode 100644 index 00000000000..6cf08a2ade1 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabContent/index.ts @@ -0,0 +1 @@ +export * from "./TabContent"; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabList/TabList.styled.tsx b/frontend/src/metabase/querying/components/FilterContent/TabList/TabList.styled.tsx new file mode 100644 index 00000000000..c1dd09a6c29 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabList/TabList.styled.tsx @@ -0,0 +1,8 @@ +import styled from "@emotion/styled"; + +import { Tabs } from "metabase/ui"; + +export const TabsListSidebar = styled(Tabs.List)` + overflow-y: auto; + flex-wrap: nowrap; +`; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabList/TabList.tsx b/frontend/src/metabase/querying/components/FilterContent/TabList/TabList.tsx new file mode 100644 index 00000000000..3da3b48ab69 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabList/TabList.tsx @@ -0,0 +1,26 @@ +import { Icon, Tabs } from "metabase/ui"; + +import type { GroupItem } from "../types"; + +import { TabsListSidebar } from "./TabList.styled"; + +export interface TabListProps { + groupItems: GroupItem[]; +} + +export function TabList({ groupItems }: TabListProps) { + return ( + <TabsListSidebar w="25%" pt="sm" pl="md"> + {groupItems.map(groupItem => ( + <Tabs.Tab + key={groupItem.key} + value={groupItem.key} + aria-label={groupItem.displayName} + icon={<Icon name={groupItem.icon} />} + > + {groupItem.displayName} + </Tabs.Tab> + ))} + </TabsListSidebar> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabList/index.ts b/frontend/src/metabase/querying/components/FilterContent/TabList/index.ts new file mode 100644 index 00000000000..abb98da193a --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabList/index.ts @@ -0,0 +1 @@ +export * from "./TabList"; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.styled.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.styled.tsx new file mode 100644 index 00000000000..6306f8413ac --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.styled.tsx @@ -0,0 +1,7 @@ +import styled from "@emotion/styled"; + +import { Tabs } from "metabase/ui"; + +export const TabPanelRoot = styled(Tabs.Panel)` + overflow-y: auto; +`; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.tsx new file mode 100644 index 00000000000..27ddf5720ef --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanel/TabPanel.tsx @@ -0,0 +1,46 @@ +import type * as Lib from "metabase-lib"; + +import { TabPanelColumnItemList } from "../TabPanelColumn"; +import { TabPanelSegmentItem } from "../TabPanelItem"; +import type { GroupItem } from "../types"; + +import { TabPanelRoot } from "./TabPanel.styled"; + +export interface TabPanelProps { + query: Lib.Query; + groupItem: GroupItem; + isSearching: boolean; + onChange: (newQuery: Lib.Query) => void; + onInput: () => void; +} + +export function TabPanel({ + query, + groupItem, + isSearching, + onChange, + onInput, +}: TabPanelProps) { + return ( + <TabPanelRoot value={groupItem.key}> + <ul> + {groupItem.segmentItems.length > 0 && ( + <TabPanelSegmentItem + query={query} + segmentItems={groupItem.segmentItems} + onChange={onChange} + /> + )} + {groupItem.columnItems.length > 0 && ( + <TabPanelColumnItemList + query={query} + columnItems={groupItem.columnItems} + isSearching={isSearching} + onChange={onChange} + onInput={onInput} + /> + )} + </ul> + </TabPanelRoot> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanel/index.ts b/frontend/src/metabase/querying/components/FilterContent/TabPanel/index.ts new file mode 100644 index 00000000000..bed5cc54b96 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanel/index.ts @@ -0,0 +1 @@ +export * from "./TabPanel"; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItem.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItem.tsx new file mode 100644 index 00000000000..9702e2a4c6e --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItem.tsx @@ -0,0 +1,49 @@ +import { useMemo, useState } from "react"; + +import { DelayGroup } from "metabase/ui"; +import type * as Lib from "metabase-lib"; + +import { TabPanelFilterItem } from "../TabPanelItem"; +import type { ColumnItem } from "../types"; + +import { findColumnFilters, findVisibleFilters } from "./columns"; + +export interface TabPanelColumnItemProps { + query: Lib.Query; + columnItem: ColumnItem; + isSearching: boolean; + onChange: (newQuery: Lib.Query) => void; + onInput: () => void; +} + +export function TabPanelColumnItem({ + query, + columnItem, + isSearching, + onChange, + onInput, +}: TabPanelColumnItemProps) { + const { column, stageIndex } = columnItem; + const currentFilters = useMemo( + () => findColumnFilters(query, stageIndex, column), + [query, stageIndex, column], + ); + const [initialFilterCount] = useState(currentFilters.length); + const visibleFilters = findVisibleFilters(currentFilters, initialFilterCount); + + return ( + <DelayGroup> + {visibleFilters.map((filter, filterIndex) => ( + <TabPanelFilterItem + key={filterIndex} + query={query} + columnItem={columnItem} + filter={filter} + isSearching={isSearching} + onChange={onChange} + onInput={onInput} + /> + ))} + </DelayGroup> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItemList.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItemList.tsx new file mode 100644 index 00000000000..8f81a6f3f64 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/TabPanelColumnItemList.tsx @@ -0,0 +1,41 @@ +import { useMemo } from "react"; + +import type * as Lib from "metabase-lib"; + +import type { ColumnItem } from "../types"; + +import { TabPanelColumnItem } from "./TabPanelColumnItem"; +import { sortColumns } from "./sorting"; + +export interface TabPanelColumnItemListProps { + query: Lib.Query; + columnItems: ColumnItem[]; + isSearching: boolean; + onChange: (newQuery: Lib.Query) => void; + onInput: () => void; +} + +export const TabPanelColumnItemList = ({ + query, + columnItems, + isSearching, + onChange, + onInput, +}: TabPanelColumnItemListProps) => { + const sortedItems = useMemo(() => sortColumns(columnItems), [columnItems]); + + return ( + <> + {sortedItems.map((columnItem, columnIndex) => ( + <TabPanelColumnItem + key={columnIndex} + query={query} + columnItem={columnItem} + isSearching={isSearching} + onChange={onChange} + onInput={onInput} + /> + ))} + </> + ); +}; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/columns.ts b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/columns.ts new file mode 100644 index 00000000000..f216972f651 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/columns.ts @@ -0,0 +1,22 @@ +import * as Lib from "metabase-lib"; + +export function findColumnFilters( + query: Lib.Query, + stageIndex: number, + column: Lib.ColumnMetadata, +): Lib.FilterClause[] { + const filters = Lib.filters(query, stageIndex); + const { filterPositions } = Lib.displayInfo(query, stageIndex, column); + return filterPositions != null + ? filterPositions.map(index => filters[index]) + : []; +} + +export function findVisibleFilters( + filters: Lib.FilterClause[], + initialFilterCount: number, +): (Lib.FilterClause | undefined)[] { + return Array(Math.max(filters.length, initialFilterCount, 1)) + .fill(undefined) + .map((_, i) => filters[i]); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/index.ts b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/index.ts new file mode 100644 index 00000000000..736e416921f --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/index.ts @@ -0,0 +1 @@ +export * from "./TabPanelColumnItemList"; diff --git a/frontend/src/metabase/querying/components/FilterModal/utils/sorting.ts b/frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/sorting.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/utils/sorting.ts rename to frontend/src/metabase/querying/components/FilterContent/TabPanelColumn/sorting.ts diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelFilterItem.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelFilterItem.tsx new file mode 100644 index 00000000000..3eef087a53a --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelFilterItem.tsx @@ -0,0 +1,50 @@ +import * as Lib from "metabase-lib"; + +import { ColumnFilterSection } from "../ColumnFilterSection"; +import type { ColumnItem } from "../types"; + +import { TabPanelItem } from "./TabPanelItem.styled"; + +export interface TabPanelFilterItemProps { + query: Lib.Query; + columnItem: ColumnItem; + filter: Lib.FilterClause | undefined; + isSearching: boolean; + onChange: (newQuery: Lib.Query) => void; + onInput: () => void; +} + +export function TabPanelFilterItem({ + query, + columnItem, + filter, + isSearching, + onChange, + onInput, +}: TabPanelFilterItemProps) { + const { column, displayName, stageIndex } = columnItem; + + const handleChange = (newFilter: Lib.ExpressionClause | undefined) => { + if (filter && newFilter) { + onChange(Lib.replaceClause(query, stageIndex, filter, newFilter)); + } else if (newFilter) { + onChange(Lib.filter(query, stageIndex, newFilter)); + } else if (filter) { + onChange(Lib.removeClause(query, stageIndex, filter)); + } + }; + + return ( + <TabPanelItem component="li" data-testid={`filter-column-${displayName}`}> + <ColumnFilterSection + query={query} + stageIndex={stageIndex} + column={column} + filter={filter} + isSearching={isSearching} + onChange={handleChange} + onInput={onInput} + /> + </TabPanelItem> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelItem.styled.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelItem.styled.tsx new file mode 100644 index 00000000000..e22be8594db --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelItem.styled.tsx @@ -0,0 +1,22 @@ +import styled from "@emotion/styled"; + +import { Box, type BoxProps } from "metabase/ui"; + +interface ColumnItemRootProps extends BoxProps { + component?: string; +} + +export const TabPanelItem = styled(Box)<ColumnItemRootProps>` + border-bottom: 1px solid var(--mb-color-border); + padding: 1rem 2rem; + padding-left: 0; + + &:last-of-type { + border-bottom: none; + } + + &:hover, + :focus-within { + background-color: var(--mb-color-bg-light); + } +`; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelSegmentItem.tsx b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelSegmentItem.tsx new file mode 100644 index 00000000000..12033aa8d05 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/TabPanelSegmentItem.tsx @@ -0,0 +1,38 @@ +import type * as Lib from "metabase-lib"; + +import { SegmentFilterEditor } from "../SegmentFilterEditor"; +import type { SegmentItem } from "../types"; + +import { TabPanelItem } from "./TabPanelItem.styled"; +import { addSegmentFilters, removeSegmentFilters } from "./segments"; + +export interface TabPanelSegmentItemProps { + query: Lib.Query; + segmentItems: SegmentItem[]; + onChange: (newQuery: Lib.Query) => void; +} + +export function TabPanelSegmentItem({ + query, + segmentItems, + onChange, +}: TabPanelSegmentItemProps) { + const handleChange = (newSegmentItems: SegmentItem[]) => { + const newQuery = removeSegmentFilters(query, segmentItems); + onChange(addSegmentFilters(newQuery, newSegmentItems)); + }; + + return ( + <TabPanelItem + component="li" + px="2rem" + py="1rem" + data-testid="filter-column-segments" + > + <SegmentFilterEditor + segmentItems={segmentItems} + onChange={handleChange} + /> + </TabPanelItem> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/index.ts b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/index.ts new file mode 100644 index 00000000000..117b2359265 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/index.ts @@ -0,0 +1,2 @@ +export * from "./TabPanelFilterItem"; +export * from "./TabPanelSegmentItem"; diff --git a/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/segments.ts b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/segments.ts new file mode 100644 index 00000000000..a3231f9bd2d --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/TabPanelItem/segments.ts @@ -0,0 +1,32 @@ +import * as Lib from "metabase-lib"; + +import type { SegmentItem } from "../types"; + +export function addSegmentFilters( + query: Lib.Query, + segmentItems: SegmentItem[], +) { + return segmentItems.reduce((query, { segment, stageIndex }) => { + return Lib.filter(query, stageIndex, segment); + }, query); +} + +export function removeSegmentFilters( + query: Lib.Query, + segmentItems: SegmentItem[], +) { + const filterGroups = segmentItems.map(({ stageIndex, filterPositions }) => { + const filters = Lib.filters(query, stageIndex); + return { + filters: filterPositions.map(filterPosition => filters[filterPosition]), + stageIndex, + }; + }); + + return filterGroups.reduce((query, { filters, stageIndex }) => { + return filters.reduce( + (newQuery, filter) => Lib.removeClause(newQuery, stageIndex, filter), + query, + ); + }, query); +} diff --git a/frontend/src/metabase/querying/components/FilterModal/TimeFilterEditor/TimeFilterEditor.tsx b/frontend/src/metabase/querying/components/FilterContent/TimeFilterEditor/TimeFilterEditor.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/TimeFilterEditor/TimeFilterEditor.tsx rename to frontend/src/metabase/querying/components/FilterContent/TimeFilterEditor/TimeFilterEditor.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/TimeFilterEditor/TimeFilterEditor.unit.spec.tsx b/frontend/src/metabase/querying/components/FilterContent/TimeFilterEditor/TimeFilterEditor.unit.spec.tsx similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/TimeFilterEditor/TimeFilterEditor.unit.spec.tsx rename to frontend/src/metabase/querying/components/FilterContent/TimeFilterEditor/TimeFilterEditor.unit.spec.tsx diff --git a/frontend/src/metabase/querying/components/FilterModal/TimeFilterEditor/index.ts b/frontend/src/metabase/querying/components/FilterContent/TimeFilterEditor/index.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/TimeFilterEditor/index.ts rename to frontend/src/metabase/querying/components/FilterContent/TimeFilterEditor/index.ts diff --git a/frontend/src/metabase/querying/components/FilterContent/index.ts b/frontend/src/metabase/querying/components/FilterContent/index.ts new file mode 100644 index 00000000000..1fb69f349bc --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterContent/index.ts @@ -0,0 +1,3 @@ +export * from "./TabContent"; +export * from "./FilterSearchInput"; +export * from "./types"; diff --git a/frontend/src/metabase/querying/components/FilterModal/types.ts b/frontend/src/metabase/querying/components/FilterContent/types.ts similarity index 100% rename from frontend/src/metabase/querying/components/FilterModal/types.ts rename to frontend/src/metabase/querying/components/FilterContent/types.ts diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterEmptyState.tsx b/frontend/src/metabase/querying/components/FilterModal/FilterEmptyState.tsx new file mode 100644 index 00000000000..1ee23e10f84 --- /dev/null +++ b/frontend/src/metabase/querying/components/FilterModal/FilterEmptyState.tsx @@ -0,0 +1,12 @@ +import { t } from "ttag"; + +import { Icon, Stack, Text } from "metabase/ui"; + +export function FilterEmptyState() { + return ( + <Stack c="text-light" h="100%" justify="center" align="center"> + <Icon name="search" size={40} /> + <Text c="text-medium" mt="lg" fw="bold">{t`Didn't find anything`}</Text> + </Stack> + ); +} diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterModal.styled.tsx b/frontend/src/metabase/querying/components/FilterModal/FilterModal.styled.tsx index e9587fcd08f..f0f4beb866b 100644 --- a/frontend/src/metabase/querying/components/FilterModal/FilterModal.styled.tsx +++ b/frontend/src/metabase/querying/components/FilterModal/FilterModal.styled.tsx @@ -1,31 +1,7 @@ import styled from "@emotion/styled"; import { breakpointMaxSmall } from "metabase/styled-components/theme"; -import type { BoxProps } from "metabase/ui"; -import { Box, Flex, Modal, Tabs } from "metabase/ui"; - -export const TabPanelRoot = styled(Tabs.Panel)` - overflow-y: auto; -`; - -interface ColumnItemRootProps extends BoxProps { - component?: string; -} - -export const TabPanelItem = styled(Box)<ColumnItemRootProps>` - border-bottom: 1px solid var(--mb-color-border); - padding: 1rem 2rem; - padding-left: 0; - - &:last-of-type { - border-bottom: none; - } - - &:hover, - :focus-within { - background-color: var(--mb-color-bg-light); - } -`; +import { Flex, Modal } from "metabase/ui"; export const ModalHeader = styled(Modal.Header)` border-bottom: 1px solid var(--mb-color-border); @@ -42,8 +18,3 @@ export const ModalBody = styled(Modal.Body)` export const ModalFooter = styled(Flex)` border-top: 1px solid var(--mb-color-border); `; - -export const TabsListSidebar = styled(Tabs.List)` - overflow-y: auto; - flex-wrap: nowrap; -`; diff --git a/frontend/src/metabase/querying/components/FilterModal/FilterModal.tsx b/frontend/src/metabase/querying/components/FilterModal/FilterModal.tsx index eb754776972..645606fb07c 100644 --- a/frontend/src/metabase/querying/components/FilterModal/FilterModal.tsx +++ b/frontend/src/metabase/querying/components/FilterModal/FilterModal.tsx @@ -2,47 +2,25 @@ import { useMemo, useState } from "react"; import { t } from "ttag"; import { - Button, - Flex, - Modal, - Stack, - Tabs, - Text, - Icon, - DelayGroup, -} from "metabase/ui"; + FilterSearchInput, + TabContent, +} from "metabase/querying/components/FilterContent"; +import { Button, Modal } from "metabase/ui"; import * as Lib from "metabase-lib"; -import { ColumnFilterSection } from "./ColumnFilterSection"; -import { - TabPanelItem, - ModalBody, - ModalFooter, - ModalHeader, - TabPanelRoot, - TabsListSidebar, -} from "./FilterModal.styled"; -import { FilterSearchInput } from "./FilterSearchInput"; -import { SegmentFilterEditor } from "./SegmentFilterEditor"; +import { FilterEmptyState } from "./FilterEmptyState"; +import { ModalBody, ModalFooter, ModalHeader } from "./FilterModal.styled"; import { SEARCH_KEY } from "./constants"; -import type { ColumnItem, GroupItem, SegmentItem } from "./types"; import { - addSegmentFilters, appendStageIfAggregated, - findColumnFilters, - findVisibleFilters, getGroupItems, - getModalTitle, - getModalWidth, hasFilters, - isSearchActive, removeFilters, - removeSegmentFilters, - searchGroupItems, - sortColumns, -} from "./utils"; +} from "./utils/filters"; +import { getModalTitle, getModalWidth } from "./utils/modal"; +import { isSearchActive, searchGroupItems } from "./utils/search"; -interface FilterModalProps { +export interface FilterModalProps { query: Lib.Query; onSubmit: (newQuery: Lib.Query) => void; onClose: () => void; @@ -118,7 +96,7 @@ export function FilterModal({ onTabChange={setTab} /> ) : ( - <SearchEmptyState /> + <FilterEmptyState /> )} </ModalBody> <ModalFooter p="md" direction="row" justify="space-between"> @@ -143,260 +121,3 @@ export function FilterModal({ </Modal.Root> ); } - -interface TabContentProps { - query: Lib.Query; - groupItems: GroupItem[]; - tab: string | null; - version: number; - isSearching: boolean; - onChange: (query: Lib.Query) => void; - onInput: () => void; - onTabChange: (tab: string | null) => void; -} - -function TabContent({ - query, - groupItems, - tab, - version, - isSearching, - onChange, - onInput, - onTabChange, -}: TabContentProps) { - return ( - <Tabs value={tab} onTabChange={onTabChange} orientation="vertical" h="100%"> - <Flex direction="row" w="100%"> - {groupItems.length > 1 && <TabList groupItems={groupItems} />} - {groupItems.map(groupItem => ( - <TabPanel - key={`${groupItem.key}:${version}`} - query={query} - groupItem={groupItem} - isSearching={isSearching} - onChange={onChange} - onInput={onInput} - /> - ))} - </Flex> - </Tabs> - ); -} - -function SearchEmptyState() { - return ( - <Stack c="text-light" h="100%" justify="center" align="center"> - <Icon name="search" size={40} /> - <Text c="text-medium" mt="lg" fw="bold">{t`Didn't find anything`}</Text> - </Stack> - ); -} - -interface TabListProps { - groupItems: GroupItem[]; -} - -function TabList({ groupItems }: TabListProps) { - return ( - <TabsListSidebar w="25%" pt="sm" pl="md"> - {groupItems.map(groupItem => ( - <Tabs.Tab - key={groupItem.key} - value={groupItem.key} - aria-label={groupItem.displayName} - icon={<Icon name={groupItem.icon} />} - > - {groupItem.displayName} - </Tabs.Tab> - ))} - </TabsListSidebar> - ); -} - -interface TabPanelProps { - query: Lib.Query; - groupItem: GroupItem; - isSearching: boolean; - onChange: (newQuery: Lib.Query) => void; - onInput: () => void; -} - -function TabPanel({ - query, - groupItem, - isSearching, - onChange, - onInput, -}: TabPanelProps) { - return ( - <TabPanelRoot value={groupItem.key}> - <ul> - {groupItem.segmentItems.length > 0 && ( - <TabPanelSegmentItem - query={query} - segmentItems={groupItem.segmentItems} - onChange={onChange} - /> - )} - {groupItem.columnItems.length > 0 && ( - <TabPanelColumnItemList - query={query} - columnItems={groupItem.columnItems} - isSearching={isSearching} - onChange={onChange} - onInput={onInput} - /> - )} - </ul> - </TabPanelRoot> - ); -} - -interface TabPanelColumnItemListProps { - query: Lib.Query; - columnItems: ColumnItem[]; - isSearching: boolean; - onChange: (newQuery: Lib.Query) => void; - onInput: () => void; -} - -const TabPanelColumnItemList = ({ - query, - columnItems, - isSearching, - onChange, - onInput, -}: TabPanelColumnItemListProps) => { - const sortedItems = useMemo(() => sortColumns(columnItems), [columnItems]); - - return ( - <> - {sortedItems.map((columnItem, columnIndex) => ( - <TabPanelColumnItem - key={columnIndex} - query={query} - columnItem={columnItem} - isSearching={isSearching} - onChange={onChange} - onInput={onInput} - /> - ))} - </> - ); -}; - -interface TabPanelColumnItemProps { - query: Lib.Query; - columnItem: ColumnItem; - isSearching: boolean; - onChange: (newQuery: Lib.Query) => void; - onInput: () => void; -} - -function TabPanelColumnItem({ - query, - columnItem, - isSearching, - onChange, - onInput, -}: TabPanelColumnItemProps) { - const { column, stageIndex } = columnItem; - const currentFilters = useMemo( - () => findColumnFilters(query, stageIndex, column), - [query, stageIndex, column], - ); - const [initialFilterCount] = useState(currentFilters.length); - const visibleFilters = findVisibleFilters(currentFilters, initialFilterCount); - - return ( - <DelayGroup> - {visibleFilters.map((filter, filterIndex) => ( - <TabPanelFilterItem - key={filterIndex} - query={query} - columnItem={columnItem} - filter={filter} - isSearching={isSearching} - onChange={onChange} - onInput={onInput} - /> - ))} - </DelayGroup> - ); -} - -interface TabPanelFilterItemProps { - query: Lib.Query; - columnItem: ColumnItem; - filter: Lib.FilterClause | undefined; - isSearching: boolean; - onChange: (newQuery: Lib.Query) => void; - onInput: () => void; -} - -function TabPanelFilterItem({ - query, - columnItem, - filter, - isSearching, - onChange, - onInput, -}: TabPanelFilterItemProps) { - const { column, displayName, stageIndex } = columnItem; - - const handleChange = (newFilter: Lib.ExpressionClause | undefined) => { - if (filter && newFilter) { - onChange(Lib.replaceClause(query, stageIndex, filter, newFilter)); - } else if (newFilter) { - onChange(Lib.filter(query, stageIndex, newFilter)); - } else if (filter) { - onChange(Lib.removeClause(query, stageIndex, filter)); - } - }; - - return ( - <TabPanelItem component="li" data-testid={`filter-column-${displayName}`}> - <ColumnFilterSection - query={query} - stageIndex={stageIndex} - column={column} - filter={filter} - isSearching={isSearching} - onChange={handleChange} - onInput={onInput} - /> - </TabPanelItem> - ); -} - -interface TabPanelSegmentItemProps { - query: Lib.Query; - segmentItems: SegmentItem[]; - onChange: (newQuery: Lib.Query) => void; -} - -function TabPanelSegmentItem({ - query, - segmentItems, - onChange, -}: TabPanelSegmentItemProps) { - const handleChange = (newSegmentItems: SegmentItem[]) => { - const newQuery = removeSegmentFilters(query, segmentItems); - onChange(addSegmentFilters(newQuery, newSegmentItems)); - }; - - return ( - <TabPanelItem - component="li" - px="2rem" - py="1rem" - data-testid="filter-column-segments" - > - <SegmentFilterEditor - segmentItems={segmentItems} - onChange={handleChange} - /> - </TabPanelItem> - ); -} diff --git a/frontend/src/metabase/querying/components/FilterModal/utils/filters.ts b/frontend/src/metabase/querying/components/FilterModal/utils/filters.ts index a2b7002415f..04009d23a8d 100644 --- a/frontend/src/metabase/querying/components/FilterModal/utils/filters.ts +++ b/frontend/src/metabase/querying/components/FilterModal/utils/filters.ts @@ -4,10 +4,9 @@ import { getColumnGroupIcon, getColumnGroupName, } from "metabase/common/utils/column-groups"; +import type { GroupItem } from "metabase/querying/components/FilterContent"; import * as Lib from "metabase-lib"; -import type { GroupItem, SegmentItem } from "../types"; - export function appendStageIfAggregated(query: Lib.Query) { const aggregations = Lib.aggregations(query, -1); const breakouts = Lib.breakouts(query, -1); @@ -75,53 +74,3 @@ export function removeFilters(query: Lib.Query) { query, ); } - -export function addSegmentFilters( - query: Lib.Query, - segmentItems: SegmentItem[], -) { - return segmentItems.reduce((query, { segment, stageIndex }) => { - return Lib.filter(query, stageIndex, segment); - }, query); -} - -export function removeSegmentFilters( - query: Lib.Query, - segmentItems: SegmentItem[], -) { - const filterGroups = segmentItems.map(({ stageIndex, filterPositions }) => { - const filters = Lib.filters(query, stageIndex); - return { - filters: filterPositions.map(filterPosition => filters[filterPosition]), - stageIndex, - }; - }); - - return filterGroups.reduce((query, { filters, stageIndex }) => { - return filters.reduce( - (newQuery, filter) => Lib.removeClause(newQuery, stageIndex, filter), - query, - ); - }, query); -} - -export function findColumnFilters( - query: Lib.Query, - stageIndex: number, - column: Lib.ColumnMetadata, -): Lib.FilterClause[] { - const filters = Lib.filters(query, stageIndex); - const { filterPositions } = Lib.displayInfo(query, stageIndex, column); - return filterPositions != null - ? filterPositions.map(index => filters[index]) - : []; -} - -export function findVisibleFilters( - filters: Lib.FilterClause[], - initialFilterCount: number, -): (Lib.FilterClause | undefined)[] { - return Array(Math.max(filters.length, initialFilterCount, 1)) - .fill(undefined) - .map((_, i) => filters[i]); -} diff --git a/frontend/src/metabase/querying/components/FilterModal/utils/index.ts b/frontend/src/metabase/querying/components/FilterModal/utils/index.ts deleted file mode 100644 index 14db48b2385..00000000000 --- a/frontend/src/metabase/querying/components/FilterModal/utils/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./filters"; -export * from "./modal"; -export * from "./search"; -export * from "./sorting"; diff --git a/frontend/src/metabase/querying/components/FilterModal/utils/modal.ts b/frontend/src/metabase/querying/components/FilterModal/utils/modal.ts index 000547da494..25aa3d2f5e1 100644 --- a/frontend/src/metabase/querying/components/FilterModal/utils/modal.ts +++ b/frontend/src/metabase/querying/components/FilterModal/utils/modal.ts @@ -1,6 +1,6 @@ import { t } from "ttag"; -import type { GroupItem } from "../types"; +import type { GroupItem } from "metabase/querying/components/FilterContent"; export function getModalTitle(groupItems: GroupItem[]) { return groupItems.length === 1 diff --git a/frontend/src/metabase/querying/components/FilterModal/utils/search.ts b/frontend/src/metabase/querying/components/FilterModal/utils/search.ts index 62fe8b6b03c..0353fb9548c 100644 --- a/frontend/src/metabase/querying/components/FilterModal/utils/search.ts +++ b/frontend/src/metabase/querying/components/FilterModal/utils/search.ts @@ -1,7 +1,8 @@ import { t } from "ttag"; +import type { GroupItem } from "metabase/querying/components/FilterContent"; + import { SEARCH_KEY } from "../constants"; -import type { GroupItem } from "../types"; export function isSearchActive(searchText: string) { return searchText.length > 0; diff --git a/frontend/src/metabase/querying/index.ts b/frontend/src/metabase/querying/index.ts index 138176b2bae..7f4bbaa540c 100644 --- a/frontend/src/metabase/querying/index.ts +++ b/frontend/src/metabase/querying/index.ts @@ -5,3 +5,7 @@ export { FilterPicker, FilterPickerBody } from "./components/FilterPicker"; export { TemporalUnitPicker } from "./components/TemporalUnitPicker"; export { TimeseriesChrome } from "./components/TimeseriesChrome"; export { queryDrill } from "./utils/drills/query-drill"; +export { removeFilters } from "metabase/querying/components/FilterModal/utils/filters"; +export { hasFilters } from "metabase/querying/components/FilterModal/utils/filters"; +export { getGroupItems } from "metabase/querying/components/FilterModal/utils/filters"; +export { appendStageIfAggregated } from "metabase/querying/components/FilterModal/utils/filters"; -- GitLab