From 3f7007f25947eb74fe3814152fe6a9e0a185b494 Mon Sep 17 00:00:00 2001 From: Sudhanshu Gautam Date: Wed, 3 Jul 2019 02:51:14 +0530 Subject: [PATCH] adds search bar functionality The process of finding image for a specific device by select inputs was a tidious one. Search bar functionality was introduced to make the process easier and convenient. The search uses fuzzyset.js to find possible suggestions for the user in realtime. Signed-off-by: Sudhanshu Gautam --- package.json | 4 +- src/containers/home/home.js | 320 +++++++++++++++----------------- src/containers/home/home.scss | 12 +- src/locales/de/translation.json | 4 + src/locales/en/translation.json | 4 + yarn.lock | 173 ++--------------- 6 files changed, 180 insertions(+), 337 deletions(-) diff --git a/package.json b/package.json index 8c1d6ca..3322b17 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "dependencies": { "@material-ui/core": "^4.1.2", "@material-ui/icons": "^4.2.1", + "fuzzyset.js": "^0.0.8", "gh-pages": "^2.0.1", "i18next": "^17.0.4", "i18next-browser-languagedetector": "^3.0.1", @@ -14,8 +15,7 @@ "react-dom": "^16.8.6", "react-i18next": "^10.11.2", "react-router-dom": "^5.0.1", - "react-scripts": "3.0.1", - "react-select": "^3.0.4" + "react-scripts": "3.0.1" }, "scripts": { "start": "react-scripts start", diff --git a/src/containers/home/home.js b/src/containers/home/home.js index d13ed3a..70b4d46 100644 --- a/src/containers/home/home.js +++ b/src/containers/home/home.js @@ -1,158 +1,135 @@ import React from "react"; -import { Container, Paper, Typography, Grid, Button } from "@material-ui/core"; +import { Container, Paper, Typography, InputAdornment, FormControl, TextField, List, ListItem, ListItemText } from "@material-ui/core"; +import { fade, makeStyles } from '@material-ui/core/styles'; + + +import SearchIcon from '@material-ui/icons/Search'; import './home.scss'; -import Select from 'react-select'; import data from '../../data.json'; import { withTranslation } from 'react-i18next'; +import FuzzySet from 'fuzzyset.js'; + +const useStylesSearch = makeStyles(theme => ({ + root: { + borderColor: '#e2e2e1', + overflow: 'hidden', + margin: 0, + borderRadius: 4, + transition: theme.transitions.create(['border-color', 'box-shadow']), + '&:hover': { + borderColor: fade(theme.palette.primary.main, 0.25), + }, + '&$focused': { + backgroundColor: '#fff', + boxShadow: `${fade(theme.palette.primary.main, 0.25)} 0 0 0 2px`, + borderColor: theme.palette.primary.main, + }, + }, + focused: {}, +})); + +function SearchTextField(props) { + const classes = useStylesSearch(); + + return ( + + {props.labelText} + + } + InputProps={ + { classes, + endAdornment: ( + + + + ) + } + } {...props} /> + ); +} class Home extends React.Component { - devices = []; + deviceNames = []; + deviceNamesID = {}; state = { - selectedOption: null, - variants: [], - models: [], showDeviceData: false, device: null, - vendor: null, - model: null, - variant: null + searchResults: [], + showSearch: false, + selectedSearchIndex: 0, + query: '', }; - - vendorExistsInDevices(vendor) { - var exists = false; - var existIndex = -1; - this.devices.forEach((d, i) => { - if (d["label"] === vendor) { - exists = true; - existIndex = i; - } - }); - return { - exists, - existIndex - }; - } - - modelExistsInDevices(vendorIndex, model) { - var exists = false; - var existIndex = -1; - this.devices[vendorIndex]["value"].forEach((d, i) => { - if (d["label"] === model) { - exists = true; - existIndex = i; - } - }); - return { - exists, - existIndex - }; - } - - variantExistsInDevices(vendorIndex, modelIndex, variant) { - var exists = false; - var existIndex = -1; - this.devices[vendorIndex]["value"][modelIndex]["value"].forEach((d, i) => { - if (d["label"] === variant) { - exists = true; - existIndex = i; - } - }); - return { - exists, - existIndex - }; - } + fuzzySet; componentDidMount() { - Object.keys(data["devices"]).forEach((device_id) => { - var vendor = ""; - var variant = ""; - var device_data = data["devices"][device_id]; - if ("vendor" in device_data) { - vendor = device_data["vendor"]; + Object.keys(data['devices']).forEach((device_id) => { + var deviceName = ''; + if ('vendor' in data['devices'][device_id]) { + deviceName += data['devices'][device_id]['vendor'] + ' '; } - var model = device_data["model"]; - if ("variant" in device_data) { - variant = device_data["variant"]; - } - var vendorExists = this.vendorExistsInDevices(vendor); - if (vendorExists.exists) { - var modelExists = this.modelExistsInDevices(vendorExists.existIndex, model); - if (modelExists.exists) { - var variantExists = this.variantExistsInDevices(vendorExists.existIndex, modelExists.existIndex, variant); - if (!variantExists.existIndex) { - this.devices[vendorExists.existIndex]["value"][modelExists.existIndex]["value"].push({ - "label": variant, - "value": device_data - }); - } - } else { - this.devices[vendorExists.existIndex]["value"].push({ - "label": model, - "value": [{ - "label": variant, - "value": device_data - }] - }); + deviceName += data['devices'][device_id]['model']; + if ('variant' in data['devices'][device_id]) { + if (data['devices'][device_id]['variant'] !== '') { + deviceName += ' ' + data['devices'][device_id]['variant']; } - } else { - this.devices.push({ - "label": vendor, - "value": [{ - "label": model, - "value": [{ - "label": variant, - "value": device_data - }] - }] - }); } + this.deviceNames.push(deviceName); + this.deviceNamesID[deviceName] = device_id; }); - } - - changeVendor = (v) => { - this.setState({ - vendor: v, - model: null, - variant: null, - }); - } - - changeModel = (v) => { - this.setState({ - model: v, - variant: v.value[0], - }); - } - - changeVariant = (v) => { - this.setState({ - variant: v, - }); + this.fuzzySet = FuzzySet(this.deviceNames); } - findDevice = () => { - try { - var device = this.state.variant.value; + selectDevice = (device_id) => { + if (device_id != null) { this.setState({ - device: device, + device: data["devices"][device_id], showDeviceData: true, - }); - } catch (error) { - this.setState({ - device: {}, - showDeviceData: false, + query: data["devices"][device_id]["vendor"] + " " + data["devices"][device_id]["model"] + " " + data["devices"][device_id]["variant"] }); } } - noOptionsMessage = (props) => {this.props.t('components.select.noOptions')}; + search = (event) => { + const query = event.target.value; + var showSearch = false; + this.setState({ + query, + searchResults: [], + showSearch, + }); + const deviceNames = this.fuzzySet.get(query, undefined, 0); + var searchResults = []; + if (deviceNames != null) { + for (var i = 0; i < deviceNames.length && i < 6; i++) { + searchResults.push(data['devices'][this.deviceNamesID[deviceNames[i][1]]]); + } + } + showSearch = true; + if (query === '') { + showSearch = false; + } + this.setState({ + searchResults, + showSearch, + }); + } + + hideSearch = () => { + setTimeout(() => { + this.setState({ + showSearch: false, + }); + }, 300); + } render() { return ( - + {this.props.t('appIntro.head')} @@ -160,53 +137,50 @@ class Home extends React.Component { {this.props.t('appIntro.para')}
- - - - - ) - } - { - this.state.model === null ? '' : ( - (this.state.model.value.length === 1 && this.state.model.value[0].label === '') ? '' : ( - -