From bff8620448f9e9e6167920cbc57196f44b68a669 Mon Sep 17 00:00:00 2001 From: Oscar Hernandez Date: Mon, 8 Feb 2021 15:44:40 -0600 Subject: [PATCH] Scaffolder: Implement search --- .../ScaffolderPage/ScaffolderPage.tsx | 109 +++++++++++++++--- 1 file changed, 91 insertions(+), 18 deletions(-) diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 3a8701253d..59480d1aba 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -29,8 +29,27 @@ import { WarningPanel, } from '@backstage/core'; import { catalogApiRef, isOwnerOf } from '@backstage/plugin-catalog-react'; -import { Button, Grid, Link, makeStyles, Typography } from '@material-ui/core'; -import React, { useEffect, useMemo, useState } from 'react'; +import { + Button, + FormControl, + Grid, + IconButton, + Input, + InputAdornment, + InputLabel, + Link, + makeStyles, + TextField, + Toolbar, + Typography, +} from '@material-ui/core'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import { Link as RouterLink } from 'react-router-dom'; import useStaleWhileRevalidate from 'swr'; import { EntityFilterGroupsProvider, useFilteredEntities } from '../../filter'; @@ -42,6 +61,8 @@ import SettingsIcon from '@material-ui/icons/Settings'; import StarIcon from '@material-ui/icons/Star'; import { useOwnUser } from '../useOwnUser'; import { useStarredEntities } from '../../hooks/useStarredEntities'; +import Search from '@material-ui/icons/Search'; +import Clear from '@material-ui/icons/Clear'; const useStyles = makeStyles(theme => ({ contentWrapper: { @@ -50,6 +71,10 @@ const useStyles = makeStyles(theme => ({ gridTemplateColumns: '250px 1fr', gridColumnGap: theme.spacing(2), }, + searchToolbar: { + paddingLeft: 0, + paddingRight: 0, + }, })); const getTemplateCardProps = ( @@ -78,6 +103,7 @@ export const ScaffolderPageContents = () => { } = useFilteredEntities(); // TODO: use Selected Sidebar Item const [selectedSidebarItem, setSelectedSidebarItem] = useState(); + const catalogApi = useApi(catalogApiRef); const errorApi = useApi(errorApiRef); const { @@ -103,6 +129,16 @@ export const ScaffolderPageContents = () => { // TODO: ButtonGroup from CatalogFilter? const filterGroups = useMemo( () => [ + { + name: orgName, + items: [ + { + id: 'all', + label: 'All', + filterFn: () => true, + }, + ], + }, { name: 'Personal', // TODO: Do we need owner? items: [ @@ -120,20 +156,28 @@ export const ScaffolderPageContents = () => { }, ], }, - { - name: orgName, - items: [ - { - id: 'all', - label: 'All', - filterFn: () => true, - }, - ], - }, ], [isStarredEntity, orgName, user], ); + const [search, setSearch] = useState(''); + const [filteredTemplates, setFilteredTemplates] = useState([] as Entity[]); // TODO: Should I use Entity? + useEffect(() => { + const searchUppercase = search.toUpperCase(); + if (search.length === 0) { + return setFilteredTemplates(matchingEntities); + } + return setFilteredTemplates( + matchingEntities.filter(template => { + const { title, tags } = template.metadata; + return ( + `${title}`.toUpperCase().indexOf(searchUppercase) !== -1 || + `${tags}`.toUpperCase().indexOf(searchUppercase) !== -1 + ); + }), + ); + }, [search, matchingEntities]); + return (
{
+ + + setSearch(event.target.value)} + value={search} + startAdornment={ + + + + } + endAdornment={ + + setSearch('')} + edge="end" + disabled={search.length === 0} + > + + + + } + /> + + + setSelectedSidebarItem(label)} // TODO: setSelecteSidebarItem - initiallySelected="owned" + initiallySelected="all" />
- {!matchingEntities && loading && } - {matchingEntities && !matchingEntities.length && ( + {!filteredTemplates && loading && } + {filteredTemplates && !filteredTemplates.length && ( Shoot! Looks like you don't have any templates. Check out the documentation{' '} @@ -189,9 +262,9 @@ export const ScaffolderPageContents = () => { )} - {matchingEntities && - matchingEntities?.length > 0 && - matchingEntities.map(template => { + {filteredTemplates && + filteredTemplates?.length > 0 && + filteredTemplates.map(template => { return (