19783: Filtering collections works now
authorPeter Amstutz <peter.amstutz@curii.com>
Fri, 9 Dec 2022 01:59:09 +0000 (20:59 -0500)
committerPeter Amstutz <peter.amstutz@curii.com>
Fri, 9 Dec 2022 01:59:09 +0000 (20:59 -0500)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

src/store/tree-picker/tree-picker-reducer.ts
src/views-components/projects-tree-picker/projects-tree-picker.tsx
src/views/run-process-panel/inputs/file-input.tsx

index d4b710c9733e9cbd82fe001ae0b133aab404991a..df0ee0ad167376af2eec2a81293ade246714ba96 100644 (file)
@@ -72,6 +72,10 @@ const receiveNodes = <V>(nodes: Array<TreeNode<V>>) => (parent: string) => (stat
         newState = setNode({ ...parentNode, children: [] })(state);
     }
     return nodes.reduce((tree, node) => {
+        const preexistingNode = getNode(node.id)(state);
+        if (preexistingNode) {
+            node = { ...preexistingNode, value: node.value };
+        }
         return setNode({ ...node, parent })(tree);
     }, newState);
 };
index bddde892039f3a6448fc2bb0b6718e71562a53e5..8f21784bd46fa5a619cddf26555adedf4fddbbf1 100644 (file)
@@ -4,19 +4,24 @@
 
 import React from 'react';
 import { Dispatch } from 'redux';
-import { connect } from 'react-redux';
+import { connect, DispatchProp } from 'react-redux';
 import { RootState } from 'store/store';
 import { values, pipe } from 'lodash/fp';
 import { HomeTreePicker } from 'views-components/projects-tree-picker/home-tree-picker';
 import { SharedTreePicker } from 'views-components/projects-tree-picker/shared-tree-picker';
 import { FavoritesTreePicker } from 'views-components/projects-tree-picker/favorites-tree-picker';
-import { getProjectsTreePickerIds, treePickerSearchActions, SHARED_PROJECT_ID, FAVORITES_PROJECT_ID } from 'store/tree-picker/tree-picker-actions';
+import {
+    getProjectsTreePickerIds, treePickerActions, treePickerSearchActions, initProjectsTreePicker,
+    SHARED_PROJECT_ID, FAVORITES_PROJECT_ID
+} from 'store/tree-picker/tree-picker-actions';
 import { TreeItem } from 'components/tree/tree';
 import { ProjectsTreePickerItem } from 'store/tree-picker/tree-picker-middleware';
 import { PublicFavoritesTreePicker } from './public-favorites-tree-picker';
 import { SearchInput } from 'components/search-input/search-input';
+import { withStyles, StyleRulesCallback, WithStyles } from '@material-ui/core';
+import { ArvadosTheme } from 'common/custom-theme';
 
-export interface ProjectsTreePickerProps {
+export interface ToplevelPickerProps {
     pickerId: string;
     includeCollections?: boolean;
     includeFiles?: boolean;
@@ -36,15 +41,13 @@ interface ProjectsTreePickerActionProps {
     onCollectionFilter: (value: string) => void;
 }
 
-type ProjectsTreePickerCombinedProps = ProjectsTreePickerProps & ProjectsTreePickerSearchProps & ProjectsTreePickerActionProps;
-
-const mapStateToProps = (state: RootState, props: ProjectsTreePickerProps): ProjectsTreePickerSearchProps => ({
+const mapStateToProps = (state: RootState, props: ToplevelPickerProps): ProjectsTreePickerSearchProps => ({
     projectSearch: "",
     collectionFilter: "",
     ...props
 });
 
-const mapDispatchToProps = (dispatch: Dispatch, props: ProjectsTreePickerProps): ProjectsTreePickerActionProps => {
+const mapDispatchToProps = (dispatch: Dispatch, props: ToplevelPickerProps): (ProjectsTreePickerActionProps & DispatchProp) => {
     const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(props.pickerId);
     const params = {
         includeCollections: props.includeCollections,
@@ -63,37 +66,87 @@ const mapDispatchToProps = (dispatch: Dispatch, props: ProjectsTreePickerProps):
             dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: shared, collectionFilterValue }));
             dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: favorites, collectionFilterValue }));
             dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: publicFavorites, collectionFilterValue }));
-        }
+        },
+        dispatch
     }
 };
 
