saved to local-storage
authorPawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>
Tue, 16 Oct 2018 07:32:19 +0000 (09:32 +0200)
committerPawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>
Tue, 16 Oct 2018 07:32:19 +0000 (09:32 +0200)
Feature #14277

Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>

src/components/icon/icon.tsx
src/services/search-service/search-service.ts
src/store/search-bar/search-bar-actions.ts
src/store/search-bar/search-bar-reducer.ts
src/views-components/search-bar/search-bar-basic-view.tsx
src/views-components/search-bar/search-bar-view.tsx
src/views-components/search-bar/search-bar.tsx

index 5d99aea93b76b12b17b2367ad570f01a4439c6ce..946d81a52a2831bf400fc891ddd9d3ffff365f47 100644 (file)
@@ -9,9 +9,10 @@ import ArrowBack from '@material-ui/icons/ArrowBack';
 import ArrowDropDown from '@material-ui/icons/ArrowDropDown';
 import BubbleChart from '@material-ui/icons/BubbleChart';
 import Cached from '@material-ui/icons/Cached';
+import ChevronLeft from '@material-ui/icons/ChevronLeft';
 import CloudUpload from '@material-ui/icons/CloudUpload';
 import Code from '@material-ui/icons/Code';
-import ChevronLeft from '@material-ui/icons/ChevronLeft';
+import Create from '@material-ui/icons/Create';
 import ImportContacts from '@material-ui/icons/ImportContacts';
 import ChevronRight from '@material-ui/icons/ChevronRight';
 import Close from '@material-ui/icons/Close';
@@ -24,6 +25,7 @@ import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
 import Folder from '@material-ui/icons/Folder';
 import GetApp from '@material-ui/icons/GetApp';
 import Help from '@material-ui/icons/Help';
+import HelpOutline from '@material-ui/icons/HelpOutline';
 import Inbox from '@material-ui/icons/Inbox';
 import Info from '@material-ui/icons/Info';
 import Input from '@material-ui/icons/Input';
@@ -46,7 +48,6 @@ import SettingsApplications from '@material-ui/icons/SettingsApplications';
 import SettingsEthernet from '@material-ui/icons/SettingsEthernet';
 import Star from '@material-ui/icons/Star';
 import StarBorder from '@material-ui/icons/StarBorder';
-import HelpOutline from '@material-ui/icons/HelpOutline';
 
 export type IconType = React.SFC<{ className?: string }>;
 
@@ -63,6 +64,7 @@ export const CloudUploadIcon: IconType = (props) => <CloudUpload {...props} />;
 export const DefaultIcon: IconType = (props) => <RateReview {...props} />;
 export const DetailsIcon: IconType = (props) => <Info {...props} />;
 export const DownloadIcon: IconType = (props) => <GetApp {...props} />;
+export const EditSavedQueryIcon: IconType = (props) => <Create {...props} />;
 export const ExpandIcon: IconType = (props) => <ExpandMoreIcon {...props} />;
 export const FavoriteIcon: IconType = (props) => <Star {...props} />;
 export const HelpIcon: IconType = (props) => <Help {...props} />;
