From 12f9cd063f0222a542ca7b7dee77dc4c52c470cb Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Wed, 11 Jan 2023 15:06:52 +0200 Subject: [PATCH] Revert "Virtualize table and card lists in data picker (#27582)" (#27625) --- ...irtualizedList.tsx => VirtualizedList.jsx} | 18 ++---------- .../CardPicker/CardPicker.styled.tsx | 4 ++- .../DataPicker/CardPicker/CardPickerView.tsx | 22 ++++++--------- .../RawDataPicker/RawDataPicker.styled.tsx | 4 ++- .../RawDataPicker/RawDataPickerView.tsx | 21 ++++++-------- .../DataPicker/VirtualizedSelectList.tsx | 28 ------------------- .../tests/DataPicker-Common.unit.spec.ts | 6 ++-- .../tests/DataPicker-Models.unit.spec.ts | 3 +- .../tests/DataPicker-Questions.unit.spec.ts | 3 +- .../tests/DataPicker-RawData.unit.spec.ts | 4 +-- .../containers/DataPicker/tests/common.tsx | 15 ---------- 11 files changed, 33 insertions(+), 95 deletions(-) rename frontend/src/metabase/components/{VirtualizedList.tsx => VirtualizedList.jsx} (69%) delete mode 100644 frontend/src/metabase/containers/DataPicker/VirtualizedSelectList.tsx diff --git a/frontend/src/metabase/components/VirtualizedList.tsx b/frontend/src/metabase/components/VirtualizedList.jsx similarity index 69% rename from frontend/src/metabase/components/VirtualizedList.tsx rename to frontend/src/metabase/components/VirtualizedList.jsx index acd498d2a2e..7f8104e36f0 100644 --- a/frontend/src/metabase/components/VirtualizedList.tsx +++ b/frontend/src/metabase/components/VirtualizedList.jsx @@ -1,20 +1,8 @@ +/* eslint-disable react/prop-types */ import React from "react"; import { List, WindowScroller, AutoSizer } from "react-virtualized"; -export interface VirtualizedListProps<Item = unknown> - extends React.HTMLProps<HTMLUListElement> { - items: Item[]; - rowHeight: number; - renderItem: (props: { item: Item; index: number }) => React.ReactNode; - scrollElement?: HTMLElement | null; -} - -function VirtualizedList<Item>({ - items, - rowHeight, - renderItem, - scrollElement, -}: VirtualizedListProps<Item>) { +function VirtualizedList({ items, rowHeight, renderItem, scrollElement }) { const rowRenderer = React.useCallback( ({ index, key, style }) => ( <div key={key} style={style}> @@ -27,7 +15,7 @@ function VirtualizedList<Item>({ const renderScrollComponent = React.useCallback( ({ width }) => { return ( - <WindowScroller scrollElement={scrollElement || undefined}> + <WindowScroller scrollElement={scrollElement}> {({ height, isScrolling, scrollTop }) => ( <List autoHeight diff --git a/frontend/src/metabase/containers/DataPicker/CardPicker/CardPicker.styled.tsx b/frontend/src/metabase/containers/DataPicker/CardPicker/CardPicker.styled.tsx index 4c5897c86f1..5bb3ffb3db8 100644 --- a/frontend/src/metabase/containers/DataPicker/CardPicker/CardPicker.styled.tsx +++ b/frontend/src/metabase/containers/DataPicker/CardPicker/CardPicker.styled.tsx @@ -1,6 +1,8 @@ import styled from "@emotion/styled"; -export const ListContainer = styled.div` +import SelectList from "metabase/components/SelectList"; + +export const StyledSelectList = styled(SelectList)` width: 100%; padding-left: 1rem; `; diff --git a/frontend/src/metabase/containers/DataPicker/CardPicker/CardPickerView.tsx b/frontend/src/metabase/containers/DataPicker/CardPicker/CardPickerView.tsx index cb7a60925e7..b301fd7e472 100644 --- a/frontend/src/metabase/containers/DataPicker/CardPicker/CardPickerView.tsx +++ b/frontend/src/metabase/containers/DataPicker/CardPicker/CardPickerView.tsx @@ -1,6 +1,8 @@ import React, { useCallback, useMemo } from "react"; import _ from "underscore"; +import SelectList from "metabase/components/SelectList"; + import { canonicalCollectionId } from "metabase/collections/utils"; import type { ITreeNodeItem } from "metabase/components/tree/types"; @@ -11,10 +13,9 @@ import type { DataPickerSelectedItem, VirtualTable } from "../types"; import EmptyState from "../EmptyState"; import LoadingState from "../LoadingState"; -import VirtualizedSelectList from "../VirtualizedSelectList"; import PanePicker from "../PanePicker"; -import { ListContainer } from "./CardPicker.styled"; +import { StyledSelectList } from "./CardPicker.styled"; type TargetModel = "model" | "question"; @@ -54,7 +55,7 @@ function TableSelectListItem({ onSelect: (id: Table["id"]) => void; }) { return ( - <VirtualizedSelectList.Item + <SelectList.Item id={table.id} name={table.display_name} isSelected={isSelected} @@ -62,7 +63,7 @@ function TableSelectListItem({ onSelect={onSelect} > {table.display_name} - </VirtualizedSelectList.Item> + </SelectList.Item> ); } @@ -103,7 +104,7 @@ function CardPickerView({ ); const renderVirtualTable = useCallback( - ({ item: table }: { item: VirtualTable }) => ( + (table: VirtualTable) => ( <TableSelectListItem key={table.id} table={table} @@ -129,14 +130,9 @@ function CardPickerView({ ) : isEmpty ? ( <EmptyState /> ) : ( - <ListContainer> - {Array.isArray(virtualTables) && ( - <VirtualizedSelectList<VirtualTable> - items={virtualTables} - renderItem={renderVirtualTable} - /> - )} - </ListContainer> + <StyledSelectList> + {virtualTables?.map?.(renderVirtualTable)} + </StyledSelectList> )} </PanePicker> ); diff --git a/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPicker.styled.tsx b/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPicker.styled.tsx index fb0f876d871..98464679d16 100644 --- a/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPicker.styled.tsx +++ b/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPicker.styled.tsx @@ -1,6 +1,8 @@ import styled from "@emotion/styled"; -export const ListContainer = styled.div` +import SelectList from "metabase/components/SelectList"; + +export const StyledSelectList = styled(SelectList)` width: 100%; padding: 0 1rem; `; diff --git a/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPickerView.tsx b/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPickerView.tsx index c741e5d92de..cd741fc35e5 100644 --- a/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPickerView.tsx +++ b/frontend/src/metabase/containers/DataPicker/RawDataPicker/RawDataPickerView.tsx @@ -1,6 +1,8 @@ import React, { useCallback, useMemo } from "react"; import _ from "underscore"; +import SelectList from "metabase/components/SelectList"; + import type { ITreeNodeItem } from "metabase/components/tree/types"; import type Database from "metabase-lib/metadata/Database"; @@ -11,9 +13,8 @@ import type { DataPickerSelectedItem } from "../types"; import EmptyState from "../EmptyState"; import LoadingState from "../LoadingState"; -import VirtualizedSelectList from "../VirtualizedSelectList"; import PanePicker from "../PanePicker"; -import { ListContainer } from "./RawDataPicker.styled"; +import { StyledSelectList } from "./RawDataPicker.styled"; interface RawDataPickerViewProps { databases: Database[]; @@ -60,7 +61,7 @@ function TableSelectListItem({ }) { const name = table.displayName(); return ( - <VirtualizedSelectList.Item + <SelectList.Item id={table.id} name={name} isSelected={isSelected} @@ -68,7 +69,7 @@ function TableSelectListItem({ onSelect={onSelect} > {name} - </VirtualizedSelectList.Item> + </SelectList.Item> ); } @@ -134,8 +135,9 @@ function RawDataPickerView({ ); const renderTable = useCallback( - ({ item: table }: { item: Table }) => ( + (table: Table) => ( <TableSelectListItem + key={table.id} table={table} isSelected={selectedTableIds.includes(table.id)} onSelect={onSelectedTable} @@ -160,14 +162,7 @@ function RawDataPickerView({ ) : isEmpty ? ( <EmptyState /> ) : ( - <ListContainer> - {Array.isArray(tables) && ( - <VirtualizedSelectList<Table> - items={tables} - renderItem={renderTable} - /> - )} - </ListContainer> + <StyledSelectList>{tables?.map?.(renderTable)}</StyledSelectList> )} </PanePicker> ); diff --git a/frontend/src/metabase/containers/DataPicker/VirtualizedSelectList.tsx b/frontend/src/metabase/containers/DataPicker/VirtualizedSelectList.tsx deleted file mode 100644 index 7ad52248e1d..00000000000 --- a/frontend/src/metabase/containers/DataPicker/VirtualizedSelectList.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; - -import VirtualizedList, { - VirtualizedListProps, -} from "metabase/components/VirtualizedList"; -import SelectList from "metabase/components/SelectList"; - -const SELECT_LIST_ITEM_HEIGHT = 40; - -type VirtualizedSelectListProps<Item> = Omit< - VirtualizedListProps<Item>, - "rowHeight" | "role" ->; - -function VirtualizedSelectList<Item>(props: VirtualizedSelectListProps<Item>) { - return ( - <VirtualizedList<Item> - data-testid="select-list" - {...props} - role="menu" - rowHeight={SELECT_LIST_ITEM_HEIGHT} - /> - ); -} - -export default Object.assign(VirtualizedSelectList, { - Item: SelectList.Item, -}); diff --git a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Common.unit.spec.ts b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Common.unit.spec.ts index eb638ade81c..d2c6dc25d66 100644 --- a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Common.unit.spec.ts +++ b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Common.unit.spec.ts @@ -1,13 +1,13 @@ import nock from "nock"; -import { screen } from "__support__/ui"; +import { screen, waitFor } from "__support__/ui"; import { SAMPLE_DATABASE } from "__support__/sample_database_fixture"; -import { setup, setupVirtualizedLists } from "./common"; +import { setup } from "./common"; describe("DataPicker", () => { beforeAll(() => { - setupVirtualizedLists(); + window.HTMLElement.prototype.scrollIntoView = jest.fn(); }); afterEach(() => { diff --git a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Models.unit.spec.ts b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Models.unit.spec.ts index a1a7c36d4c1..44ac210af3e 100644 --- a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Models.unit.spec.ts +++ b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Models.unit.spec.ts @@ -13,7 +13,6 @@ import { import { setup, - setupVirtualizedLists, EMPTY_COLLECTION, SAMPLE_COLLECTION, SAMPLE_MODEL, @@ -28,7 +27,7 @@ const ROOT_COLLECTION_MODEL_VIRTUAL_SCHEMA_ID = getCollectionVirtualSchemaId( describe("DataPicker — picking models", () => { beforeAll(() => { - setupVirtualizedLists(); + window.HTMLElement.prototype.scrollIntoView = jest.fn(); }); afterEach(() => { diff --git a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Questions.unit.spec.ts b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Questions.unit.spec.ts index 5d38a0b09a8..320c707e4a1 100644 --- a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Questions.unit.spec.ts +++ b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-Questions.unit.spec.ts @@ -13,7 +13,6 @@ import { import { setup, - setupVirtualizedLists, EMPTY_COLLECTION, SAMPLE_COLLECTION, SAMPLE_QUESTION, @@ -26,7 +25,7 @@ const ROOT_COLLECTION_QUESTIONS_VIRTUAL_SCHEMA_ID = describe("DataPicker — picking questions", () => { beforeAll(() => { - setupVirtualizedLists(); + window.HTMLElement.prototype.scrollIntoView = jest.fn(); }); afterEach(() => { diff --git a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-RawData.unit.spec.ts b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-RawData.unit.spec.ts index d43bb01762c..f05e431e73e 100644 --- a/frontend/src/metabase/containers/DataPicker/tests/DataPicker-RawData.unit.spec.ts +++ b/frontend/src/metabase/containers/DataPicker/tests/DataPicker-RawData.unit.spec.ts @@ -10,11 +10,11 @@ import { import { generateSchemaId } from "metabase-lib/metadata/utils/schema"; -import { setup, setupVirtualizedLists } from "./common"; +import { setup } from "./common"; describe("DataPicker — picking raw data", () => { beforeAll(() => { - setupVirtualizedLists(); + window.HTMLElement.prototype.scrollIntoView = jest.fn(); }); afterEach(() => { diff --git a/frontend/src/metabase/containers/DataPicker/tests/common.tsx b/frontend/src/metabase/containers/DataPicker/tests/common.tsx index 3bb1fdb15c4..7846c37c9a9 100644 --- a/frontend/src/metabase/containers/DataPicker/tests/common.tsx +++ b/frontend/src/metabase/containers/DataPicker/tests/common.tsx @@ -111,21 +111,6 @@ interface SetupOpts { hasNestedQueriesEnabled?: boolean; } -// react-virtualized's AutoSizer uses offsetWidth and offsetHeight. -// Jest runs in JSDom which doesn't support measurements APIs. -export function setupVirtualizedLists() { - Object.defineProperty(HTMLElement.prototype, "offsetHeight", { - configurable: true, - value: 100, - }); - Object.defineProperty(HTMLElement.prototype, "offsetWidth", { - configurable: true, - value: 100, - }); - - window.HTMLElement.prototype.scrollIntoView = jest.fn(); -} - export async function setup({ initialValue = { tableIds: [] }, filters, -- GitLab