-export const ProjectsTreePicker = connect(mapStateToProps, mapDispatchToProps)(({ pickerId, onProjectSearch, onCollectionFilter, ...props }: ProjectsTreePickerCombinedProps) => {
-    const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(pickerId);
-    const relatedTreePickers = getRelatedTreePickers(pickerId);
-    const p = {
-        ...props,
-        relatedTreePickers,
-        disableActivation,
-    };
-    return <div>
-        <span>
-            <SearchInput value="" label="Search Projects" selfClearProp='' onSearch={onProjectSearch} debounce={200} />
-            <SearchInput value="" label="Filter Collections" selfClearProp='' onSearch={onCollectionFilter} debounce={200} />
-        </span>
-        <div data-cy="projects-tree-home-tree-picker">
-            <HomeTreePicker pickerId={home} {...p} />
-        </div>
-        <div data-cy="projects-tree-shared-tree-picker">
-            <SharedTreePicker pickerId={shared} {...p} />
-        </div>
-        <div data-cy="projects-tree-public-favourites-tree-picker">
-            <PublicFavoritesTreePicker pickerId={publicFavorites} {...p} />
-        </div>
-        <div data-cy="projects-tree-favourites-tree-picker">
-            <FavoritesTreePicker pickerId={favorites} {...p} />
-        </div>
-    </div>;
+type CssRules = 'pickerHeight' | 'searchFlex' | 'searchPadding';
+
+const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+    pickerHeight: {
+        height: "80vh"
+    },
+    searchFlex: {
+        display: "flex",
+        justifyContent: "space-around",
+        paddingBottom: "1em"
+    },
 });
 
+type ProjectsTreePickerCombinedProps = ToplevelPickerProps & ProjectsTreePickerSearchProps & ProjectsTreePickerActionProps & DispatchProp & WithStyles<CssRules>;
+
+export const ProjectsTreePicker = connect(mapStateToProps, mapDispatchToProps)(
+    withStyles(styles)(
+        class FileInputComponent extends React.Component<ProjectsTreePickerCombinedProps> {
+
+            componentDidMount() {
+                const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(this.props.pickerId);
+
+                this.props.dispatch<any>(initProjectsTreePicker(this.props.pickerId));
+
+                this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_PROJECT_SEARCH({ pickerId: this.props.pickerId, projectSearchValue: "" }));
+                this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: home, collectionFilterValue: "" }));
+                this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: shared, collectionFilterValue: "" }));
+                this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: favorites, collectionFilterValue: "" }));
+                this.props.dispatch(treePickerSearchActions.SET_TREE_PICKER_COLLECTION_FILTER({ pickerId: publicFavorites, collectionFilterValue: "" }));
+            }
+
+            componentWillUnmount() {
+                const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(this.props.pickerId);
+                // Release all the state, we don't need it to hang around forever.
+                this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: this.props.pickerId }));
+                this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: home }));
+                this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: shared }));
+                this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: favorites }));
+                this.props.dispatch(treePickerActions.RESET_TREE_PICKER({ pickerId: publicFavorites }));
+            }
+
+            render() {
+                const pickerId = this.props.pickerId;
+                const onProjectSearch = this.props.onProjectSearch;
+                const onCollectionFilter = this.props.onCollectionFilter;
+
+                const { home, shared, favorites, publicFavorites } = getProjectsTreePickerIds(pickerId);
+                const relatedTreePickers = getRelatedTreePickers(pickerId);
+                const p = {
+                    includeCollections: this.props.includeCollections,
+                    includeFiles: this.props.includeFiles,
+                    showSelection: this.props.showSelection,
+                    options: this.props.options,
+                    relatedTreePickers,
+                    disableActivation,
+                };
+                return <div className={this.props.classes.pickerHeight} >
+                    <span className={this.props.classes.searchFlex}>
+                        <SearchInput value="" label="Search Projects" selfClearProp='' onSearch={onProjectSearch} debounce={200} />
+                        <SearchInput value="" label="Filter Collections inside Projects" selfClearProp='' onSearch={onCollectionFilter} debounce={200} />
+                    </span>
+                    <div data-cy="projects-tree-home-tree-picker">
+                        <HomeTreePicker {...p} pickerId={home} />
+                    </div>
+                    <div data-cy="projects-tree-shared-tree-picker">
+                        <SharedTreePicker {...p} pickerId={shared} />
+                    </div>
+                    <div data-cy="projects-tree-public-favourites-tree-picker">
+                        <PublicFavoritesTreePicker {...p} pickerId={publicFavorites} />
+                    </div>
+                    <div data-cy="projects-tree-favourites-tree-picker">
+                        <FavoritesTreePicker {...p} pickerId={favorites} />
+                    </div>
+                </div >;
+            }
+        }));
+
 const getRelatedTreePickers = pipe(getProjectsTreePickerIds, values);
 const disableActivation = [SHARED_PROJECT_ID, FAVORITES_PROJECT_ID];
index 099a81289c58ef93974b66c6535397ac7b7b406f..24ea0b793baa264023dc097566d040dae6767676 100644 (file)
@@ -137,7 +137,7 @@ const FileInputComponent = connect()(
                         color='primary'
                         onClick={this.submit}>Ok</Button>
                 </DialogActions>
-            </Dialog>;
+            </Dialog >;
         }
 
     });