linking-to-different-views
authorPawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>
Fri, 5 Oct 2018 11:37:10 +0000 (13:37 +0200)
committerPawel Kowalczyk <pawel.kowalczyk@contractors.roche.com>
Fri, 5 Oct 2018 11:37:10 +0000 (13:37 +0200)
Feature #14275

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

src/components/search-bar/search-bar.tsx
src/store/store.ts
src/store/structured-search/structured-search-actions.ts [new file with mode: 0644]
src/store/structured-search/structured-search-reducer.ts [new file with mode: 0644]

index ebb7f5e9e6e6ecc74ec692cf45bdd57eca1ea117..2036a6625db342d034f2376a7bcbc71304fe6109 100644 (file)
@@ -11,10 +11,15 @@ import {
     WithStyles,
     Tooltip,
     InputAdornment, Input,
-    List, ListItem, ListItemText, ListItemSecondaryAction
+    List, ListItem, ListItemText, ListItemSecondaryAction, Button
 } from '@material-ui/core';
 import SearchIcon from '@material-ui/icons/Search';
 import { RemoveIcon } from '~/components/icon/icon';
+import { connect } from 'react-redux';
+import { RootState } from '~/store/store';
+import { Dispatch } from 'redux';
+import { goToView } from '~/store/structured-search/structured-search-actions';
+import { SearchView } from '~/store/structured-search/structured-search-reducer';
 
 type CssRules = 'container' | 'input' | 'advanced' | 'searchQueryList' | 'list' | 'searchView' | 'searchBar';
 
