Commit 27dd9978 authored by Muneeb Saeed's avatar Muneeb Saeed

Filtering work added

parent ea3a31b1
# This file specifies files that are *not* uploaded to Google Cloud
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
# Node.js dependencies:
node_modules/
\ No newline at end of file
...@@ -31,8 +31,8 @@ async function main(searchQuery, facets, filters) { ...@@ -31,8 +31,8 @@ async function main(searchQuery, facets, filters) {
// Raw search query. // Raw search query.
const query = searchQuery; //TRY DIFFERENT QUERY PHRASES const query = searchQuery; //TRY DIFFERENT QUERY PHRASES
const facetSpecs = facets ? facets : []; const facetSpecs = facets ? facets : [];
// const filter = filters; // TRY DIFFERENT FILTER EXPRESSIONS const filter = filters; /// TRY DIFFERENT FILTER EXPRESSIONS
const filter = '(availability: ANY("OUT_OF_STOCK") AND brands: ANY("Google"))'; // TRY DIFFERENT FILTER EXPRESSIONS // const filter = '(colors: ANY("Cool gray" ,"Light gray"))'; // TRY DIFFERENT FILTER EXPRESSIONS
// A unique identifier for tracking visitors. // A unique identifier for tracking visitors.
const visitorId = '12345'; const visitorId = '12345';
...@@ -52,7 +52,7 @@ async function main(searchQuery, facets, filters) { ...@@ -52,7 +52,7 @@ async function main(searchQuery, facets, filters) {
placement, placement,
query, query,
facetSpecs, facetSpecs,
// filter, filter,
visitorId, visitorId,
pageSize, pageSize,
}; };
......
...@@ -11,10 +11,17 @@ app.use(bodyParser.json()); ...@@ -11,10 +11,17 @@ app.use(bodyParser.json());
const searchService = require('./samples/interactive-tutorials/search/search-simple-query'); const searchService = require('./samples/interactive-tutorials/search/search-simple-query');
app.get('/search', (req, res) => { app.get('/search', (req, res) => {
const { text, facets } = req.query const { text, facets, filters } = req.query;
const facetArray= facets && facets.split(',') || []; const facetsObj = facets && JSON.parse(facets).map((facet) => ({ facetKey: { key: facet }}));
const facetObj = facetArray.map((facet) => ({ facetKey: { key: facet }}));
searchService(text, facetObj) const filterObj = filters && JSON.parse(filters) || [];
let filterString = '';
Object.keys(filterObj).forEach((key, i, arr) => {
filterString = filterString + `${key}: ANY("${filterObj[key].join('","')}")${i == arr.length -1 ? '' : ' AND '}`;
});
filterString = filterString && `(${filterString})`;
searchService(text, facetsObj, filterString)
.then(result => { .then(result => {
return res.send(result); return res.send(result);
}) })
......
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import './search-results.css'; import './search-results.css';
import { Typography, Col, Row, Card, Select, Checkbox, Collapse } from 'antd'; import { Typography, Col, Row, Card, Select, Checkbox, Collapse } from 'antd';
...@@ -6,12 +6,12 @@ import { LinkOutlined, FilterFilled } from '@ant-design/icons'; ...@@ -6,12 +6,12 @@ import { LinkOutlined, FilterFilled } from '@ant-design/icons';
const { Meta } = Card; const { Meta } = Card;
const { Panel } = Collapse; const { Panel } = Collapse;
const SearchResults = ({ searchResults, facets, onSelectFacet }) => { const SearchResults = ({ searchResults, facets, onSelectFacet, onSelectFilter }) => {
const availabilityMap = new Map(); const availabilityMap = new Map();
availabilityMap.set('IN_STOCK', 'In Stock'); availabilityMap.set('IN_STOCK', 'In Stock');
availabilityMap.set('OUT_OF_STOCK', 'Out of Stock'); availabilityMap.set('OUT_OF_STOCK', 'Out of Stock');
// const [filters, setFilters] = useState('()'); const [filters, setFilters] = useState(null);
const facetOptions = [ const facetOptions = [
{ {
...@@ -35,16 +35,26 @@ const SearchResults = ({ searchResults, facets, onSelectFacet }) => { ...@@ -35,16 +35,26 @@ const SearchResults = ({ searchResults, facets, onSelectFacet }) => {
facetOptions.forEach(facet => facetMap.set(facet.value, facet.label)); facetOptions.forEach(facet => facetMap.set(facet.value, facet.label));
const onChangeHandler = (value) => { const onChangeHandler = (value) => {
if (value) { onSelectFacet(value);
onSelectFacet(value)
}
}; };
const onChangeCheckboxHandler = (filterValue, filterKey) => { const onChangeCheckboxHandler = (filterValue, filterKey) => {
console.log('filterValue', filterValue); if (filterValue && filterValue.length) {
console.log('filterKey', filterKey); setFilters((prevState) => ({
...prevState,
[filterKey]: filterValue
}));
} else {
const tempVal = { ...filters }
delete tempVal[`${filterKey}`];
setFilters(tempVal);
}
};
}; useEffect(() => {
if (filters != null)
onSelectFilter(filters);
}, [filters]);
return ( return (
<> <>
...@@ -73,7 +83,7 @@ const SearchResults = ({ searchResults, facets, onSelectFacet }) => { ...@@ -73,7 +83,7 @@ const SearchResults = ({ searchResults, facets, onSelectFacet }) => {
{ facets.length > 0 && facets.map((facet, i) => { facets.length > 0 && facets.map((facet, i) =>
<Collapse ghost> <Collapse ghost>
<Panel header={facetMap.get(facet.key)} key={i} style={{ fontSize: '0.9rem', color: '#000000 ' }}> <Panel header={facetMap.get(facet.key)} key={i} style={{ fontSize: '0.9rem', color: '#000000 ' }}>
<Checkbox.Group class="verticalCheckBox" options={[...facet.values.map((f) => ({label: f.value, value: f.value}) )]} <Checkbox.Group className="verticalCheckBox" options={[...facet.values.map((f) => ({label: f.value, value: f.value}) )]}
onChange={(val) => onChangeCheckboxHandler(val, facet.key)} /> onChange={(val) => onChangeCheckboxHandler(val, facet.key)} />
</Panel> </Panel>
</Collapse> </Collapse>
......
import React, { useState } from 'react'; import React, { useEffect, useState } from 'react';
import SearchResults from './search-results'; import SearchResults from './search-results';
import { Button, Input, Col, Row } from 'antd'; import { Button, Input, Col, Row } from 'antd';
...@@ -6,38 +6,66 @@ import { SearchOutlined } from '@ant-design/icons'; ...@@ -6,38 +6,66 @@ import { SearchOutlined } from '@ant-design/icons';
const Search = () => { const Search = () => {
const [searchText, setSearchText] = useState({ text: '' }); const INITIAL_STATE = { searchQuery: '', facets: [], filters: null };
const [payload, setPayload] = useState(INITIAL_STATE);
const [searchResults, setSearchResults] = useState([]); const [searchResults, setSearchResults] = useState([]);
const [facets, setfacets] = useState([]); const [facets, setfacets] = useState([]);
const handleOnChange = (e) => { const handleOnChange = (e) => {
setSearchText(prevState => ({ setPayload(prevState => ({
...prevState, ...prevState,
text: e.target.value, searchQuery: e.target.value,
filters: null
})); }));
}; };
const handleOnSearch = async (value) => { const handleOnSearch = async () => {
const { text, facets } = value; const { searchQuery, facets, filters } = payload;
if (text) { if (searchQuery) {
const url = `https://api-dot-abs-poc-np-prj-01-3f2a.uc.r.appspot.com/search?text=${text}${facets && facets.length? `&facets=${facets}` : ''}`; const apiEndpoint = 'https://api-dot-abs-poc-np-prj-01-3f2a.uc.r.appspot.com';
// const apiEndpoint = 'http://localhost:8080';
const url = `${apiEndpoint}/search?text=${searchQuery}${facets.length? `&facets=${JSON.stringify(facets)}` : ''}${filters && Object.keys(filters).length? `&filters=${JSON.stringify(filters)}` : ''}`;
const searchResults = await fetch(url) const searchResults = await fetch(url)
.then(res => res.json()) .then(res => res.json())
.catch(err => console.log(err)); .catch(err => console.log(err));
setSearchResults(searchResults.results.length ? [...searchResults.results] : []); setSearchResults(searchResults.results?.length ? [...searchResults.results] : []);
setfacets(searchResults.facets.length ? [...searchResults.facets] : []); !Object.keys(filters || {}).length && setfacets(searchResults.facets?.length ? [...searchResults.facets] : []); // for not updating facets while filtering
} }
} };
const handleImageClick = () => { const handleImageClick = () => {
setSearchText(prevState => ({ setPayload(INITIAL_STATE);
...prevState,
text: ''
}));
setSearchResults([]); setSearchResults([]);
setfacets([]); setfacets([]);
};
const onSelectFacet = (val) => {
setPayload(prevState => ({
...prevState,
facets: val,
}));
} }
const onSelectFilter = (val) => {
setPayload(prevState => ({
...prevState,
filters: val,
}));
}
useEffect(() => {
if (payload.filters != null) {
handleOnSearch();
}
}, [payload.filters])
useEffect(() => {
payload.facets.length ? handleOnSearch() : setfacets([]);
}, [payload.facets])
return ( return (
<> <>
{searchResults.length > 0 && {searchResults.length > 0 &&
...@@ -53,13 +81,11 @@ const Search = () => { ...@@ -53,13 +81,11 @@ const Search = () => {
> >
<span style={{ <span style={{
margin: '1rem 0', margin: '1rem 0',
// width: '7rem',
height: 'auto', height: 'auto',
}} }}
onClick={() => handleImageClick()} onClick={() => handleImageClick()}
> >
<img src='ultabeauty.png' alt="google" style={{ <img src='ultabeauty.png' alt="google" style={{
// width: '100%'
}} }}
/> />
</span> </span>
...@@ -71,16 +97,19 @@ const Search = () => { ...@@ -71,16 +97,19 @@ const Search = () => {
<Input <Input
size='large' size='large'
placeholder="Input Search Text" placeholder="Input Search Text"
value={searchText.text} value={payload.searchQuery}
allowClear allowClear
prefix={<SearchOutlined style={{ color: "#d9d9d9", margin: '0 0.5rem' }} />} prefix={<SearchOutlined style={{ color: "#d9d9d9", margin: '0 0.5rem' }} />}
onChange={handleOnChange} onChange={handleOnChange}
onPressEnter={() => handleOnSearch(searchText, 2)} onPressEnter={() => handleOnSearch()}
/> />
</Col> </Col>
</Row> </Row>
</div> </div>
<SearchResults searchResults={searchResults} facets={facets} onSelectFacet={(val) => handleOnSearch({ text: searchText.text, facets: val } )} /> <SearchResults searchResults={searchResults} facets={facets}
onSelectFacet={(val) => onSelectFacet(val)}
onSelectFilter={(val) => onSelectFilter(val)}
/>
</> </>
} }
{searchResults.length === 0 && {searchResults.length === 0 &&
...@@ -92,10 +121,6 @@ const Search = () => { ...@@ -92,10 +121,6 @@ const Search = () => {
<Row> <Row>
<Col span={12} offset={6}> <Col span={12} offset={6}>
<div className='App'> <div className='App'>
{/* <Typography.Title
style={{ fontSize: '3rem', color: '#000000 ' }}>
{CONFIGS.title}
</Typography.Title> */}
<span> <span>
<img src='ultabeauty.png' alt="google" style={{ <img src='ultabeauty.png' alt="google" style={{
width: '12rem', width: '12rem',
...@@ -108,11 +133,11 @@ const Search = () => { ...@@ -108,11 +133,11 @@ const Search = () => {
<Input <Input
size='large' size='large'
placeholder="Input Search Text" placeholder="Input Search Text"
value={searchText.text} value={payload.searchQuery}
allowClear allowClear
prefix={<SearchOutlined style={{ color: "#d9d9d9", margin: '0 0.5rem' }} />} prefix={<SearchOutlined style={{ color: "#d9d9d9", margin: '0 0.5rem' }} />}
onChange={handleOnChange} onChange={handleOnChange}
onPressEnter={() => handleOnSearch(searchText)} onPressEnter={() => handleOnSearch()}
/> />
<Button type='primary' style={{ <Button type='primary' style={{
margin: '2rem 1rem', margin: '2rem 1rem',
...@@ -120,7 +145,7 @@ const Search = () => { ...@@ -120,7 +145,7 @@ const Search = () => {
minHeight: '2.5rem', minHeight: '2.5rem',
background: '#b5904a' background: '#b5904a'
}} }}
onClick={() => handleOnSearch(searchText)} onClick={() => handleOnSearch()}
> Search </Button> > Search </Button>
</div> </div>
</Col> </Col>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment