From d0dc311913b42c7cb42123b2aa7b7389d00461cd Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 1 Dec 2022 23:32:24 +0530 Subject: [PATCH 1/7] Create a reusable search hook --- packages/toolpad-app/src/theme.ts | 27 ++++++++++--- .../toolpad-app/src/toolpad/Apps/index.tsx | 16 +++++--- packages/toolpad-app/src/utils/useSearch.tsx | 40 +++++++++++++++++++ 3 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 packages/toolpad-app/src/utils/useSearch.tsx diff --git a/packages/toolpad-app/src/theme.ts b/packages/toolpad-app/src/theme.ts index dc8b53b498e..8e20e864150 100644 --- a/packages/toolpad-app/src/theme.ts +++ b/packages/toolpad-app/src/theme.ts @@ -712,18 +712,13 @@ export function getThemedComponents(theme: Theme): { components: Theme['componen defaultProps: { size: 'small', }, - styleOverrides: { - root: { - backgroundColor: - theme.palette.mode === 'dark' ? theme.palette.primaryDark[900] : '#fff', - }, - }, }, MuiToggleButton: { styleOverrides: { root: { textTransform: 'none', fontWeight: 500, + padding: theme.spacing(0.5), color: theme.palette.mode === 'dark' ? theme.palette.grey[300] : theme.palette.grey[700], borderColor: @@ -891,11 +886,31 @@ export function getThemedComponents(theme: Theme): { components: Theme['componen defaultProps: { margin: 'dense', }, + styleOverrides: { + root: { + fontSize: defaultTheme.typography.pxToRem(13), + '& .MuiInputBase-input': { + paddingTop: theme.spacing(0.7), + paddingBottom: theme.spacing(0.7), + }, + '& .MuiSvgIcon-root': { + fontSize: defaultTheme.typography.pxToRem(18), + color: + theme.palette.mode === 'dark' ? theme.palette.grey[300] : theme.palette.grey[500], + marginRight: theme.spacing(0.2), + }, + }, + }, }, MuiInputLabel: { defaultProps: { margin: 'dense', }, + styleOverrides: { + root: { + fontSize: defaultTheme.typography.pxToRem(13), + }, + }, }, MuiListItem: { defaultProps: { diff --git a/packages/toolpad-app/src/toolpad/Apps/index.tsx b/packages/toolpad-app/src/toolpad/Apps/index.tsx index b2cd60eefd0..235feacb898 100644 --- a/packages/toolpad-app/src/toolpad/Apps/index.tsx +++ b/packages/toolpad-app/src/toolpad/Apps/index.tsx @@ -38,6 +38,7 @@ import DialogForm from '../../components/DialogForm'; import type { Deployment } from '../../../prisma/generated/client'; import ToolpadHomeShell from '../ToolpadHomeShell'; import getReadableDuration from '../../utils/readableDuration'; +import useSearch from '../../utils/useSearch'; import type { AppMeta } from '../../server/data'; import useLocalStorageState from '../../utils/useLocalStorageState'; import ErrorAlert from '../AppEditor/PageEditor/ErrorAlert'; @@ -619,17 +620,22 @@ export default function Home() { const AppsView = viewMode === 'list' ? AppsListView : AppsGridView; + const [AppsSearchField, filteredApps] = useSearch(apps, 'Search apps'); + return config.isDemo ? ( ) : ( - + Apps - + {AppsSearchField} + - + - + @@ -657,7 +663,7 @@ export default function Home() { ) : ( (elements: T[], placeholder?: string): [JSX.Element, T[]] { + const [searchText, setSearchText] = React.useState(''); + + const handleSearchInput = React.useCallback((event: React.ChangeEvent) => { + setSearchText(event.target.value); + }, []); + + const filteredElements = React.useMemo(() => { + return elements.filter((elem: any) => + elem.name.toLowerCase().includes(searchText.toLowerCase()), + ); + }, [elements, searchText]); + + return [ + , + }} + placeholder={placeholder ?? 'Search'} + value={searchText} + onChange={handleSearchInput} + />, + filteredElements, + ]; +} + +export default useSearch; From 7542f5b9bbb05d823325d99147bc98f7aad74b88 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 1 Dec 2022 23:52:06 +0530 Subject: [PATCH 2/7] Small style tweaks --- packages/toolpad-app/src/theme.ts | 2 +- packages/toolpad-app/src/toolpad/Apps/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/toolpad-app/src/theme.ts b/packages/toolpad-app/src/theme.ts index 8e20e864150..e3b748760ab 100644 --- a/packages/toolpad-app/src/theme.ts +++ b/packages/toolpad-app/src/theme.ts @@ -896,7 +896,7 @@ export function getThemedComponents(theme: Theme): { components: Theme['componen '& .MuiSvgIcon-root': { fontSize: defaultTheme.typography.pxToRem(18), color: - theme.palette.mode === 'dark' ? theme.palette.grey[300] : theme.palette.grey[500], + theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], marginRight: theme.spacing(0.2), }, }, diff --git a/packages/toolpad-app/src/toolpad/Apps/index.tsx b/packages/toolpad-app/src/toolpad/Apps/index.tsx index 235feacb898..b5786eb7761 100644 --- a/packages/toolpad-app/src/toolpad/Apps/index.tsx +++ b/packages/toolpad-app/src/toolpad/Apps/index.tsx @@ -627,7 +627,7 @@ export default function Home() { ) : ( - + Apps From 7073c118fb60f6d668a9c5ee624b61f917e6169e Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Tue, 6 Dec 2022 12:48:07 +0530 Subject: [PATCH 3/7] Fix: Reuse later, reserve space for scrollbar --- .../toolpad-app/src/toolpad/Apps/index.tsx | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/Apps/index.tsx b/packages/toolpad-app/src/toolpad/Apps/index.tsx index b5786eb7761..3ef0a0f541b 100644 --- a/packages/toolpad-app/src/toolpad/Apps/index.tsx +++ b/packages/toolpad-app/src/toolpad/Apps/index.tsx @@ -31,6 +31,7 @@ import { import LoadingButton from '@mui/lab/LoadingButton'; import ViewListIcon from '@mui/icons-material/ViewList'; import GridViewIcon from '@mui/icons-material/GridView'; +import Search from '@mui/icons-material/SearchOutlined'; import invariant from 'invariant'; import { Link } from 'react-router-dom'; import client from '../../api'; @@ -38,7 +39,6 @@ import DialogForm from '../../components/DialogForm'; import type { Deployment } from '../../../prisma/generated/client'; import ToolpadHomeShell from '../ToolpadHomeShell'; import getReadableDuration from '../../utils/readableDuration'; -import useSearch from '../../utils/useSearch'; import type { AppMeta } from '../../server/data'; import useLocalStorageState from '../../utils/useLocalStorageState'; import ErrorAlert from '../AppEditor/PageEditor/ErrorAlert'; @@ -620,7 +620,17 @@ export default function Home() { const AppsView = viewMode === 'list' ? AppsListView : AppsGridView; - const [AppsSearchField, filteredApps] = useSearch(apps, 'Search apps'); + const [searchText, setSearchText] = React.useState(''); + + const handleSearchInput = React.useCallback((event: React.ChangeEvent) => { + setSearchText(event.target.value); + }, []); + + const filteredApps = React.useMemo(() => { + return apps.filter((element: any) => + element.name.toLowerCase().includes(searchText.toLowerCase()), + ); + }, [apps, searchText]); return config.isDemo ? ( @@ -632,7 +642,16 @@ export default function Home() { Apps - {AppsSearchField} + , + }} + placeholder={'Search apps'} + value={searchText} + onChange={handleSearchInput} + /> @@ -661,7 +680,7 @@ export default function Home() { {error ? ( ) : ( - + Date: Tue, 13 Dec 2022 18:38:54 +0530 Subject: [PATCH 4/7] Review: Only override text field --- packages/toolpad-app/src/theme.ts | 38 +++++++++++++++---------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/packages/toolpad-app/src/theme.ts b/packages/toolpad-app/src/theme.ts index e3b748760ab..3d8dd6c6850 100644 --- a/packages/toolpad-app/src/theme.ts +++ b/packages/toolpad-app/src/theme.ts @@ -828,6 +828,24 @@ export function getThemedComponents(theme: Theme): { components: Theme['componen size: 'small', margin: 'dense', }, + styleOverrides: { + root: { + fontSize: defaultTheme.typography.pxToRem(13), + '& .MuiInputBase-input': { + paddingTop: theme.spacing(0.6), + paddingBottom: theme.spacing(0.6), + }, + '& .MuiInputLabel-root': { + fontSize: defaultTheme.typography.pxToRem(13), + }, + '& .MuiSvgIcon-root': { + fontSize: defaultTheme.typography.pxToRem(18), + color: + theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], + marginRight: theme.spacing(0.2), + }, + }, + }, }, MuiCheckbox: { defaultProps: { @@ -886,31 +904,11 @@ export function getThemedComponents(theme: Theme): { components: Theme['componen defaultProps: { margin: 'dense', }, - styleOverrides: { - root: { - fontSize: defaultTheme.typography.pxToRem(13), - '& .MuiInputBase-input': { - paddingTop: theme.spacing(0.7), - paddingBottom: theme.spacing(0.7), - }, - '& .MuiSvgIcon-root': { - fontSize: defaultTheme.typography.pxToRem(18), - color: - theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], - marginRight: theme.spacing(0.2), - }, - }, - }, }, MuiInputLabel: { defaultProps: { margin: 'dense', }, - styleOverrides: { - root: { - fontSize: defaultTheme.typography.pxToRem(13), - }, - }, }, MuiListItem: { defaultProps: { From aa0c2ba9e04ddb89ef020aba086b6819e819065a Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Tue, 13 Dec 2022 19:09:40 +0530 Subject: [PATCH 5/7] Review: Remove unused hook, bring style overrides to component --- packages/toolpad-app/src/theme.ts | 18 --------- .../toolpad-app/src/toolpad/Apps/index.tsx | 16 +++++++- packages/toolpad-app/src/utils/useSearch.tsx | 40 ------------------- 3 files changed, 15 insertions(+), 59 deletions(-) delete mode 100644 packages/toolpad-app/src/utils/useSearch.tsx diff --git a/packages/toolpad-app/src/theme.ts b/packages/toolpad-app/src/theme.ts index 3d8dd6c6850..e8c530906d8 100644 --- a/packages/toolpad-app/src/theme.ts +++ b/packages/toolpad-app/src/theme.ts @@ -828,24 +828,6 @@ export function getThemedComponents(theme: Theme): { components: Theme['componen size: 'small', margin: 'dense', }, - styleOverrides: { - root: { - fontSize: defaultTheme.typography.pxToRem(13), - '& .MuiInputBase-input': { - paddingTop: theme.spacing(0.6), - paddingBottom: theme.spacing(0.6), - }, - '& .MuiInputLabel-root': { - fontSize: defaultTheme.typography.pxToRem(13), - }, - '& .MuiSvgIcon-root': { - fontSize: defaultTheme.typography.pxToRem(18), - color: - theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], - marginRight: theme.spacing(0.2), - }, - }, - }, }, MuiCheckbox: { defaultProps: { diff --git a/packages/toolpad-app/src/toolpad/Apps/index.tsx b/packages/toolpad-app/src/toolpad/Apps/index.tsx index c0e70a794ce..5d83591e3b3 100644 --- a/packages/toolpad-app/src/toolpad/Apps/index.tsx +++ b/packages/toolpad-app/src/toolpad/Apps/index.tsx @@ -643,7 +643,21 @@ export default function Home() { ({ + '& .MuiInputBase-root': { + fontSize: theme.typography.pxToRem(14), + }, + '& .MuiInputBase-input': { + paddingTop: theme.spacing(0.7), + paddingBottom: theme.spacing(0.7), + }, + '& .MuiSvgIcon-root': { + fontSize: theme.typography.pxToRem(16), + color: + theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], + marginRight: theme.spacing(0.6), + }, + })} key={'search'} InputProps={{ startAdornment: , diff --git a/packages/toolpad-app/src/utils/useSearch.tsx b/packages/toolpad-app/src/utils/useSearch.tsx deleted file mode 100644 index 800c1c70b1c..00000000000 --- a/packages/toolpad-app/src/utils/useSearch.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import { TextField } from '@mui/material'; -import Search from '@mui/icons-material/SearchOutlined'; - -/** - * Creates a search field. - * @param elements The elements to search through. - * @param {string=} placeholder The value of the placeholder text - * @returns The search field and the filtered elements - */ - -function useSearch(elements: T[], placeholder?: string): [JSX.Element, T[]] { - const [searchText, setSearchText] = React.useState(''); - - const handleSearchInput = React.useCallback((event: React.ChangeEvent) => { - setSearchText(event.target.value); - }, []); - - const filteredElements = React.useMemo(() => { - return elements.filter((elem: any) => - elem.name.toLowerCase().includes(searchText.toLowerCase()), - ); - }, [elements, searchText]); - - return [ - , - }} - placeholder={placeholder ?? 'Search'} - value={searchText} - onChange={handleSearchInput} - />, - filteredElements, - ]; -} - -export default useSearch; From 14fa9593da4534a6c3512a6f90dbeb83d4ccd661 Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 5 Jan 2023 10:32:25 +0530 Subject: [PATCH 6/7] Fix: Review Pedro --- .../toolpad-app/src/toolpad/Apps/index.tsx | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/Apps/index.tsx b/packages/toolpad-app/src/toolpad/Apps/index.tsx index 088518c6872..97706b109ac 100644 --- a/packages/toolpad-app/src/toolpad/Apps/index.tsx +++ b/packages/toolpad-app/src/toolpad/Apps/index.tsx @@ -27,6 +27,7 @@ import { Typography, Alert, AlertTitle, + Theme, } from '@mui/material'; import LoadingButton from '@mui/lab/LoadingButton'; import ViewListIcon from '@mui/icons-material/ViewList'; @@ -695,6 +696,22 @@ function DemoPage() { ); } +const searchFieldStyleOverrides = (theme: Theme) => ({ + '& .MuiInputBase-root': { + fontSize: theme.typography.pxToRem(14), + }, + '& .MuiInputBase-input': { + paddingTop: theme.spacing(0.7), + paddingBottom: theme.spacing(0.7), + }, + '& .MuiSvgIcon-root': { + fontSize: theme.typography.pxToRem(16), + color: theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], + marginRight: theme.spacing(0.6), + marginTop: theme.spacing(0.2), + }, +}); + export default function Home() { const { data: apps = [], @@ -752,21 +769,7 @@ export default function Home() { ({ - '& .MuiInputBase-root': { - fontSize: theme.typography.pxToRem(14), - }, - '& .MuiInputBase-input': { - paddingTop: theme.spacing(0.7), - paddingBottom: theme.spacing(0.7), - }, - '& .MuiSvgIcon-root': { - fontSize: theme.typography.pxToRem(16), - color: - theme.palette.mode === 'dark' ? theme.palette.grey[400] : theme.palette.grey[500], - marginRight: theme.spacing(0.6), - }, - })} + sx={searchFieldStyleOverrides} key={'search'} InputProps={{ startAdornment: , From 8b7ee6256dead887a85d8e8899f38fbbd4d4924f Mon Sep 17 00:00:00 2001 From: Bharat Kashyap Date: Thu, 5 Jan 2023 11:00:07 +0530 Subject: [PATCH 7/7] Test for app search --- test/integration/appSearch.spec.ts | 20 ++++++++++++++++++++ test/models/ToolpadHome.ts | 6 ++++++ 2 files changed, 26 insertions(+) create mode 100644 test/integration/appSearch.spec.ts diff --git a/test/integration/appSearch.spec.ts b/test/integration/appSearch.spec.ts new file mode 100644 index 00000000000..0725d3a4091 --- /dev/null +++ b/test/integration/appSearch.spec.ts @@ -0,0 +1,20 @@ +import { ToolpadHome } from '../models/ToolpadHome'; +import { test, expect } from '../playwright/test'; +import generateId from '../utils/generateId'; + +test('app search flow', async ({ page }) => { + const appName1 = `App ${generateId()}`; + const appName2 = `App ${generateId()}`; + + const homeModel = new ToolpadHome(page); + await homeModel.goto(); + await homeModel.createApplication({ name: appName1 }); + await homeModel.goto(); + await homeModel.createApplication({ name: appName2 }); + await homeModel.goto(); + + await homeModel.searchFor(appName1); + + await expect(homeModel.getAppRow(appName1)).toBeVisible(); + await expect(homeModel.getAppRow(appName2)).toBeHidden(); +}); diff --git a/test/models/ToolpadHome.ts b/test/models/ToolpadHome.ts index 8eef893e547..ba37777564d 100644 --- a/test/models/ToolpadHome.ts +++ b/test/models/ToolpadHome.ts @@ -110,4 +110,10 @@ export class ToolpadHome { return { id: idMatch[1] }; } + + async searchFor(name: string) { + const textField = this.page.getByPlaceholder('Search apps'); + await textField.focus(); + await textField.fill(name); + } }