@@ -34,7 +39,8 @@ const styles: StyleRulesCallback<CssRules> = theme => {
             justifyContent: 'flex-end',
             paddingRight: theme.spacing.unit * 2,
             paddingBottom: theme.spacing.unit,
-            fontSize: '14px'
+            fontSize: '14px',
+            cursor: 'pointer'
         },
         searchQueryList: {
             padding: `${theme.spacing.unit / 2}px ${theme.spacing.unit}px `,
@@ -55,11 +61,13 @@ const styles: StyleRulesCallback<CssRules> = theme => {
 
 interface SearchBarDataProps {
     value: string;
+    currentView: string;
 }
 
 interface SearchBarActionProps {
     onSearch: (value: string) => any;
     debounce?: number;
+    onSetView: (currentView: string) => void;
 }
 
 type SearchBarProps = SearchBarDataProps & SearchBarActionProps & WithStyles<CssRules>;
@@ -69,9 +77,21 @@ interface SearchBarState {
     isSearchViewOpen: boolean;
 }
 
+const mapStateToProps = ({ structuredSearch }: RootState) => {
+    return {
+        currentView: structuredSearch.currentView
+    };
+};
+
+const mapDispatchToProps = (dispatch: Dispatch) => ({
+    onSetView: (currentView: string) => {
+        dispatch<any>(goToView(currentView));
+    }
+});
+
 export const DEFAULT_SEARCH_DEBOUNCE = 1000;
 
-export const SearchBar = withStyles(styles)(
+export const SearchBar = connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(
     class extends React.Component<SearchBarProps> {
         state: SearchBarState = {
             value: "",
@@ -81,8 +101,8 @@ export const SearchBar = withStyles(styles)(
         timeout: number;
 
         render() {
-            const { classes } = this.props;
-            return <Paper className={classes.container} onBlur={this.closeSearchView}>
+            const { classes, currentView } = this.props;
+            return <Paper className={classes.container} >
                 <form onSubmit={this.handleSubmit} className={classes.searchBar}>
                     <Input
                         autoComplete={''}
@@ -92,7 +112,7 @@ export const SearchBar = withStyles(styles)(
                         value={this.state.value}
                         fullWidth={true}
                         disableUnderline={true}
-                        onFocus={this.openSearchView}
+                        onClick={this.toggleSearchView}
                         endAdornment={
                             <InputAdornment position="end">
                                 <Tooltip title='Search'>
@@ -102,19 +122,7 @@ export const SearchBar = withStyles(styles)(
                                 </Tooltip>
                             </InputAdornment>
                         } />
-                    {this.state.isSearchViewOpen && <Paper className={classes.searchView}>
-                        <div className={classes.searchQueryList}>Saved search queries</div>
-                        <List component="nav" className={classes.list}>
-                            {this.renderSavedQueries('Test')}
-                            {this.renderSavedQueries('Demo')}
-                        </List>
-                        <div className={classes.searchQueryList}>Recent search queries</div>
-                        <List component="nav" className={classes.list}>
-                            {this.renderRecentQueries('cos')}
-                            {this.renderRecentQueries('testtest')}
-                        </List>
-                        <div className={classes.advanced}>Advanced search</div>
-                    </Paper>}
+                    {this.state.isSearchViewOpen && this.getView(currentView)}
                 </form>
             </Paper>;
         }
@@ -133,13 +141,42 @@ export const SearchBar = withStyles(styles)(
             clearTimeout(this.timeout);
         }
 
-        closeSearchView = () =>
-            this.setState({ isSearchViewOpen: false })
-
-
-        openSearchView = () =>
-            this.setState({ isSearchViewOpen: true })
+        toggleSearchView = () =>
+            this.setState({ isSearchViewOpen: !this.state.isSearchViewOpen })
 
+        getView = (currentView: string) => {
+            switch (currentView) {
+                case SearchView.BASIC:
+                    return <Paper className={this.props.classes.searchView}>
+                        <div className={this.props.classes.searchQueryList}>Saved search queries</div>
+                        <List component="nav" className={this.props.classes.list}>
+                            {this.renderSavedQueries('Test')}
+                            {this.renderSavedQueries('Demo')}
+                        </List>
+                        <div className={this.props.classes.searchQueryList}>Recent search queries</div>
+                        <List component="nav" className={this.props.classes.list}>
+                            {this.renderRecentQueries('cos')}
+                            {this.renderRecentQueries('testtest')}
+                        </List>
+                        <div className={this.props.classes.advanced} onClick={() => this.props.onSetView(SearchView.ADVANCED)}>Advanced search</div>
+                    </Paper>;
+                case SearchView.ADVANCED:
+                    return <Paper>
+                        <List component="nav" className={this.props.classes.list}>
+                            {this.renderRecentQueries('ADVANCED VIEW')}
+                        </List>
+                        <Button onClick={() => this.props.onSetView(SearchView.BASIC)}>Back</Button>
+                    </Paper>;
+                case SearchView.AUTOCOMPLETE:
+                    return <Paper>
+                        <List component="nav" className={this.props.classes.list}>
+                            {this.renderRecentQueries('AUTOCOMPLETE VIEW')}
+                        </List>
+                    </Paper>;
+                default:
+                    return '';
+            }
+        }
 
         renderRecentQueries = (text: string) =>
             <ListItem button>
@@ -171,7 +208,11 @@ export const SearchBar = withStyles(styles)(
                 () => this.props.onSearch(this.state.value),
                 this.props.debounce || DEFAULT_SEARCH_DEBOUNCE
             );
-
+            if (event.target.value.length > 0) {
+                this.props.onSetView(SearchView.AUTOCOMPLETE);
+            } else {
+                this.props.onSetView(SearchView.BASIC);
+            }
         }
     }
-);
+));
index 4c08a39c4b4a394ba1a8cde77249ab90c49bf7f1..48c03dbf8445f8d48662af3b8c328b7217018b65 100644 (file)
@@ -39,6 +39,7 @@ import { runProcessPanelReducer } from '~/store/run-process-panel/run-process-pa
 import { WorkflowMiddlewareService } from './workflow-panel/workflow-middleware-service';
 import { WORKFLOW_PANEL_ID } from './workflow-panel/workflow-panel-actions';
 import { fileTreePickerReducer } from './file-tree-picker/file-tree-picker-reducer';
+import { structuredSearchReducer } from './structured-search/structured-search-reducer';
 
 const composeEnhancers =
     (process.env.NODE_ENV === 'development' &&
@@ -101,5 +102,6 @@ const createRootReducer = (services: ServiceRepository) => combineReducers({
     processPanel: processPanelReducer,
     progressIndicator: progressIndicatorReducer,
     fileTreePicker: fileTreePickerReducer,
-    runProcessPanel: runProcessPanelReducer
+    runProcessPanel: runProcessPanelReducer,
+    structuredSearch: structuredSearchReducer
 });
diff --git a/src/store/structured-search/structured-search-actions.ts b/src/store/structured-search/structured-search-actions.ts
new file mode 100644 (file)
index 0000000..0f3efd9
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { unionize, ofType, UnionOf } from "~/common/unionize";
+
+export const structuredSearchActions = unionize({
+    SET_CURRENT_VIEW: ofType<string>()
+});
+
+export type StructuredSearchActions = UnionOf<typeof structuredSearchActions>;
+
+export const goToView = (currentView: string) => structuredSearchActions.SET_CURRENT_VIEW(currentView);
\ No newline at end of file
diff --git a/src/store/structured-search/structured-search-reducer.ts b/src/store/structured-search/structured-search-reducer.ts
new file mode 100644 (file)
index 0000000..8633c15
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { structuredSearchActions, StructuredSearchActions } from '~/store/structured-search/structured-search-actions';
+
+interface StructuredSearch {
+    currentView: string;
+}
+
+export enum SearchView {
+    BASIC = 'basic',
+    ADVANCED = 'advanced',
+    AUTOCOMPLETE = 'autocomplete'
+}
+
+const initialState: StructuredSearch = {
+    currentView: SearchView.BASIC
+};
+
+export const structuredSearchReducer = (state = initialState, action: StructuredSearchActions): StructuredSearch => 
+    structuredSearchActions.match(action, {
+        SET_CURRENT_VIEW: currentView => ({... state, currentView}),
+        default: () => state
+    });
\ No newline at end of file