--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+export class SearchQueriesService {
+ private recentQueries: string[] = this.getRecentQueries();
+
+ saveRecentQuery(query: string) {
+ if (this.recentQueries.length >= 5) {
+ this.recentQueries.shift();
+ this.recentQueries.push(query);
+ } else {
+ this.recentQueries.push(query);
+ }
+ localStorage.setItem('recentQueries', JSON.stringify(this.recentQueries));
+ }
+
+ getRecentQueries() {
+ return JSON.parse(localStorage.getItem('recentQueries') || '[]') as string[];
+ }
+}
\ No newline at end of file
import { LogService } from './log-service/log-service';
import { ApiActions } from "~/services/api/api-actions";
import { WorkflowService } from "~/services/workflow-service/workflow-service";
+import { SearchQueriesService } from '~/services/search-service/search-service';
export type ServiceRepository = ReturnType<typeof createServices>;
const collectionFilesService = new CollectionFilesService(collectionService);
const favoriteService = new FavoriteService(linkService, groupsService);
const tagService = new TagService(linkService);
+ const searchQueriesService = new SearchQueriesService();
return {
ancestorsService,
linkService,
logService,
projectService,
+ searchQueriesService,
tagService,
userService,
webdavClient,
// SPDX-License-Identifier: AGPL-3.0
import { unionize, ofType, UnionOf } from "~/common/unionize";
+import { Dispatch } from 'redux';
+import { RootState } from '~/store/store';
+import { ServiceRepository } from '~/services/services';
export const searchBarActions = unionize({
SET_CURRENT_VIEW: ofType<string>(),
export type SearchBarActions = UnionOf<typeof searchBarActions>;
-export const goToView = (currentView: string) => searchBarActions.SET_CURRENT_VIEW(currentView);
\ No newline at end of file
+export const goToView = (currentView: string) => searchBarActions.SET_CURRENT_VIEW(currentView);
+
+export const saveRecentQuery = (query: string) =>
+ (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+ services.searchQueriesService.saveRecentQuery(query);
+ };
+
+export const loadRecentQueries = () =>
+ (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+ const recentSearchQueries = services.searchQueriesService.getRecentQueries();
+ return recentSearchQueries || [];
+ };
\ No newline at end of file
interface SearchBarBasicViewProps {
setView: (currentView: string) => void;
+ recentQueries: () => string[];
}
export const SearchBarBasicView = withStyles(styles)(
- ({ classes, setView }: SearchBarBasicViewProps & WithStyles<CssRules>) =>
+ ({ classes, setView, recentQueries }: SearchBarBasicViewProps & WithStyles<CssRules>) =>
<Paper className={classes.searchView}>
<div className={classes.searchQueryList}>Saved search queries</div>
<List component="nav" className={classes.list}>
</List>
<div className={classes.searchQueryList}>Recent search queries</div>
<List component="nav" className={classes.list}>
- <RenderRecentQueries text="cos" />
- <RenderRecentQueries text="testtest" />
+ {recentQueries().map((query, index) => <RenderRecentQueries key={query + index} text={query} />)}
</List>
<div className={classes.advanced} onClick={() => setView(SearchView.ADVANCED)}>Advanced search</div>
</Paper>
onSetView: (currentView: string) => void;
openView: () => void;
closeView: () => void;
+ saveQuery: (query: string) => void;
+ loadQueries: () => string[];
}
type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
getView = (currentView: string) => {
switch (currentView) {
case SearchView.BASIC:
- return <SearchBarBasicView setView={this.props.onSetView} />;
+ return <SearchBarBasicView setView={this.props.onSetView} recentQueries={this.props.loadQueries}/>;
case SearchView.ADVANCED:
return <SearchBarAdvancedView setView={this.props.onSetView} />;
case SearchView.AUTOCOMPLETE:
return <SearchBarAutocompleteView />;
default:
- return <SearchBarBasicView setView={this.props.onSetView} />;
+ return <SearchBarBasicView setView={this.props.onSetView} recentQueries={this.props.loadQueries}/>;
}
}
handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
- event.preventDefault();
- clearTimeout(this.timeout);
- this.props.onSearch(this.state.value);
- }
+ event.preventDefault();
+ clearTimeout(this.timeout);
+ this.props.saveQuery(this.state.value);
+ this.props.onSearch(this.state.value);
+ this.props.loadQueries();
+ }
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
clearTimeout(this.timeout);
import { Dispatch } from 'redux';
import { goToView, searchBarActions } from '~/store/search-bar/search-bar-actions';
import { SearchBarView } from '~/views-components/search-bar/search-bar-view';
+import { saveRecentQuery, loadRecentQueries } from '~/store/search-bar/search-bar-actions';
const mapStateToProps = ({ searchBar }: RootState) => {
return {
const mapDispatchToProps = (dispatch: Dispatch) => ({
onSetView: (currentView: string) => dispatch(goToView(currentView)),
openView: () => dispatch<any>(searchBarActions.OPEN_SEARCH_VIEW()),
- closeView: () => dispatch<any>(searchBarActions.CLOSE_SEARCH_VIEW())
+ closeView: () => dispatch<any>(searchBarActions.CLOSE_SEARCH_VIEW()),
+ saveQuery: (query: string) => dispatch<any>(saveRecentQuery(query)),
+ loadQueries: () => dispatch<any>(loadRecentQueries())
});
export const SearchBar = connect(mapStateToProps, mapDispatchToProps)(SearchBarView);
\ No newline at end of file