1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
13 InputAdornment, Input,
14 ListItem, ListItemText, ListItemSecondaryAction,
16 } from '@material-ui/core';
17 import SearchIcon from '@material-ui/icons/Search';
18 import { RemoveIcon } from '~/components/icon/icon';
19 import { SearchView } from '~/store/search-bar/search-bar-reducer';
20 import { SearchBarBasicView } from '~/views-components/search-bar/search-bar-basic-view';
21 import { SearchBarAdvancedView } from '~/views-components/search-bar/search-bar-advanced-view';
22 import { SearchBarAutocompleteView } from '~/views-components/search-bar/search-bar-autocomplete-view';
24 type CssRules = 'container' | 'input' | 'searchBar';
26 const styles: StyleRulesCallback<CssRules> = theme => {
35 padding: `0px ${theme.spacing.unit}px`
43 interface SearchBarDataProps {
49 interface SearchBarActionProps {
50 onSearch: (value: string) => any;
52 onSetView: (currentView: string) => void;
54 closeView: () => void;
55 saveQuery: (query: string) => void;
56 loadQueries: () => string[];
59 type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
61 interface SearchBarState {
65 interface RenderQueriesProps {
69 export const RenderRecentQueries = (props: RenderQueriesProps) => {
70 return <ListItem button>
71 <ListItemText secondary={props.text} />
76 export const RenderSavedQueries = (props: RenderQueriesProps) => {
77 return <ListItem button>
78 <ListItemText secondary={props.text} />
79 <ListItemSecondaryAction>
80 <Tooltip title="Remove">
81 <IconButton aria-label="Remove">
85 </ListItemSecondaryAction>
89 export const DEFAULT_SEARCH_DEBOUNCE = 1000;
91 export const SearchBarView = withStyles(styles)(
92 class extends React.Component<SearchBarProps> {
93 state: SearchBarState = {
100 const { classes, currentView, openView, closeView, open } = this.props;
101 return <ClickAwayListener onClickAway={() => closeView()}>
102 <Paper className={classes.container} >
103 <form onSubmit={this.handleSubmit} className={classes.searchBar}>
105 className={classes.input}
106 onChange={this.handleChange}
108 value={this.state.value}
110 disableUnderline={true}
111 onClick={() => openView()}
113 <InputAdornment position="end">
114 <Tooltip title='Search'>
121 {open && this.getView(currentView)}
124 </ClickAwayListener>;
127 componentDidMount() {
128 this.setState({ value: this.props.value });
131 componentWillReceiveProps(nextProps: SearchBarProps) {
132 if (nextProps.value !== this.props.value) {
133 this.setState({ value: nextProps.value });
137 componentWillUnmount() {
138 clearTimeout(this.timeout);
141 getView = (currentView: string) => {
142 switch (currentView) {
143 case SearchView.BASIC:
144 return <SearchBarBasicView setView={this.props.onSetView} recentQueries={this.props.loadQueries}/>;
145 case SearchView.ADVANCED:
146 return <SearchBarAdvancedView setView={this.props.onSetView} />;
147 case SearchView.AUTOCOMPLETE:
148 return <SearchBarAutocompleteView />;
150 return <SearchBarBasicView setView={this.props.onSetView} recentQueries={this.props.loadQueries}/>;
154 handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
155 event.preventDefault();
156 clearTimeout(this.timeout);
157 this.props.saveQuery(this.state.value);
158 this.props.onSearch(this.state.value);
159 this.props.loadQueries();
162 handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
163 clearTimeout(this.timeout);
164 this.setState({ value: event.target.value });
165 this.timeout = window.setTimeout(
166 () => this.props.onSearch(this.state.value),
167 this.props.debounce || DEFAULT_SEARCH_DEBOUNCE
169 if (event.target.value.length > 0) {
170 this.props.onSetView(SearchView.AUTOCOMPLETE);
172 this.props.onSetView(SearchView.BASIC);