[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