X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/f87e91a3d8cfbcd1bebf116701423c2c54bc5e19..040d25dbcc9ec46c4c21c945ccf02dcf1bf44c26:/src/components/main-app-bar/search-bar/search-bar.tsx?ds=sidebyside

diff --git a/src/components/main-app-bar/search-bar/search-bar.tsx b/src/components/main-app-bar/search-bar/search-bar.tsx
index c07ddca844..f9e93d679c 100644
--- a/src/components/main-app-bar/search-bar/search-bar.tsx
+++ b/src/components/main-app-bar/search-bar/search-bar.tsx
@@ -3,57 +3,87 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { AppBar, Toolbar, Typography, Grid, IconButton, Badge, Paper, Input, StyleRulesCallback, withStyles, WithStyles } from '@material-ui/core';
-import NotificationsIcon from '@material-ui/icons/Notifications';
-import PersonIcon from '@material-ui/icons/Person';
-import HelpIcon from '@material-ui/icons/Help';
+import { IconButton, Paper, StyleRulesCallback, withStyles, WithStyles } from '@material-ui/core';
 import SearchIcon from '@material-ui/icons/Search';
-import { AppBarProps } from '@material-ui/core/AppBar';
 
 interface SearchBarDataProps {
     value: string;
 }
 
 interface SearchBarActionProps {
-    onChange: (value: string) => any;
-    onSubmit: () => any;
+    onSearch: (value: string) => any;
+    debounce?: number;
 }
 
-type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>
+type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
+
+interface SearchBarState {
+    value: string;
+}
+
+export const DEFAULT_SEARCH_DEBOUNCE = 1000;
 
 class SearchBar extends React.Component<SearchBarProps> {
+
+    state: SearchBarState = {
+        value: ""
+    };
+
+    timeout: NodeJS.Timer;
+
     render() {
-        const { classes } = this.props
+        const { classes } = this.props;
         return <Paper className={classes.container}>
             <form onSubmit={this.handleSubmit}>
                 <input
                     className={classes.input}
                     onChange={this.handleChange}
                     placeholder="Search"
-                    value={this.props.value}
+                    value={this.state.value}
                 />
                 <IconButton className={classes.button}>
                     <SearchIcon />
                 </IconButton>
             </form>
-        </Paper>
+        </Paper>;
+    }
+
+    componentDidMount() {
+        this.setState({value: this.props.value});
+    }
+
+    componentWillReceiveProps(nextProps: SearchBarProps) {
+        if (nextProps.value !== this.props.value) {
+            this.setState({ value: nextProps.value });
+        }
+    }
+
+    componentWillUnmount() {
+        clearTimeout(this.timeout);
     }
 
     handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
         event.preventDefault();
-        this.props.onSubmit();
+        clearTimeout(this.timeout);
+        this.props.onSearch(this.state.value);
     }
 
     handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
-        this.props.onChange(event.target.value);
+        clearTimeout(this.timeout);
+        this.setState({ value: event.target.value });
+        this.timeout = setTimeout(
+            () => this.props.onSearch(this.state.value),
+            this.props.debounce || DEFAULT_SEARCH_DEBOUNCE
+        );
+
     }
 
 }
 
-type CssRules = 'container' | 'input' | 'button'
+type CssRules = 'container' | 'input' | 'button';
 
 const styles: StyleRulesCallback<CssRules> = theme => {
-    const { unit } = theme.spacing
+    const { unit } = theme.spacing;
     return {
         container: {
             position: 'relative',
@@ -74,7 +104,7 @@ const styles: StyleRulesCallback<CssRules> = theme => {
             width: unit * 3,
             height: unit * 3
         }
-    }
-}
+    };
+};
 
-export default withStyles(styles)(SearchBar)
\ No newline at end of file
+export default withStyles(styles)(SearchBar);
\ No newline at end of file
