[ARVADOS-WORKBENCH2] updated: 1.2.0-569-g4af7aea

Git user git at public.curoverse.com
Tue Oct 9 10:37:39 EDT 2018


Summary of changes:
 src/index.tsx                                      |  15 +--
 src/models/tree.ts                                 |   2 +
 src/store/tree-picker/tree-picker-actions.ts       |  14 +++
 src/store/tree-picker/tree-picker-reducer.ts       |   4 +-
 .../projects-tree-picker/favorites-tree-picker.tsx |   4 +-
 ...picker.tsx => generic-projects-tree-picker.tsx} |  16 +--
 ...ojects-tree-picker.tsx => home-tree-picker.tsx} |   4 +-
 .../projects-tree-picker/projects-tree-picker.tsx  | 109 ++++-----------------
 ...ects-tree-picker.tsx => shared-tree-picker.tsx} |   6 +-
 src/views/workbench/workbench.tsx                  |  25 ++---
 10 files changed, 68 insertions(+), 131 deletions(-)
 copy src/views-components/projects-tree-picker/{projects-tree-picker.tsx => generic-projects-tree-picker.tsx} (89%)
 rename src/views-components/projects-tree-picker/{user-projects-tree-picker.tsx => home-tree-picker.tsx} (82%)
 rename src/views-components/projects-tree-picker/{shared-projects-tree-picker.tsx => shared-tree-picker.tsx} (73%)

       via  4af7aea9d89d1775a79288cb9433e0ec9e1176e4 (commit)
      from  22b21c3a28e0ef59e10168fab5aa633cc25cbab4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 4af7aea9d89d1775a79288cb9433e0ec9e1176e4
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Oct 9 16:37:18 2018 +0200

    Create basic cumulative projects picker
    
    Feature #13862
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --git a/src/index.tsx b/src/index.tsx
index 16cf86a..c1238a5 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -43,7 +43,7 @@ import { trashedCollectionActionSet } from '~/views-components/context-menu/acti
 import { ContainerRequestState } from '~/models/container-request';
 import { MountKind } from '~/models/mount-types';
 import { receiveTreePickerData, loadUserProject } from '~/store/tree-picker/tree-picker-actions';
-import { loadProject, loadCollection, initUserProject, initSharedProject, initFavoritesProject } from './store/tree-picker/tree-picker-actions';
+import { loadProject, loadCollection, initUserProject, initSharedProject, initFavoritesProject, initProjectsTreePicker } from './store/tree-picker/tree-picker-actions';
 import { ResourceKind } from '~/models/resource';
 
 const getBuildNumber = () => "BN-" + (process.env.REACT_APP_BUILD_NUMBER || "dev");
