searchbox list result select result item

This commit is contained in:
shams mosowi
2019-09-30 18:17:22 +10:00
parent a5c8ad9bc8
commit c67a0cc20e
4 changed files with 165 additions and 85 deletions

View File

@@ -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<HTMLButtonElement | null>(null);
const classes = useStyles();
const handleClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
setAnchorEl(event.currentTarget);
const handleClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
setSearch((oldValues: any) => ({
...oldValues,
collection: collectionPath,
anchorEl: event.currentTarget,
onSubmit: onSubmit,
}));
};
// if (isScrolling) return <div />;
const open = Boolean(anchorEl);
const id = open ? "no-transition-popper" : undefined;
const onClickAway = (event: any) => {
if (event.target.id !== id) {
// onSubmit();
// setAnchorEl(null);
}
};
return (
<div className={classes.root}>
<ClickAwayListener onClickAway={onClickAway}>
<div>
<IconButton onClick={handleClick}>
<SearchIcon />
</IconButton>
{value}
<Popper id={id} open={open} anchorEl={anchorEl}>
<Paper>
<TextField
id={id}
placeholder={`searching ${collectionPath}`}
onChange={(e: any) => {
setQuery(e.target.value);
}}
/>
<div>
{/* <InstantSearch
indexName={collectionPath}
searchClient={searchClient}
>
<SearchBox /> */}
{/* </InstantSearch> */}
</div>
</Paper>
</Popper>
</div>
</ClickAwayListener>
</div>
);
};
const Hit = (props: any) => {
return (
<div>
<h3>{props.hit.firstName}</h3>
<p>{props.hit.email}</p>
<div className={classes.root} onClick={handleClick}>
<TextField
placeholder={`searching ${collectionPath}`}
onChange={(e: any) => {
setQuery(e.target.value);
}}
/>
</div>
);
};

View File

@@ -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<any[]>([]);
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) => (
<ListItem
button
onClick={() => {
let snapshot = { ...hit };
delete snapshot._highlightResult;
if (onSubmit)
onSubmit({ snapshot, docPath: `${collection}/${snapshot.objectID}` });
clearSearch();
}}
>
<ListItemText primary={hit.firstName} secondary={hit.lastName} />
</ListItem>
);
if (anchorEl)
return (
<div className={classes.root}>
<ClickAwayListener onClickAway={onClickAway}>
<Popper id={id} open={open} anchorEl={anchorEl}>
<Paper>
results for {query}
<List>{hits.map((hit: any) => Hit(hit))}</List>
</Paper>
</Popper>
</ClickAwayListener>
</div>
);
else return <div />;
};
export default SearchBox;

View File

@@ -120,16 +120,7 @@ export const cellFormatter = (column: any) => {
return (props: any) => {
return <LongText {...props} onSubmit={onSubmit(key, props.row)} />;
};
case FieldType.documentSelect:
return (props: any) => {
return (
<DocSelect
{...props}
onSubmit={onSubmit(key, props.row)}
collectionPath={column.collectionPath}
/>
);
};
default:
return false;
}

View File

@@ -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) => (
<DocSelect
{...props}
onSubmit={onSubmit(column.key, props.row)}
collectionPath={column.collectionPath}
setSearch={setSearch}
/>
);
const handleClick = (headerProps: any) => (
event: React.MouseEvent<HTMLButtonElement, 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}
/>
<SearchBox searchData={search} clearSearch={clearSearch} />
</>
);
} else return <p>Loading</p>;