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, SearchBarAutocompleteViewDataProps } from '~/views-components/search-bar/search-bar-autocomplete-view';
23 import { ArvadosTheme } from '~/common/custom-theme';
25 type CssRules = 'container' | 'input' | 'searchBar';
27 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => {
36 padding: `0px ${theme.spacing.unit}px`
44 type SearchBarDataProps = {
48 } & SearchBarAutocompleteViewDataProps;
50 interface SearchBarActionProps {
51 onSearch: (value: string) => any;
53 onSetView: (currentView: string) => void;
55 closeView: () => void;
58 type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
60 interface SearchBarState {
64 interface RenderQueriesProps {
65 text: string | JSX.Element;
68 export const RecentQueriesItem = (props: RenderQueriesProps) => {
69 return <ListItem button>
70 <ListItemText secondary={props.text} />
75 export const RenderSavedQueries = (props: RenderQueriesProps) => {
76 return <ListItem button>
77 <ListItemText secondary={props.text} />
78 <ListItemSecondaryAction>
79 <Tooltip title="Remove">
80 <IconButton aria-label="Remove">
84 </ListItemSecondaryAction>
88 export const DEFAULT_SEARCH_DEBOUNCE = 1000;
90 export const SearchBarView = withStyles(styles)(
91 class extends React.Component<SearchBarProps> {
92 state: SearchBarState = {
99 const { classes, currentView, openView, closeView, open } = this.props;
100 return <ClickAwayListener onClickAway={() => closeView()}>
101 <Paper className={classes.container} >
102 <form onSubmit={this.handleSubmit} className={classes.searchBar}>
104 className={classes.input}
105 onChange={this.handleChange}
107 value={this.state.value}
109 disableUnderline={true}
110 onClick={() => openView()}
112 <InputAdornment position="end">
113 <Tooltip title='Search'>
120 {open && this.getView(currentView)}
123 </ClickAwayListener>;
126 componentDidMount() {
127 this.setState({ value: this.props.searchValue });
130 componentWillReceiveProps(nextProps: SearchBarProps) {
131 if (nextProps.searchValue !== this.props.searchValue) {
132 this.setState({ value: nextProps.searchValue });
136 componentWillUnmount() {
137 clearTimeout(this.timeout);
140 getView = (currentView: string) => {
141 switch (currentView) {
142 case SearchView.BASIC:
143 return <SearchBarBasicView setView={this.props.onSetView} />;
144 case SearchView.ADVANCED:
145 return <SearchBarAdvancedView setView={this.props.onSetView} />;
146 case SearchView.AUTOCOMPLETE:
147 return <SearchBarAutocompleteView
148 searchResults={this.props.searchResults}
149 searchValue={this.props.searchValue} />;
151 return <SearchBarBasicView setView={this.props.onSetView} />;
155 handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
156 event.preventDefault();
157 clearTimeout(this.timeout);
158 this.props.onSearch(this.state.value);
161 handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
162 clearTimeout(this.timeout);
163 this.setState({ value: event.target.value });
164 this.timeout = window.setTimeout(
165 () => this.props.onSearch(this.state.value),
166 this.props.debounce || DEFAULT_SEARCH_DEBOUNCE
168 if (event.target.value.length > 0) {
169 this.props.onSetView(SearchView.AUTOCOMPLETE);
171 this.props.onSetView(SearchView.BASIC);