@@ -117,15 +117,10 @@ const initListener = (history: History, store: RootStore, services: ServiceRepos
             await store.dispatch(loadWorkbench());
             addRouteChangeHandlers(history, store);
             // createEnumCollectorWorkflow(services);
-            store.dispatch(initUserProject('testPicker1'));
-            store.dispatch(initUserProject('testPicker2'));
-            store.dispatch(initUserProject('testPicker3'));
-            store.dispatch(initSharedProject('testPicker4'));
-            store.dispatch(initSharedProject('testPicker5'));
-            store.dispatch(initSharedProject('testPicker6'));
-            store.dispatch(initFavoritesProject('testPicker7'));
-            store.dispatch(initFavoritesProject('testPicker8'));
-            store.dispatch(initFavoritesProject('testPicker9'));
+            store.dispatch(initProjectsTreePicker('testPicker1'));
+            store.dispatch(initProjectsTreePicker('testPicker2'));
+            store.dispatch(initProjectsTreePicker('testPicker3'));
+            
             // await store.dispatch(loadCollection(
             //     'c97qk-4zz18-9sn8ygaf62chkkd',
             //     'testPicker',
diff --git a/src/models/tree.ts b/src/models/tree.ts
index 69d2e93..cce27b1 100644
--- a/src/models/tree.ts
+++ b/src/models/tree.ts
@@ -109,6 +109,8 @@ export const mapIdsToNodes = (ids: string[]) => <T>(tree: Tree<T>) =>
 export const activateNode = (id: string) => <T>(tree: Tree<T>) =>
     mapTree(node => node.id === id ? { ...node, active: true } : { ...node, active: false })(tree);
 
+export const deactivateNode = <T>(tree: Tree<T>) =>
+    mapTree(node => node.active ? { ...node, active: false } : node)(tree);
 
 export const expandNode = (...ids: string[]) => <T>(tree: Tree<T>) =>
     mapTree(node => ids.some(id => id === node.id) ? { ...node, expanded: true } : node)(tree);
diff --git a/src/store/tree-picker/tree-picker-actions.ts b/src/store/tree-picker/tree-picker-actions.ts
index 41ee62f..06f73c3 100644
--- a/src/store/tree-picker/tree-picker-actions.ts
+++ b/src/store/tree-picker/tree-picker-actions.ts
@@ -18,6 +18,7 @@ export const treePickerActions = unionize({
     LOAD_TREE_PICKER_NODE_SUCCESS: ofType<{ id: string, nodes: Array<TreeNode<any>>, pickerId: string }>(),
     TOGGLE_TREE_PICKER_NODE_COLLAPSE: ofType<{ id: string, pickerId: string }>(),
     ACTIVATE_TREE_PICKER_NODE: ofType<{ id: string, pickerId: string }>(),
+    DEACTIVATE_TREE_PICKER_NODE: ofType<{ pickerId: string }>(),
     TOGGLE_TREE_PICKER_NODE_SELECTION: ofType<{ id: string, pickerId: string }>(),
     EXPAND_TREE_PICKER_NODES: ofType<{ ids: string[], pickerId: string }>(),
     RESET_TREE_PICKER: ofType<{ pickerId: string }>()
@@ -25,6 +26,19 @@ export const treePickerActions = unionize({
 
 export type TreePickerAction = UnionOf<typeof treePickerActions>;
 
+export const getProjectsTreePickerIds = (pickerId: string) => ({
+    home: `${pickerId}_home`,
+    shared: `${pickerId}_shared`,
+    favorites: `${pickerId}_favorites`,
+});
+export const initProjectsTreePicker = (pickerId: string) => 
+async (dispatch: Dispatch, _: () => RootState, services: ServiceRepository) => {
+    const {home, shared, favorites} = getProjectsTreePickerIds(pickerId);
+    dispatch<any>(initUserProject(home));
+    dispatch<any>(initSharedProject(shared));
+    dispatch<any>(initFavoritesProject(favorites));
+};
+
 interface ReceiveTreePickerDataParams<T> {
     data: T[];
     extractNodeData: (value: T) => { id: string, value: T, status?: TreeNodeStatus };
diff --git a/src/store/tree-picker/tree-picker-reducer.ts b/src/store/tree-picker/tree-picker-reducer.ts
index 69c4905..2df567e 100644
--- a/src/store/tree-picker/tree-picker-reducer.ts
+++ b/src/store/tree-picker/tree-picker-reducer.ts
@@ -2,7 +2,7 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import { createTree, TreeNode, setNode, Tree, TreeNodeStatus, setNodeStatus, expandNode } from '~/models/tree';
+import { createTree, TreeNode, setNode, Tree, TreeNodeStatus, setNodeStatus, expandNode, deactivateNode } from '~/models/tree';
 import { TreePicker } from "./tree-picker";
 import { treePickerActions, TreePickerAction } from "./tree-picker-actions";
 import { compose } from "redux";
@@ -18,6 +18,8 @@ export const treePickerReducer = (state: TreePicker = {}, action: TreePickerActi
             updateOrCreatePicker(state, pickerId, toggleNodeCollapse(id)),
         ACTIVATE_TREE_PICKER_NODE: ({ id, pickerId }) =>
             updateOrCreatePicker(state, pickerId, activateNode(id)),
+        DEACTIVATE_TREE_PICKER_NODE: ({ pickerId }) =>
+            updateOrCreatePicker(state, pickerId, deactivateNode),
         TOGGLE_TREE_PICKER_NODE_SELECTION: ({ id, pickerId }) =>
             updateOrCreatePicker(state, pickerId, toggleNodeSelection(id)),
         RESET_TREE_PICKER: ({ pickerId }) =>
diff --git a/src/views-components/projects-tree-picker/favorites-tree-picker.tsx b/src/views-components/projects-tree-picker/favorites-tree-picker.tsx
index 74cb16a..0970406 100644
--- a/src/views-components/projects-tree-picker/favorites-tree-picker.tsx
+++ b/src/views-components/projects-tree-picker/favorites-tree-picker.tsx
@@ -3,12 +3,12 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { connect } from 'react-redux';
-import { ProjectsTreePicker, ProjectsTreePickerProps } from '~/views-components/projects-tree-picker/projects-tree-picker';
+import { ProjectsTreePicker, ProjectsTreePickerProps } from '~/views-components/projects-tree-picker/generic-projects-tree-picker';
 import { Dispatch } from 'redux';
 import { FavoriteIcon } from '~/components/icon/icon';
 import { loadFavoritesProject } from '~/store/tree-picker/tree-picker-actions';
 
-export const FavoritesProjectsTreePicker = connect(() => ({
+export const FavoritesTreePicker = connect(() => ({
     rootItemIcon: FavoriteIcon,
 }), (dispatch: Dispatch): Pick<ProjectsTreePickerProps, 'loadRootItem'> => ({
     loadRootItem: (_, pickerId, includeCollections, includeFiles) => {
diff --git a/src/views-components/projects-tree-picker/projects-tree-picker.tsx b/src/views-components/projects-tree-picker/generic-projects-tree-picker.tsx
similarity index 89%
copy from src/views-components/projects-tree-picker/projects-tree-picker.tsx
copy to src/views-components/projects-tree-picker/generic-projects-tree-picker.tsx
index be030ef..1ddbe3a 100644
--- a/src/views-components/projects-tree-picker/projects-tree-picker.tsx
+++ b/src/views-components/projects-tree-picker/generic-projects-tree-picker.tsx
@@ -21,7 +21,7 @@ export interface ProjectsTreePickerRootItem {
     name: string;
 }
 
-type ProjectsTreePickerItem = ProjectsTreePickerRootItem | GroupContentsResource | CollectionDirectory | CollectionFile;
+export type ProjectsTreePickerItem = ProjectsTreePickerRootItem | GroupContentsResource | CollectionDirectory | CollectionFile;
 type PickedTreePickerProps = Pick<TreePickerProps<ProjectsTreePickerItem>, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen' | 'toggleItemSelection'>;
 
 export interface ProjectsTreePickerDataProps {
@@ -32,20 +32,20 @@ export interface ProjectsTreePickerDataProps {
     loadRootItem: (item: TreeItem<ProjectsTreePickerRootItem>, pickerId: string, includeCollections?: boolean, inlcudeFiles?: boolean) => void;
 }
 
-export interface ProjectsTreePickerActionProps {
-}
-
-export type ProjectsTreePickerProps = ProjectsTreePickerDataProps & ProjectsTreePickerActionProps;
+export type ProjectsTreePickerProps = ProjectsTreePickerDataProps & Partial<PickedTreePickerProps>;
 
 const mapStateToProps = (_: any, { pickerId, rootItemIcon }: ProjectsTreePickerProps) => ({
     render: renderTreeItem(rootItemIcon),
     pickerId,
 });
 
-const mapDispatchToProps = (dispatch: Dispatch, { loadRootItem, includeCollections, includeFiles }: ProjectsTreePickerProps): PickedTreePickerProps => ({
+const mapDispatchToProps = (dispatch: Dispatch, { loadRootItem, includeCollections, includeFiles, ...props }: ProjectsTreePickerProps): PickedTreePickerProps => ({
     onContextMenu: () => { return; },
-    toggleItemActive: (_, { id }, pickerId) => {
-        dispatch(treePickerActions.ACTIVATE_TREE_PICKER_NODE({ id, pickerId }));
+    toggleItemActive: (event, item, pickerId) => {
+        dispatch(treePickerActions.ACTIVATE_TREE_PICKER_NODE({ id: item.id, pickerId }));
+        if (props.toggleItemActive) {
+            props.toggleItemActive(event, item, pickerId);
+        }
     },
     toggleItemOpen: (_, item, pickerId) => {
         const { id, data, status } = item;
diff --git a/src/views-components/projects-tree-picker/user-projects-tree-picker.tsx b/src/views-components/projects-tree-picker/home-tree-picker.tsx
similarity index 82%
rename from src/views-components/projects-tree-picker/user-projects-tree-picker.tsx
rename to src/views-components/projects-tree-picker/home-tree-picker.tsx
index 10a0b20..45f0b5c 100644
--- a/src/views-components/projects-tree-picker/user-projects-tree-picker.tsx
+++ b/src/views-components/projects-tree-picker/home-tree-picker.tsx
@@ -3,12 +3,12 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { connect } from 'react-redux';
-import { ProjectsTreePicker, ProjectsTreePickerProps } from '~/views-components/projects-tree-picker/projects-tree-picker';
+import { ProjectsTreePicker, ProjectsTreePickerProps } from '~/views-components/projects-tree-picker/generic-projects-tree-picker';
 import { Dispatch } from 'redux';
 import { loadUserProject } from '~/store/tree-picker/tree-picker-actions';
 import { ProjectIcon } from '~/components/icon/icon';
 
-export const UserProjectsTreePicker = connect(() => ({
+export const HomeTreePicker = connect(() => ({
     rootItemIcon: ProjectIcon,
 }), (dispatch: Dispatch): Pick<ProjectsTreePickerProps, 'loadRootItem'> => ({
     loadRootItem: (_, pickerId, includeCollections, includeFiles) => {
diff --git a/src/views-components/projects-tree-picker/projects-tree-picker.tsx b/src/views-components/projects-tree-picker/projects-tree-picker.tsx
index be030ef..7982813 100644
--- a/src/views-components/projects-tree-picker/projects-tree-picker.tsx
+++ b/src/views-components/projects-tree-picker/projects-tree-picker.tsx
@@ -2,97 +2,28 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as React from "react";
-import { Dispatch } from "redux";
-import { connect } from "react-redux";
-import { TreeItem, TreeItemStatus } from '~/components/tree/tree';
-import { ProjectResource } from "~/models/project";
-import { treePickerActions } from "~/store/tree-picker/tree-picker-actions";
-import { ListItemTextIcon } from "~/components/list-item-text-icon/list-item-text-icon";
-import { ProjectIcon, InputIcon, IconType, CollectionIcon } from '~/components/icon/icon';
-import { loadProject, loadCollection } from '~/store/tree-picker/tree-picker-actions';
-import { GroupContentsResource } from '~/services/groups-service/groups-service';
-import { CollectionDirectory, CollectionFile, CollectionFileType } from '~/models/collection-file';
-import { ResourceKind } from '~/models/resource';
-import { TreePickerProps, TreePicker } from "~/views-components/tree-picker/tree-picker";
-
-export interface ProjectsTreePickerRootItem {
-    id: string;
-    name: string;
-}
-
-type ProjectsTreePickerItem = ProjectsTreePickerRootItem | GroupContentsResource | CollectionDirectory | CollectionFile;
-type PickedTreePickerProps = Pick<TreePickerProps<ProjectsTreePickerItem>, 'onContextMenu' | 'toggleItemActive' | 'toggleItemOpen' | 'toggleItemSelection'>;
-
-export interface ProjectsTreePickerDataProps {
+import * as React from 'react';
+import { Dispatch } from 'redux';
+import { connect } from 'react-redux';
+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, treePickerActions } from '~/store/tree-picker/tree-picker-actions';
+import { TreeItem } from '~/components/tree/tree';
+import { ProjectsTreePickerItem } from './generic-projects-tree-picker';
+
+export interface ProjectsTreePickerProps {
     pickerId: string;
     includeCollections?: boolean;
     includeFiles?: boolean;
-    rootItemIcon: IconType;
-    loadRootItem: (item: TreeItem<ProjectsTreePickerRootItem>, pickerId: string, includeCollections?: boolean, inlcudeFiles?: boolean) => void;
-}
-
-export interface ProjectsTreePickerActionProps {
+    toggleItemActive?: (event: React.MouseEvent<HTMLElement>, item: TreeItem<ProjectsTreePickerItem>, pickerId: string) => void;
 }
 
-export type ProjectsTreePickerProps = ProjectsTreePickerDataProps & ProjectsTreePickerActionProps;
-
-const mapStateToProps = (_: any, { pickerId, rootItemIcon }: ProjectsTreePickerProps) => ({
-    render: renderTreeItem(rootItemIcon),
-    pickerId,
-});
-
-const mapDispatchToProps = (dispatch: Dispatch, { loadRootItem, includeCollections, includeFiles }: ProjectsTreePickerProps): PickedTreePickerProps => ({
-    onContextMenu: () => { return; },
-    toggleItemActive: (_, { id }, pickerId) => {
-        dispatch(treePickerActions.ACTIVATE_TREE_PICKER_NODE({ id, pickerId }));
-    },
-    toggleItemOpen: (_, item, pickerId) => {
-        const { id, data, status } = item;
-        if (status === TreeItemStatus.INITIAL) {
-            if ('kind' in data) {
-                dispatch<any>(
-                    data.kind === ResourceKind.COLLECTION
-                        ? loadCollection(id, pickerId)
-                        : loadProject({ id, pickerId, includeCollections, includeFiles })
-                );
-            } else if (!('type' in data) && loadRootItem) {
-                loadRootItem(item as TreeItem<ProjectsTreePickerRootItem>, pickerId, includeCollections, includeFiles);
-            }
-        } else if (status === TreeItemStatus.LOADED) {
-            dispatch(treePickerActions.TOGGLE_TREE_PICKER_NODE_COLLAPSE({ id, pickerId }));
-        }
-    },
-    toggleItemSelection: (_, { id }, pickerId) => {
-        dispatch<any>(treePickerActions.TOGGLE_TREE_PICKER_NODE_SELECTION({ id, pickerId }));
-    },
-});
-
-export const ProjectsTreePicker = connect(mapStateToProps, mapDispatchToProps)(TreePicker);
-
-const getProjectPickerIcon = ({ data }: TreeItem<ProjectsTreePickerItem>, rootIcon: IconType): IconType => {
-    if ('kind' in data) {
-        switch (data.kind) {
-            case ResourceKind.COLLECTION:
-                return CollectionIcon;
-            default:
-                return ProjectIcon;
-        }
-    } else if ('type' in data) {
-        switch (data.type) {
-            case CollectionFileType.FILE:
-                return InputIcon;
-            default:
-                return ProjectIcon;
-        }
-    } else {
-        return rootIcon;
-    }
-};
-
-const renderTreeItem = (rootItemIcon: IconType) => (item: TreeItem<ProjectResource>) =>
-    <ListItemTextIcon
-        icon={getProjectPickerIcon(item, rootItemIcon)}
-        name={item.data.name}
-        isActive={item.active}
-        hasMargin={true} />;
+export const ProjectsTreePicker =  ({ pickerId, ...props }: ProjectsTreePickerProps) => {
+    const { home, shared, favorites } = getProjectsTreePickerIds(pickerId);
+    return <div>
+        <HomeTreePicker pickerId={home} {...props} />
+        <SharedTreePicker pickerId={shared} {...props} />
+        <FavoritesTreePicker pickerId={favorites} {...props} />
+    </div>;
+    };
diff --git a/src/views-components/projects-tree-picker/shared-projects-tree-picker.tsx b/src/views-components/projects-tree-picker/shared-tree-picker.tsx
similarity index 73%
rename from src/views-components/projects-tree-picker/shared-projects-tree-picker.tsx
rename to src/views-components/projects-tree-picker/shared-tree-picker.tsx
index 6a05c2a..a986b1b 100644
--- a/src/views-components/projects-tree-picker/shared-projects-tree-picker.tsx
+++ b/src/views-components/projects-tree-picker/shared-tree-picker.tsx
@@ -3,12 +3,12 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { connect } from 'react-redux';
-import { ProjectsTreePicker, ProjectsTreePickerProps } from '~/views-components/projects-tree-picker/projects-tree-picker';
+import { ProjectsTreePicker, ProjectsTreePickerProps } from '~/views-components/projects-tree-picker/generic-projects-tree-picker';
 import { Dispatch } from 'redux';
 import { ShareMeIcon } from '~/components/icon/icon';
-import { loadProject } from '../../store/tree-picker/tree-picker-actions';
+import { loadProject } from '~/store/tree-picker/tree-picker-actions';
 
-export const SharedProjectsTreePicker = connect(() => ({
+export const SharedTreePicker = connect(() => ({
     rootItemIcon: ShareMeIcon,
 }), (dispatch: Dispatch): Pick<ProjectsTreePickerProps, 'loadRootItem'> => ({
     loadRootItem: (_, pickerId, includeCollections, includeFiles) => {
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 6c02dd2..dd68cb8 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -41,14 +41,10 @@ import { SharedWithMePanel } from '~/views/shared-with-me-panel/shared-with-me-p
 import { RunProcessPanel } from '~/views/run-process-panel/run-process-panel';
 import SplitterLayout from 'react-splitter-layout';
 import { WorkflowPanel } from '~/views/workflow-panel/workflow-panel';
-import { TreePicker } from '../../views-components/tree-picker/tree-picker';
-import { noop } from 'lodash';
-import { TreeItem } from '~/components/tree/tree';
-import { GroupContentsResource } from '~/services/groups-service/groups-service';
+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 { ProjectsTreePicker } from '~/views-components/projects-tree-picker/projects-tree-picker';
-import { UserProjectsTreePicker } from '~/views-components/projects-tree-picker/user-projects-tree-picker';
-import { SharedProjectsTreePicker } from '~/views-components/projects-tree-picker/shared-projects-tree-picker';
-import { FavoritesProjectsTreePicker } from '../../views-components/projects-tree-picker/favorites-tree-picker';
 
 type CssRules = 'root' | 'container' | 'splitter' | 'asidePanel' | 'contentWrapper' | 'content';
 
@@ -96,15 +92,12 @@ export const WorkbenchPanel =
                             <MainContentBar />
                         </Grid>
                         <Grid item xs className={classes.content}>
-                            <UserProjectsTreePicker pickerId='testPicker1'/>
-                            <UserProjectsTreePicker pickerId='testPicker2' includeCollections/>
-                            <UserProjectsTreePicker pickerId='testPicker3' includeCollections includeFiles/>
-                            <SharedProjectsTreePicker pickerId='testPicker4'/>
-                            <SharedProjectsTreePicker pickerId='testPicker5' includeCollections/>
-                            <SharedProjectsTreePicker pickerId='testPicker6' includeCollections includeFiles/>
-                            <FavoritesProjectsTreePicker pickerId='testPicker7'/>
-                            <FavoritesProjectsTreePicker pickerId='testPicker8' includeCollections/>
-                            <FavoritesProjectsTreePicker pickerId='testPicker9' includeCollections includeFiles/>
+                            <p>Projects only</p>
+                            <ProjectsTreePicker pickerId="testPicker1"/>
+                            <p>Collections included</p>
+                            <ProjectsTreePicker pickerId="testPicker2" includeCollections/>
+                            <p>Files included</p>
+                            <ProjectsTreePicker pickerId="testPicker3" includeCollections includeFiles toggleItemActive={(...args: any[]) => console.log(args)}/>
                             <Switch>
                                 <Route path={Routes.PROJECTS} component={ProjectPanel} />
                                 <Route path={Routes.COLLECTIONS} component={CollectionPanel} />

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list