From c67a0cc20edf06aae7e198a8f67e3e54d1a975c6 Mon Sep 17 00:00:00 2001 From: shams mosowi Date: Mon, 30 Sep 2019 18:17:22 +1000 Subject: [PATCH] searchbox list result select result item --- src/components/Fields/DocSelect.tsx | 102 ++++++++------------------- src/components/SearchBox.tsx | 105 ++++++++++++++++++++++++++++ src/components/Table/grid-fns.tsx | 11 +-- src/components/Table/index.tsx | 32 ++++++++- 4 files changed, 165 insertions(+), 85 deletions(-) create mode 100644 src/components/SearchBox.tsx diff --git a/src/components/Fields/DocSelect.tsx b/src/components/Fields/DocSelect.tsx index 41338097..195e731c 100644 --- a/src/components/Fields/DocSelect.tsx +++ b/src/components/Fields/DocSelect.tsx @@ -2,21 +2,8 @@ import React, { useState, useEffect } from "react"; import SearchIcon from "@material-ui/icons/Search"; import IconButton from "@material-ui/core/IconButton"; import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; -import Popper from "@material-ui/core/Popper"; -import Paper from "@material-ui/core/Paper"; -import ClickAwayListener from "@material-ui/core/ClickAwayListener"; -import algoliasearch from "algoliasearch/lite"; import { TextField } from "@material-ui/core"; -const searchClient = algoliasearch( - process.env.REACT_APP_ALGOLIA_APP_ID - ? process.env.REACT_APP_ALGOLIA_APP_ID - : "", - process.env.REACT_APP_ALGOLIA_SEARCH_KEY - ? process.env.REACT_APP_ALGOLIA_SEARCH_KEY - : "" -); - const useStyles = makeStyles((theme: Theme) => createStyles({ root: { @@ -41,80 +28,47 @@ interface Props { onSubmit: Function; collectionPath: string; isScrolling: boolean; + setSearch: any; } const DocSelect = (props: Props) => { - const { value, row, onSubmit, collectionPath, isScrolling } = props; + const { + value, + row, + onSubmit, + collectionPath, + isScrolling, + setSearch, + } = props; const [query, setQuery] = useState(value ? value : ""); - const [hits, setHits] = useState<{}>([]); - const algoliaIndex = searchClient.initIndex(collectionPath); - const search = async (query: string) => { - const resp = await algoliaIndex.search({ query }); - setHits(resp.hits); - }; + useEffect(() => { - //search(query); + setSearch((oldValues: any) => ({ + ...oldValues, + query, + })); }, [query]); - const [anchorEl, setAnchorEl] = useState(null); const classes = useStyles(); - const handleClick = ( - event: React.MouseEvent - ) => { - setAnchorEl(event.currentTarget); + const handleClick = (event: React.MouseEvent) => { + setSearch((oldValues: any) => ({ + ...oldValues, + collection: collectionPath, + anchorEl: event.currentTarget, + onSubmit: onSubmit, + })); }; // if (isScrolling) return
; - const open = Boolean(anchorEl); - const id = open ? "no-transition-popper" : undefined; - const onClickAway = (event: any) => { - if (event.target.id !== id) { - // onSubmit(); - // setAnchorEl(null); - } - }; return ( -
- -
- - - - {value} - - - { - setQuery(e.target.value); - }} - /> - -
- {/* - - */} - - {/* */} -
-
-
-
-
-
- ); -}; - -const Hit = (props: any) => { - return ( -
-

{props.hit.firstName}

-

{props.hit.email}

+
+ { + setQuery(e.target.value); + }} + />
); }; diff --git a/src/components/SearchBox.tsx b/src/components/SearchBox.tsx new file mode 100644 index 00000000..bc7d72c4 --- /dev/null +++ b/src/components/SearchBox.tsx @@ -0,0 +1,105 @@ +import React, { useState, useEffect, useContext } from "react"; +import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; +import Popper from "@material-ui/core/Popper"; +import List from "@material-ui/core/List"; +import ListItem from "@material-ui/core/ListItem"; +import ListItemText from "@material-ui/core/ListItemText"; +import ClickAwayListener from "@material-ui/core/ClickAwayListener"; +import algoliasearch from "algoliasearch/lite"; +import Paper from "@material-ui/core/Paper"; + +const searchClient = algoliasearch( + process.env.REACT_APP_ALGOLIA_APP_ID + ? process.env.REACT_APP_ALGOLIA_APP_ID + : "", + process.env.REACT_APP_ALGOLIA_SEARCH_KEY + ? process.env.REACT_APP_ALGOLIA_SEARCH_KEY + : "" +); + +const useStyles = makeStyles(() => + createStyles({ + root: { + position: "relative", + display: "flex", + flexWrap: "wrap", + minWidth: 200, + }, + typography: {}, + textArea: { + fontSize: 14, + minWidth: 230, + }, + list: { backgroundColor: "#fff", minWidth: 200 }, + }) +); +interface Props { + searchData: { + query: string; + collection: string; + anchorEl: any; + onSubmit: Function | undefined; + }; + clearSearch: Function; +} + +const SearchBox = (props: Props) => { + const { searchData, clearSearch } = props; + const { query, collection, anchorEl, onSubmit } = searchData; + const classes = useStyles(); + + const [hits, setHits] = useState([]); + const [algoliaIndex, setAlgoliaIndex] = useState< + algoliasearch.Index | undefined + >(undefined); + useEffect(() => { + if (collection) { + setAlgoliaIndex(searchClient.initIndex(collection)); + } + }, [collection]); + + const search = async (query: string) => { + if (algoliaIndex) { + const resp = await algoliaIndex.search({ query }); + setHits(resp.hits); + } + }; + useEffect(() => { + search(query); + }, [query]); + + const open = Boolean(anchorEl); + const id = open ? "no-transition-popper" : undefined; + const onClickAway = (event: any) => {}; + const Hit = (hit: any) => ( + { + let snapshot = { ...hit }; + delete snapshot._highlightResult; + if (onSubmit) + onSubmit({ snapshot, docPath: `${collection}/${snapshot.objectID}` }); + clearSearch(); + }} + > + + + ); + + if (anchorEl) + return ( +
+ + + + results for {query} + {hits.map((hit: any) => Hit(hit))} + + + +
+ ); + else return
; +}; + +export default SearchBox; diff --git a/src/components/Table/grid-fns.tsx b/src/components/Table/grid-fns.tsx index fb4a7ffa..cdd66e3a 100644 --- a/src/components/Table/grid-fns.tsx +++ b/src/components/Table/grid-fns.tsx @@ -120,16 +120,7 @@ export const cellFormatter = (column: any) => { return (props: any) => { return ; }; - case FieldType.documentSelect: - return (props: any) => { - return ( - - ); - }; + default: return false; } diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index 231c2b3a..8af35b31 100644 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -15,10 +15,14 @@ import { onGridRowsUpdated, singleSelectEditor, editable, + onSubmit, } from "./grid-fns"; import { CLOUD_FUNCTIONS } from "firebase/callables"; import ImportCSV from "components/ImportCSV"; +import SearchBox from "../SearchBox"; +import DocSelect from "../Fields/DocSelect"; + const deleteAlgoliaRecord = functions.httpsCallable( CLOUD_FUNCTIONS.deleteAlgoliaRecord ); @@ -42,6 +46,12 @@ const useStyles = makeStyles(Theme => function Table(props: any) { const { collection } = props; const { tableState, tableActions } = useFiretable(collection); + const [search, setSearch] = useState({ + query: "", + anchorEl: undefined, + collection: "", + onSubmit: undefined, + }); useEffect(() => { tableActions.set(collection); }, [collection]); @@ -54,6 +64,22 @@ function Table(props: any) { setHeader(null); setAnchorEl(null); }; + const clearSearch = () => { + setSearch({ + query: "", + anchorEl: undefined, + collection: "", + onSubmit: undefined, + }); + }; + const docSelect = (column: any) => (props: any) => ( + + ); const handleClick = (headerProps: any) => ( event: React.MouseEvent ) => { @@ -100,7 +126,10 @@ function Table(props: any) { editable: editable(column.type), resizable: true, headerRenderer: headerRenderer, - formatter: cellFormatter(column), + formatter: + column.type === FieldType.documentSelect + ? docSelect(column) + : cellFormatter(column), editor: column.type === FieldType.singleSelect ? singleSelectEditor(column.options) @@ -171,6 +200,7 @@ function Table(props: any) { column={header && header.column} actions={tableActions.column} /> + ); } else return

Loading

;