[ARVADOS-WORKBENCH2] created: 1.1.4-118-g9692547

Git user git at public.curoverse.com
Sun Jun 24 18:43:55 EDT 2018


        at  969254757ab4c21840faedf2bd1e4297c35203ac (commit)


commit 969254757ab4c21840faedf2bd1e4297c35203ac
Author: Daniel Kos <daniel.kos at contractors.roche.com>
Date:   Fri Jun 22 14:11:16 2018 +0200

    Added data selector for workbench data explorer
    
    Feature #13666
    
    Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos at contractors.roche.com>

diff --git a/src/index.tsx b/src/index.tsx
index cf1610f..28f8300 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -21,6 +21,8 @@ const history = createBrowserHistory();
 const store = configureStore({
     projects: [
     ],
+    collections: [
+    ],
     router: {
         location: null
     },
diff --git a/src/models/resource.ts b/src/models/resource.ts
index 39b4e91..4c198fb 100644
--- a/src/models/resource.ts
+++ b/src/models/resource.ts
@@ -7,3 +7,21 @@ export interface Resource {
     href: string;
     kind: string;
 }
+
+export enum ResourceKind {
+    PROJECT = "project",
+    COLLECTION = "collection",
+    PIPELINE = "pipeline",
+    LEVEL_UP = "levelup",
+    UNKNOWN = "unknown"
+}
+
+export function getResourceKind(itemKind: string) {
+    switch (itemKind) {
+        case "arvados#project": return ResourceKind.PROJECT;
+        case "arvados#collection": return ResourceKind.COLLECTION;
+        case "arvados#pipeline": return ResourceKind.PIPELINE;
+        default:
+            return ResourceKind.UNKNOWN;
+    }
+}
diff --git a/src/store/project/project-reducer.ts b/src/store/project/project-reducer.ts
index 4f7545f..2c74eb2 100644
--- a/src/store/project/project-reducer.ts
+++ b/src/store/project/project-reducer.ts
@@ -22,8 +22,21 @@ export function findTreeItem<T>(tree: Array<TreeItem<T>>, itemId: string): TreeI
     return item;
 }
 
+export function getActiveTreeItem<T>(tree: Array<TreeItem<T>>): TreeItem<T> | undefined {
+    let item;
+    for (const t of tree) {
+        item = t.active
+            ? t
+            : getActiveTreeItem(t.items ? t.items : []);
+        if (item) {
+            break;
+        }
+    }
+    return item;
+}
+
 export function getTreePath<T>(tree: Array<TreeItem<T>>, itemId: string): Array<TreeItem<T>> {
-    for(const item of tree){
+    for (const item of tree){
         if(item.id === itemId){
             return [item];
         } else {
diff --git a/src/store/store.ts b/src/store/store.ts
index 6b9c31f..6053e03 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -8,7 +8,7 @@ import thunkMiddleware from 'redux-thunk';
 import { History } from "history";
 import projectsReducer, { ProjectState } from "./project/project-reducer";
 import authReducer, { AuthState } from "./auth/auth-reducer";
-import collectionsReducer from "./collection/collection-reducer";
+import collectionsReducer, { CollectionState } from "./collection/collection-reducer";
 
 const composeEnhancers =
     (process.env.NODE_ENV === 'development' &&
@@ -18,6 +18,7 @@ const composeEnhancers =
 export interface RootState {
     auth: AuthState;
     projects: ProjectState;
+    collections: CollectionState;
     router: RouterState;
 }
 
diff --git a/src/views-components/data-explorer/data-explorer.tsx b/src/views-components/data-explorer/data-explorer.tsx
index c4de01a..4ba0f87 100644
--- a/src/views-components/data-explorer/data-explorer.tsx
+++ b/src/views-components/data-explorer/data-explorer.tsx
@@ -3,17 +3,17 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import * as React from 'react';
-import { Typography, Grid, Paper, Toolbar } from '@material-ui/core';
+import { Grid, Paper, Toolbar, Typography } from '@material-ui/core';
 import IconButton from '@material-ui/core/IconButton';
 import MoreVertIcon from "@material-ui/icons/MoreVert";
-import { formatFileSize, formatDate } from '../../common/formatters';
+import { formatDate, formatFileSize } from '../../common/formatters';
 import { DataItem } from './data-item';
-import { DataColumns } from "../../components/data-table/data-table";
+import DataTable, { DataColumns } from "../../components/data-table/data-table";
 import ContextMenu from "../../components/context-menu/context-menu";
 import ColumnSelector from "../../components/column-selector/column-selector";
-import DataTable from "../../components/data-table/data-table";
 import { mockAnchorFromMouseEvent } from "../../components/popover/helpers";
 import { DataColumn } from "../../components/data-table/data-column";
+import { ResourceKind } from "../../models/resource";
 
 export interface DataExplorerContextActions {
     onAddToFavourite: (dataIitem: DataItem) => void;
@@ -191,10 +191,12 @@ class DataExplorer extends React.Component<DataExplorerProps, DataExplorerState>
 
 const renderIcon = (dataItem: DataItem) => {
     switch (dataItem.type) {
-        case "arvados#group":
-            return <i className="fas fa-folder fa-lg" />;
-        case "arvados#groupList":
-            return <i className="fas fa-th fa-lg" />;
+        case ResourceKind.LEVEL_UP:
+            return <i className="icon-level-up" style={{fontSize: "1rem"}}/>;
+        case ResourceKind.PROJECT:
+            return <i className="fas fa-folder fa-lg"/>;
+        case ResourceKind.COLLECTION:
+            return <i className="fas fa-th fa-lg"/>;
         default:
             return <i />;
     }
diff --git a/src/views-components/data-explorer/data-item.ts b/src/views-components/data-explorer/data-item.ts
index 65e8f63..ebff77d 100644
--- a/src/views-components/data-explorer/data-item.ts
+++ b/src/views-components/data-explorer/data-item.ts
@@ -2,12 +2,26 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
+import { getResourceKind, Resource, ResourceKind } from "../../models/resource";
+
 export interface DataItem {
     uuid: string;
     name: string;
-    type: string;
+    type: ResourceKind;
+    url: string;
     owner: string;
     lastModified: string;
     fileSize?: number;
     status?: string;
 }
+
+function resourceToDataItem(r: Resource, kind?: ResourceKind) {
+    return {
+        uuid: r.uuid,
+        name: r.name,
+        type: kind ? kind : getResourceKind(r.kind),
+        owner: r.ownerUuid,
+        lastModified: r.modifiedAt
+    };
+}
+
diff --git a/src/views/data-explorer/data-explorer-selectors.ts b/src/views/data-explorer/data-explorer-selectors.ts
index 5f17037..73881fa 100644
--- a/src/views/data-explorer/data-explorer-selectors.ts
+++ b/src/views/data-explorer/data-explorer-selectors.ts
@@ -1,11 +1,54 @@
 import { TreeItem } from "../../components/tree/tree";
 import { Project } from "../../models/project";
 import { DataItem } from "../../views-components/data-explorer/data-item";
+import { findTreeItem } from "../../store/project/project-reducer";
+import { ResourceKind } from "../../models/resource";
+import { Collection } from "../../models/collection";
+
+
+export const projectExplorerItems = (projects: Array<TreeItem<Project>>, treeItemId: string, collections: Array<Collection>): DataItem[] => {
+    const dataItems: DataItem[] = [];
+
+    const treeItem = findTreeItem(projects, treeItemId);
+    if (treeItem) {
+        dataItems.push({
+            name: "..",
+            url: `/projects/${treeItem.data.ownerUuid}`,
+            type: ResourceKind.LEVEL_UP,
+            owner: treeItem.data.ownerUuid,
+            uuid: treeItem.data.uuid,
+            lastModified: treeItem.data.modifiedAt
+        });
+
+        if (treeItem.items) {
+            treeItem.items.forEach(p => {
+                const item = {
+                    name: p.data.name,
+                    type: ResourceKind.PROJECT,
+                    url: `/projects/${treeItem.data.uuid}`,
+                    owner: p.data.ownerUuid,
+                    uuid: p.data.uuid,
+                    lastModified: p.data.modifiedAt
+                } as DataItem;
+
+                dataItems.push(item);
+            });
+        }
+    }
+
+    collections.forEach(c => {
+        const item = {
+            name: c.name,
+            type: ResourceKind.COLLECTION,
+            url: `/collections/${c.uuid}`,
+            owner: c.ownerUuid,
+            uuid: c.uuid,
+            lastModified: c.modifiedAt
+        } as DataItem;
+
+        dataItems.push(item);
+    });
+
+    return dataItems;
+};
 
-export const mapProjectTreeItem = (item: TreeItem<Project>): DataItem => ({
-    name: item.data.name,
-    type: item.data.kind,
-    owner: item.data.ownerUuid,
-    lastModified: item.data.modifiedAt,
-    uuid: item.data.uuid
-});
diff --git a/src/views/data-explorer/data-explorer.tsx b/src/views/data-explorer/data-explorer.tsx
index f4ee36f..a667469 100644
--- a/src/views/data-explorer/data-explorer.tsx
+++ b/src/views/data-explorer/data-explorer.tsx
@@ -5,32 +5,35 @@
 import * as React from 'react';
 import { RouteComponentProps } from 'react-router';
 import { Project } from '../../models/project';
-import { ProjectState, findTreeItem } from '../../store/project/project-reducer';
+import { ProjectState } from '../../store/project/project-reducer';
 import { RootState } from '../../store/store';
 import { connect, DispatchProp } from 'react-redux';
 import { push } from 'react-router-redux';
-import projectActions from "../../store/project/project-action";
 import { DataColumns } from "../../components/data-table/data-table";
 import DataExplorer, { DataExplorerContextActions } from "../../views-components/data-explorer/data-explorer";
-import { mapProjectTreeItem } from "./data-explorer-selectors";
+import { projectExplorerItems } from "./data-explorer-selectors";
 import { DataItem } from "../../views-components/data-explorer/data-item";
+import { CollectionState } from "../../store/collection/collection-reducer";
+import { ResourceKind } from "../../models/resource";
+import projectActions from "../../store/project/project-action";
+import { getCollectionList } from "../../store/collection/collection-action";
 
 interface DataExplorerViewDataProps {
     projects: ProjectState;
+    collections: CollectionState;
 }
 
-type DataExplorerViewProps = DataExplorerViewDataProps & RouteComponentProps<{ name: string }> & DispatchProp;
+type DataExplorerViewProps = DataExplorerViewDataProps & RouteComponentProps<{ uuid: string }> & DispatchProp;
 type DataExplorerViewState = DataColumns<Project>;
 
 class DataExplorerView extends React.Component<DataExplorerViewProps, DataExplorerViewState> {
-
     render() {
-        const project = findTreeItem(this.props.projects, this.props.match.params.name);
-        const projectItems = project && project.items || [];
+        const treeItemId = this.props.match.params.uuid;
+        const items = projectExplorerItems(this.props.projects, treeItemId, this.props.collections);
         return (
             <DataExplorer
-                items={projectItems.map(mapProjectTreeItem)}
-                onItemClick={this.goToProject}
+                items={items}
+                onItemClick={this.goToItem}
                 contextActions={this.contextActions}
             />
         );
@@ -46,14 +49,19 @@ class DataExplorerView extends React.Component<DataExplorerViewProps, DataExplor
         onShare: console.log
     };
 
-    goToProject = (item: DataItem) => {
-        this.props.dispatch(push(`/project/${item}`));
-        this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM(item.uuid));
+    goToItem = (item: DataItem) => {
+        // FIXME: Unify project tree switch action
+        this.props.dispatch(push(item.url));
+        if (item.type === ResourceKind.PROJECT || item.type === ResourceKind.LEVEL_UP) {
+            this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM(item.uuid));
+        }
+        this.props.dispatch<any>(getCollectionList(item.uuid));
     }
 }
 
 export default connect(
     (state: RootState) => ({
-        projects: state.projects
+        projects: state.projects,
+        collections: state.collections
     })
 )(DataExplorerView);
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 41725b5..c981c90 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -20,6 +20,7 @@ import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
 import { Project } from "../../models/project";
 import { getTreePath } from '../../store/project/project-reducer';
 import DataExplorer from '../data-explorer/data-explorer';
+import { getCollectionList } from "../../store/collection/collection-action";
 
 const drawerWidth = 240;
 const appBarHeight = 102;
@@ -122,7 +123,6 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
         }
     };
 
-
     mainAppBarActions: MainAppBarActionProps = {
         onBreadcrumbClick: ({ itemId, status }: NavBreadcrumb) => {
             this.toggleProjectTreeItem(itemId, status);
@@ -141,6 +141,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
             this.props.dispatch<any>(getProjectList(itemId))
                 .then(() => this.openProjectItem(itemId));
         }
+        this.props.dispatch<any>(getCollectionList(itemId));
     }
 
     openProjectItem = (itemId: string) => {
@@ -183,7 +184,7 @@ class Workbench extends React.Component<WorkbenchProps, WorkbenchState> {
                 <main className={classes.contentWrapper}>
                     <div className={classes.content}>
                         <Switch>
-                            <Route path="/project/:name" component={DataExplorer} />
+                            <Route path="/project/:uuid" component={DataExplorer} />
                         </Switch>
                     </div>
                 </main>
diff --git a/tslint.json b/tslint.json
index 4845e4d..7f02975 100644
--- a/tslint.json
+++ b/tslint.json
@@ -12,7 +12,8 @@
     "no-debugger": false,
     "no-console": false,
     "no-shadowed-variable": false,
-    "semicolon": true
+    "semicolon": true,
+    "array-type": false
   },
   "linterOptions": {
     "exclude": [

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list