index f9392c237a1c46387f49891201e493ca9490cbb3..9d60e1b6a750550d141fbef8a8c99b5ff43a52df 100644 (file)
@@ -2,9 +2,11 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
+import { SearchBarAdvanceFormData } from '~/models/search-bar';
+
 export class SearchService {
     private recentQueries: string[] = this.getRecentQueries();
-    private savedQueries: string[] = this.getSavedQueries();
+    private savedQueries: SearchBarAdvanceFormData[] = this.getSavedQueries();
 
     saveRecentQuery(query: string) {
         if (this.recentQueries.length >= MAX_NUMBER_OF_RECENT_QUERIES) {
@@ -20,13 +22,22 @@ export class SearchService {
         return JSON.parse(localStorage.getItem('recentQueries') || '[]') as string[];
     }
 
-    saveQuery(query: string) {
-        this.savedQueries.push(query);
+    saveQuery(data: SearchBarAdvanceFormData) {
+        this.savedQueries.push({
+            type: data.type,
+            cluster: data.cluster,
+            project: data.project,
+            inTrash: data.inTrash,
+            dateFrom: data.dateFrom,
+            dateTo: data.dateTo,
+            saveQuery: data.saveQuery,
+            searchQuery: data.searchQuery
+        });
         localStorage.setItem('savedQueries', JSON.stringify(this.savedQueries));
     }
 
     getSavedQueries() {
-        return JSON.parse(localStorage.getItem('savedQueries') || '[]') as string[];
+        return JSON.parse(localStorage.getItem('savedQueries') || '[]') as SearchBarAdvanceFormData[];
     }
 
     deleteSavedQuery(id: number) {
index 771cbc891da17de2ba7b995721ac388c2c63a483..97367e20ff7ce7b82054494adc4025ba00af0fe5 100644 (file)
@@ -14,6 +14,7 @@ import { SearchView } from '~/store/search-bar/search-bar-reducer';
 import { navigateToSearchResults, navigateTo } from '~/store/navigation/navigation-action';
 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
 import { SearchBarAdvanceFormData } from '~/models/search-bar';
+import { initialize } from 'redux-form';
 
 export const searchBarActions = unionize({
     SET_CURRENT_VIEW: ofType<string>(),
@@ -21,7 +22,7 @@ export const searchBarActions = unionize({
     CLOSE_SEARCH_VIEW: ofType<{}>(),
     SET_SEARCH_RESULTS: ofType<GroupContentsResource[]>(),
     SET_SEARCH_VALUE: ofType<string>(),
-    SET_SAVED_QUERIES: ofType<string[]>()
+    SET_SAVED_QUERIES: ofType<SearchBarAdvanceFormData[]>()
 });
 
 export type SearchBarActions = UnionOf<typeof searchBarActions>;
@@ -44,7 +45,7 @@ export const loadRecentQueries = () =>
 export const saveQuery = (data: SearchBarAdvanceFormData) =>
     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
         if (data.saveQuery && data.searchQuery) {
-            services.searchService.saveQuery(data.searchQuery);
+            services.searchService.saveQuery(data);
             dispatch(searchBarActions.SET_SAVED_QUERIES(services.searchService.getSavedQueries()));
             dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Query has been sucessfully saved', kind: SnackbarKind.SUCCESS }));
         }
@@ -58,6 +59,22 @@ export const deleteSavedQuery = (id: number) =>
         return savedSearchQueries || [];
     };
 
+export const editSavedQuery = (data: SearchBarAdvanceFormData, id: number) =>
+    (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
+        dispatch(searchBarActions.SET_CURRENT_VIEW(SearchView.ADVANCED));
+        const initialData: SearchBarAdvanceFormData = {
+            type: data.type,
+            cluster: data.cluster,
+            project: data.project,
+            inTrash: data.inTrash,
+            dateFrom: data.dateFrom,
+            dateTo: data.dateTo,
+            saveQuery: data.saveQuery,
+            searchQuery: data.searchQuery
+        };
+        dispatch<any>(initialize(SEARCH_BAR_ADVANCE_FORM_NAME, initialData));
+    };
+
 export const openSearchView = () =>
     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
         dispatch(searchBarActions.OPEN_SEARCH_VIEW());
@@ -65,22 +82,21 @@ export const openSearchView = () =>
         dispatch(searchBarActions.SET_SAVED_QUERIES(savedSearchQueries));
     };
 
-export const closeSearchView = () => 
+export const closeSearchView = () =>
     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
         const isOpen = getState().searchBar.open;
-        if(isOpen) {
+        if (isOpen) {
             dispatch(searchBarActions.CLOSE_SEARCH_VIEW());
             dispatch(searchBarActions.SET_CURRENT_VIEW(SearchView.BASIC));
         }
     };
 
-
 export const navigateToItem = (uuid: string) =>
     (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
         dispatch(searchBarActions.CLOSE_SEARCH_VIEW());
         dispatch(navigateTo(uuid));
     };
-    
+
 export const searchData = (searchValue: string) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const currentView = getState().searchBar.currentView;
index 7e119d21dc4d83715a2d54048a25af7b158d1e0b..a95604374825fd1311b21eba8a143297876e5ee0 100644 (file)
@@ -4,13 +4,14 @@
 
 import { searchBarActions, SearchBarActions } from '~/store/search-bar/search-bar-actions';
 import { GroupContentsResource } from '~/services/groups-service/groups-service';
+import { SearchBarAdvanceFormData } from '~/models/search-bar';
 
 interface SearchBar {
     currentView: string;
     open: boolean;
     searchResults: GroupContentsResource[];
     searchValue: string;
-    savedQueries: string[];
+    savedQueries: SearchBarAdvanceFormData[];
 }
 
 export enum SearchView {
index 97a5d3e34086e31bdbdc3f03a8ac1db73278a77d..8ad0f09579d032eed4debfa6e70e851238be3ab6 100644 (file)
@@ -6,6 +6,7 @@ import * as React from 'react';
 import { Paper, StyleRulesCallback, withStyles, WithStyles, List } from '@material-ui/core';
 import { SearchView } from '~/store/search-bar/search-bar-reducer';
 import { RenderRecentQueries, RenderSavedQueries } from '~/views-components/search-bar/search-bar-view';
+import { SearchBarAdvanceFormData } from '~/models/search-bar';
 
 type CssRules = 'advanced' | 'searchQueryList' | 'list' | 'searchView';
 
@@ -39,12 +40,13 @@ interface SearchBarBasicViewProps {
     setView: (currentView: string) => void;
     recentQueries: () => string[];
     deleteSavedQuery: (id: number) => void;
-    savedQueries: string[];
+    savedQueries: SearchBarAdvanceFormData[];
     onSearch: (searchValue: string) => void;
+    editSavedQuery: (data: SearchBarAdvanceFormData, id: number) => void;
 }
 
 export const SearchBarBasicView = withStyles(styles)(
-    ({ classes, setView, recentQueries, deleteSavedQuery, savedQueries, onSearch }: SearchBarBasicViewProps & WithStyles<CssRules>) =>
+    ({ classes, setView, recentQueries, deleteSavedQuery, savedQueries, onSearch, editSavedQuery }: SearchBarBasicViewProps & WithStyles<CssRules>) =>
         <Paper className={classes.searchView}>
             <div className={classes.searchQueryList}>Recent search queries</div>
             <List component="nav" className={classes.list}>
@@ -52,7 +54,7 @@ export const SearchBarBasicView = withStyles(styles)(
             </List>
             <div className={classes.searchQueryList}>Saved search queries</div>
             <List component="nav" className={classes.list}>
-                {savedQueries.map((query, index) => <RenderSavedQueries key={index} text={query} id={index} deleteSavedQuery={deleteSavedQuery} onSearch={onSearch} />)}
+                {savedQueries.map((query, index) => <RenderSavedQueries key={index} text={query.searchQuery} id={index} deleteSavedQuery={deleteSavedQuery} onSearch={onSearch} data={query} editSavedQuery={editSavedQuery}/>)}
             </List>
             <div className={classes.advanced} onClick={() => setView(SearchView.ADVANCED)}>Advanced search</div>
         </Paper>
index 8e1f84b01fabdbe0661e2bdaeebc5e7838ba8d40..a81eec97e018d8b32415473f1d92cfa62b31b813 100644 (file)
@@ -15,7 +15,7 @@ import {
     ClickAwayListener
 } from '@material-ui/core';
 import SearchIcon from '@material-ui/icons/Search';
-import { RemoveIcon } from '~/components/icon/icon';
+import { RemoveIcon, EditSavedQueryIcon } from '~/components/icon/icon';
 import { SearchView } from '~/store/search-bar/search-bar-reducer';
 import { SearchBarBasicView } from '~/views-components/search-bar/search-bar-basic-view';
 import { SearchBarAdvancedView } from '~/views-components/search-bar/search-bar-advanced-view';
@@ -53,7 +53,7 @@ type SearchBarDataProps = {
     searchValue: string;
     currentView: string;
     isPopoverOpen: boolean;
-    savedQueries: string[];
+    savedQueries: SearchBarAdvanceFormData[];
 } & SearchBarAutocompleteViewDataProps;
 
 interface SearchBarActionProps {
@@ -67,6 +67,7 @@ interface SearchBarActionProps {
     deleteSavedQuery: (id: number) => void;
     openSearchView: () => void;
     navigateTo: (uuid: string) => void;
+    editSavedQuery: (data: SearchBarAdvanceFormData, id: number) => void;
 }
 
 type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
@@ -75,8 +76,6 @@ interface SearchBarState {
     value: string;
 }
 
-
-
 interface RenderRecentQueriesProps {
     text: string | JSX.Element;
     onSearch: (searchValue: string | JSX.Element) => void;
@@ -105,12 +104,19 @@ interface RenderSavedQueriesProps {
     id: number;
     deleteSavedQuery: (id: number) => void;
     onSearch: (searchValue: string | JSX.Element) => void;
+    editSavedQuery: (data: SearchBarAdvanceFormData, id: number) => void;
+    data: SearchBarAdvanceFormData;
 }
 
 export const RenderSavedQueries = (props: RenderSavedQueriesProps) => {
     return <ListItem button>
         <ListItemText secondary={props.text} onClick={() => props.onSearch(props.text)} />
         <ListItemSecondaryAction>
+            <Tooltip title="Edit">
+                <IconButton aria-label="Edit" onClick={() => props.editSavedQuery(props.data, props.id)}>
+                    <EditSavedQueryIcon />
+                </IconButton>
+            </Tooltip>
             <Tooltip title="Remove">
                 <IconButton aria-label="Remove" onClick={() => props.deleteSavedQuery(props.id)}>
                     <RemoveIcon />
@@ -175,10 +181,10 @@ export const SearchBarView = withStyles(styles)(
         }
 
         getView = (currentView: string) => {
-            const { onSetView, loadRecentQueries, savedQueries, deleteSavedQuery, searchValue, searchResults, saveQuery, onSearch, navigateTo } = this.props;
+            const { onSetView, loadRecentQueries, savedQueries, deleteSavedQuery, searchValue, searchResults, saveQuery, onSearch, navigateTo, editSavedQuery } = this.props;
             switch (currentView) {
                 case SearchView.BASIC:
-                    return <SearchBarBasicView setView={onSetView} recentQueries={loadRecentQueries} savedQueries={savedQueries} deleteSavedQuery={deleteSavedQuery} onSearch={onSearch} />;
+                    return <SearchBarBasicView setView={onSetView} recentQueries={loadRecentQueries} savedQueries={savedQueries} deleteSavedQuery={deleteSavedQuery} onSearch={onSearch} editSavedQuery={editSavedQuery} />;
                 case SearchView.ADVANCED:
                     return <SearchBarAdvancedView setView={onSetView} saveQuery={saveQuery} />;
                 case SearchView.AUTOCOMPLETE:
@@ -187,7 +193,7 @@ export const SearchBarView = withStyles(styles)(
                         searchResults={searchResults}
                         searchValue={searchValue} />;
                 default:
-                    return <SearchBarBasicView setView={onSetView} recentQueries={loadRecentQueries} savedQueries={savedQueries} deleteSavedQuery={deleteSavedQuery} onSearch={onSearch} />;
+                    return <SearchBarBasicView setView={onSetView} recentQueries={loadRecentQueries} savedQueries={savedQueries} deleteSavedQuery={deleteSavedQuery} onSearch={onSearch} editSavedQuery={editSavedQuery} />;
             }
         }
 
index 5208a7d61c0259e2ae2724ebc9510edf2ed5b403..9eae7172de55c2ad6063f982048911638a42b2ad 100644 (file)
@@ -14,7 +14,8 @@ import {
     saveQuery,
     openSearchView,
     closeSearchView,
-    navigateToItem
+    navigateToItem,
+    editSavedQuery
 } from '~/store/search-bar/search-bar-actions';
 import { SearchBarView } from '~/views-components/search-bar/search-bar-view';
 import { SearchBarAdvanceFormData } from '~/models/search-bar';
@@ -38,7 +39,8 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
     saveQuery: (data: SearchBarAdvanceFormData) => dispatch<any>(saveQuery(data)),
     deleteSavedQuery: (id: number) => dispatch<any>(deleteSavedQuery(id)),
     openSearchView: () => dispatch<any>(openSearchView()),
-    navigateTo: (uuid: string) => dispatch<any>(navigateToItem(uuid))
+    navigateTo: (uuid: string) => dispatch<any>(navigateToItem(uuid)),
+    editSavedQuery: (data: SearchBarAdvanceFormData, id: number) => dispatch<any>(editSavedQuery(data, id))
 });
 
 export const SearchBar = connect(mapStateToProps, mapDispatchToProps)(SearchBarView);
\ No newline at end of file