[ARVADOS-WORKBENCH2] updated: 1.1.4-166-g52cc3b9

Git user git at public.curoverse.com
Tue Jun 26 12:42:44 EDT 2018


Summary of changes:
 src/common/formatters.ts                           |   3 +-
 .../data-explorer/data-explorer.test.tsx           |   4 +-
 src/components/data-explorer/data-explorer.tsx     |  28 ++---
 src/components/data-table/data-column.ts           |   1 +
 src/components/data-table/data-table.test.tsx      |  18 ----
 src/components/data-table/data-table.tsx           |  31 +++---
 src/models/resource.ts                             |  24 ++++-
 src/services/auth-service/auth-service.ts          |   4 +
 .../collection-service/collection-service.ts       |   3 +-
 src/services/project-service/project-service.ts    |   3 +-
 src/store/collection/collection-reducer.test.ts    |   5 +-
 src/store/collection/collection-reducer.ts         |   2 +-
 src/store/navigation/navigation-action.ts          |  80 ++++++++++++++
 src/store/project/project-reducer.test.ts          | 115 +++++++++++----------
 src/store/project/project-reducer.ts               |  78 ++++++++++----
 src/store/store.ts                                 |   3 +-
 .../project-explorer/project-explorer-item.ts      |  24 -----
 .../project-tree/project-tree.test.tsx             |  16 +--
 src/views/project-panel/project-panel-item.ts      |  29 ++++++
 src/views/project-panel/project-panel-selectors.ts |  58 +++++++++++
 .../project-panel/project-panel.tsx}               |  92 +++++++++--------
 src/views/workbench/workbench.test.tsx             |  11 +-
 src/views/workbench/workbench.tsx                  | 104 +++++++------------
 tslint.json                                        |   4 +-
 24 files changed, 465 insertions(+), 275 deletions(-)
 create mode 100644 src/store/navigation/navigation-action.ts
 delete mode 100644 src/views-components/project-explorer/project-explorer-item.ts
 create mode 100644 src/views/project-panel/project-panel-item.ts
 create mode 100644 src/views/project-panel/project-panel-selectors.ts
 rename src/{views-components/project-explorer/project-explorer.tsx => views/project-panel/project-panel.tsx} (64%)

       via  52cc3b912c703c24bc90e67aaf24e8ad912d3ebf (commit)
       via  57357cac58b568e2ba1445af6a44eb089026b34e (commit)
       via  37eb0fb5a3f6c36b484fce5c2f6dacb3ce95eef5 (commit)
       via  95bc64c72fa9e7ede2cc235ee668ee2e8aa6a1f0 (commit)
       via  c3efa27ba09323568c2b7d2cd27911fe4937ccbc (commit)
       via  c3945a12b21445b157cfe3ea77f88134c670d88c (commit)
       via  2d06516661e4df961a586e3fd66c8e782332d18f (commit)
       via  afa829ac853b470517757951c51c6a8b1316f0f1 (commit)
       via  278f75bd896ee35887282f61e10bbeaf6471011d (commit)
       via  78915a29d2911b1c442920b614f3e48da9e567c2 (commit)
       via  3eaf143e04107bf25e15aaef4d1b4d5d7ef68f86 (commit)
       via  4beb141298fce3da40f07e1a0a08f29ac28dfd09 (commit)
       via  b0ea85a58cf15903e67c5a7161d7887b03af713e (commit)
       via  948bf5f1e58f1003630b3b564e813557d1f54d84 (commit)
       via  e9fe89a00d2aea95b7e6c5ecdbeb4f6a583070b1 (commit)
       via  5fd5db805554d3eddd46cc911a5108fbb74b3cfc (commit)
       via  6e44781d01db889030cc5f7819aa7f15fe837e19 (commit)
       via  969254757ab4c21840faedf2bd1e4297c35203ac (commit)
      from  2d31e440b94eca0f22b2968f30a48cfc825514f1 (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 52cc3b912c703c24bc90e67aaf24e8ad912d3ebf
Merge: 2d31e44 57357ca
Author: Michal Klobukowski <michal.klobukowski at contractors.roche.com>
Date:   Tue Jun 26 18:42:24 2018 +0200

    Merge branch 'master'
    
    Feature #13678
    
    Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski <michal.klobukowski at contractors.roche.com>

diff --cc src/components/data-table/data-table.test.tsx
index 77979af,726972e..b9d1125
--- a/src/components/data-table/data-table.test.tsx
+++ b/src/components/data-table/data-table.test.tsx
@@@ -97,26 -98,8 +97,8 @@@ describe("<DataTable />", () => 
          expect(dataTable.find(TableBody).find(TableCell).key()).toBe("column-1-key");
      });
  
-     it("shows information that items array is empty", () => {
-         const columns: DataColumns<string> = [
-             {
-                 name: "Column 1",
-                 render: () => <span />,
-                 selected: true
-             }
-         ];
-         const dataTable = mount(<DataTable
-             columns={columns}
-             items={[]}
-             onFiltersChange={jest.fn()}
-             onRowClick={jest.fn()}
-             onRowContextMenu={jest.fn()}
-             onSortToggle={jest.fn()} />);
-         expect(dataTable.find(Typography).text()).toBe("No items");
-     });
- 
      it("renders items", () => {
 -        const columns: Array<DataColumn<string>> = [
 +        const columns: DataColumns<string> = [
              {
                  name: "Column 1",
                  render: (item) => <Typography>{item}</Typography>,
diff --cc src/store/navigation/navigation-action.ts
index 0000000,0b4bcdf..b811f9a
mode 000000,100644..100644
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@@ -1,0 -1,63 +1,80 @@@
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+ 
+ import { Dispatch } from "redux";
+ import projectActions, { getProjectList } from "../project/project-action";
+ import { push } from "react-router-redux";
 -import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
++import { TreeItemStatus } from "../../components/tree/tree";
+ import { getCollectionList } from "../collection/collection-action";
+ import { findTreeItem } from "../project/project-reducer";
 -import { Project } from "../../models/project";
+ import { Resource, ResourceKind } from "../../models/resource";
+ import sidePanelActions from "../side-panel/side-panel-action";
++import dataExplorerActions from "../data-explorer/data-explorer-action";
++import { PROJECT_PANEL_ID } from "../../views/project-panel/project-panel";
++import { projectPanelItems } from "../../views/project-panel/project-panel-selectors";
++import { RootState } from "../store";
+ 
+ export const getResourceUrl = (resource: Resource): string => {
+     switch (resource.kind) {
+         case ResourceKind.LEVEL_UP: return `/projects/${resource.ownerUuid}`;
+         case ResourceKind.PROJECT: return `/projects/${resource.uuid}`;
+         case ResourceKind.COLLECTION: return `/collections/${resource.uuid}`;
+         default:
+             return "#";
+     }
+ };
+ 
+ export enum ItemMode {
+     BOTH,
+     OPEN,
+     ACTIVE
+ }
+ 
 -export const setProjectItem = (projects: Array<TreeItem<Project>>, itemId: string, itemKind: ResourceKind, itemMode: ItemMode) => (dispatch: Dispatch) => {
++export const setProjectItem = (itemId: string, itemKind = ResourceKind.PROJECT, itemMode = ItemMode.OPEN) =>
++    (dispatch: Dispatch, getState: () => RootState) => {
++        const { projects } = getState();
+ 
 -    const openProjectItem = (resource: Resource) => {
 -        if (itemMode === ItemMode.OPEN || itemMode === ItemMode.BOTH) {
 -            dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(resource.uuid));
++        let treeItem = findTreeItem(projects.items, itemId);
++        if (treeItem && itemKind === ResourceKind.LEVEL_UP) {
++            treeItem = findTreeItem(projects.items, treeItem.data.ownerUuid);
+         }
+ 
 -        if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
 -            dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(resource.uuid));
 -        }
++        if (treeItem) {
++            dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treeItem.data.uuid));
+ 
 -        dispatch(push(getResourceUrl({...resource, kind: itemKind})));
++            if (treeItem.status === TreeItemStatus.Loaded) {
++                dispatch<any>(openProjectItem(treeItem.data, itemKind, itemMode));
++            } else {
++                dispatch<any>(getProjectList(itemId))
++                    .then(() => dispatch<any>(openProjectItem(treeItem!.data, itemKind, itemMode)));
++            }
++            if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
++                dispatch<any>(getCollectionList(itemId));
++            }
++        }
+     };
+ 
 -    let treeItem = findTreeItem(projects, itemId);
 -    if (treeItem && itemKind === ResourceKind.LEVEL_UP) {
 -        treeItem = findTreeItem(projects, treeItem.data.ownerUuid);
 -    }
++const openProjectItem = (resource: Resource, itemKind: ResourceKind, itemMode: ItemMode) =>
++    (dispatch: Dispatch, getState: () => RootState) => {
+ 
 -    if (treeItem) {
 -        dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treeItem.data.uuid));
++        const { collections, projects } = getState();
+ 
 -        if (treeItem.status === TreeItemStatus.Loaded) {
 -            openProjectItem(treeItem.data);
 -        } else {
 -            dispatch<any>(getProjectList(itemId))
 -                .then(() => openProjectItem(treeItem!.data));
++        if (itemMode === ItemMode.OPEN || itemMode === ItemMode.BOTH) {
++            dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(resource.uuid));
+         }
++
+         if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
 -            dispatch<any>(getCollectionList(itemId));
++            dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(resource.uuid));
+         }
 -    }
 -};
++
++        dispatch(push(getResourceUrl({ ...resource, kind: itemKind })));
++        dispatch(dataExplorerActions.SET_ITEMS({
++            id: PROJECT_PANEL_ID,
++            items: projectPanelItems(
++                projects.items,
++                resource.uuid,
++                collections
++            )
++        }));
++    };
diff --cc src/store/store.ts
index 7092c1d,40b24a0..68c5d82
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@@ -10,8 -10,7 +10,8 @@@ import { History } from "history"
  import projectsReducer, { ProjectState } from "./project/project-reducer";
  import sidePanelReducer, { SidePanelState } from './side-panel/side-panel-reducer';
  import authReducer, { AuthState } from "./auth/auth-reducer";
- import collectionsReducer from "./collection/collection-reducer";
 +import dataExplorerReducer, { DataExplorerState } from './data-explorer/data-explorer-reducer';
+ import collectionsReducer, { CollectionState } from "./collection/collection-reducer";
  
  const composeEnhancers =
      (process.env.NODE_ENV === 'development' &&
@@@ -21,8 -20,8 +21,9 @@@
  export interface RootState {
      auth: AuthState;
      projects: ProjectState;
+     collections: CollectionState;
      router: RouterState;
 +    dataExplorer: DataExplorerState;
      sidePanel: SidePanelState;
  }
  
diff --cc src/views/project-panel/project-panel-item.ts
index 0000000,4fa3d3d..e0eb84f
mode 000000,100644..100644
--- a/src/views/project-panel/project-panel-item.ts
+++ b/src/views/project-panel/project-panel-item.ts
@@@ -1,0 -1,27 +1,29 @@@
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+ 
++import { TreeItem } from "../../components/tree/tree";
++import { Project } from "../../models/project";
+ import { getResourceKind, Resource, ResourceKind } from "../../models/resource";
+ 
 -export interface ProjectExplorerItem {
++export interface ProjectPanelItem {
+     uuid: string;
+     name: string;
+     kind: ResourceKind;
+     url: string;
+     owner: string;
+     lastModified: string;
+     fileSize?: number;
+     status?: string;
+ }
+ 
+ function resourceToDataItem(r: Resource, kind?: ResourceKind) {
+     return {
+         uuid: r.uuid,
+         name: r.name,
+         kind: kind ? kind : getResourceKind(r.kind),
+         owner: r.ownerUuid,
+         lastModified: r.modifiedAt
+     };
+ }
+ 
diff --cc src/views/project-panel/project-panel-selectors.ts
index 0000000,83bfd60..5571e91
mode 000000,100644..100644
--- a/src/views/project-panel/project-panel-selectors.ts
+++ b/src/views/project-panel/project-panel-selectors.ts
@@@ -1,0 -1,58 +1,58 @@@
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+ 
+ import { TreeItem } from "../../components/tree/tree";
+ import { Project } from "../../models/project";
+ import { findTreeItem } from "../../store/project/project-reducer";
+ import { ResourceKind } from "../../models/resource";
+ import { Collection } from "../../models/collection";
+ import { getResourceUrl } from "../../store/navigation/navigation-action";
 -import { ProjectExplorerItem } from "../../views-components/project-explorer/project-explorer-item";
++import { ProjectPanelItem } from "./project-panel-item";
+ 
 -export const projectExplorerItems = (projects: Array<TreeItem<Project>>, treeItemId: string, collections: Array<Collection>): ProjectExplorerItem[] => {
 -    const dataItems: ProjectExplorerItem[] = [];
++export const projectPanelItems = (projects: Array<TreeItem<Project>>, treeItemId: string, collections: Array<Collection>): ProjectPanelItem[] => {
++    const dataItems: ProjectPanelItem[] = [];
+ 
+     const treeItem = findTreeItem(projects, treeItemId);
+     if (treeItem) {
+         dataItems.push({
+             name: "..",
+             url: getResourceUrl(treeItem.data),
+             kind: ResourceKind.LEVEL_UP,
+             owner: "",
+             uuid: treeItem.data.uuid,
+             lastModified: ""
+         });
+ 
+         if (treeItem.items) {
+             treeItem.items.forEach(p => {
+                 const item = {
+                     name: p.data.name,
+                     kind: ResourceKind.PROJECT,
+                     url: getResourceUrl(treeItem.data),
+                     owner: p.data.ownerUuid,
+                     uuid: p.data.uuid,
+                     lastModified: p.data.modifiedAt
 -                } as ProjectExplorerItem;
++                } as ProjectPanelItem;
+ 
+                 dataItems.push(item);
+             });
+         }
+     }
+ 
+     collections.forEach(c => {
+         const item = {
+             name: c.name,
+             kind: ResourceKind.COLLECTION,
+             url: getResourceUrl(c),
+             owner: c.ownerUuid,
+             uuid: c.uuid,
+             lastModified: c.modifiedAt
 -        } as ProjectExplorerItem;
++        } as ProjectPanelItem;
+ 
+         dataItems.push(item);
+     });
+ 
+     return dataItems;
+ };
+ 
diff --cc src/views/project-panel/project-panel.tsx
index 16f670c,df9721f..dbff20e
--- a/src/views/project-panel/project-panel.tsx
+++ b/src/views/project-panel/project-panel.tsx
@@@ -3,78 -3,105 +3,84 @@@
  // SPDX-License-Identifier: AGPL-3.0
  
  import * as React from 'react';
- import { ProjectExplorerItem } from './project-explorer-item';
 -import { RouteComponentProps } from 'react-router';
 -import { ProjectState } from '../../store/project/project-reducer';
 -import { RootState } from '../../store/store';
 -import { connect, DispatchProp } from 'react-redux';
 -import { CollectionState } from "../../store/collection/collection-reducer";
 -import { ItemMode, setProjectItem } from "../../store/navigation/navigation-action";
 -import ProjectExplorer from "../../views-components/project-explorer/project-explorer";
 -import { projectExplorerItems } from "./project-panel-selectors";
 -import { ProjectExplorerItem } from "../../views-components/project-explorer/project-explorer-item";
 -import { Button, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
 -import { DataColumn, SortDirection } from '../../components/data-table/data-column';
++import { ProjectPanelItem } from './project-panel-item';
 +import { Grid, Typography, Button, Toolbar, StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core';
 +import { formatDate, formatFileSize } from '../../common/formatters';
- import DataExplorer from '../data-explorer/data-explorer';
- import { DataColumn } from '../../components/data-table/data-column';
++import DataExplorer from "../../views-components/data-explorer/data-explorer";
++import { DataColumn, toggleSortDirection } from '../../components/data-table/data-column';
  import { DataTableFilterItem } from '../../components/data-table-filters/data-table-filters';
 +import { ContextMenuAction } from '../../components/context-menu/context-menu';
 +import { DispatchProp, connect } from 'react-redux';
 +import actions from "../../store/data-explorer/data-explorer-action";
++import { setProjectItem } from "../../store/navigation/navigation-action";
 +import { DataColumns } from '../../components/data-table/data-table';
++import { ResourceKind } from "../../models/resource";
  
- export const PROJECT_EXPLORER_ID = "projectExplorer";
- class ProjectExplorer extends React.Component<DispatchProp & WithStyles<CssRules>> {
 -interface ProjectPanelDataProps {
 -    projects: ProjectState;
 -    collections: CollectionState;
 -}
++export const PROJECT_PANEL_ID = "projectPanel";
++class ProjectPanel extends React.Component<DispatchProp & WithStyles<CssRules>> {
 +    render() {
 +        return <div>
 +            <div className={this.props.classes.toolbar}>
 +                <Button color="primary" variant="raised" className={this.props.classes.button}>
 +                    Create a collection
 +                </Button>
 +                <Button color="primary" variant="raised" className={this.props.classes.button}>
 +                    Run a process
 +                </Button>
 +                <Button color="primary" variant="raised" className={this.props.classes.button}>
 +                    Create a project
 +                </Button>
 +            </div>
 +            <DataExplorer
-                 id={PROJECT_EXPLORER_ID}
++                id={PROJECT_PANEL_ID}
 +                contextActions={contextMenuActions}
 +                onColumnToggle={this.toggleColumn}
 +                onFiltersChange={this.changeFilters}
-                 onRowClick={console.log}
++                onRowClick={this.openProject}
 +                onSortToggle={this.toggleSort}
 +                onSearch={this.search}
 +                onContextAction={this.executeAction}
 +                onChangePage={this.changePage}
 +                onChangeRowsPerPage={this.changeRowsPerPage} />;
 +        </div>;
 +    }
  
 -type ProjectPanelProps = ProjectPanelDataProps & RouteComponentProps<{ name: string }> & DispatchProp;
 +    componentDidMount() {
-         this.props.dispatch(actions.SET_COLUMNS({ id: PROJECT_EXPLORER_ID, columns }));
++        this.props.dispatch(actions.SET_COLUMNS({ id: PROJECT_PANEL_ID, columns }));
 +    }
  
-     toggleColumn = (toggledColumn: DataColumn<ProjectExplorerItem>) => {
-         this.props.dispatch(actions.TOGGLE_COLUMN({ id: PROJECT_EXPLORER_ID, columnName: toggledColumn.name }));
 -interface ProjectPanelState {
 -    sort: {
 -        columnName: string;
 -        direction: SortDirection;
 -    };
 -    filters: string[];
 -}
++    toggleColumn = (toggledColumn: DataColumn<ProjectPanelItem>) => {
++        this.props.dispatch(actions.TOGGLE_COLUMN({ id: PROJECT_PANEL_ID, columnName: toggledColumn.name }));
 +    }
  
-     toggleSort = (toggledColumn: DataColumn<ProjectExplorerItem>) => {
-         this.props.dispatch(actions.TOGGLE_SORT({ id: PROJECT_EXPLORER_ID, columnName: toggledColumn.name }));
 -class ProjectPanel extends React.Component<ProjectPanelProps & WithStyles<CssRules>, ProjectPanelState> {
 -    state: ProjectPanelState = {
 -        sort: {
 -            columnName: "Name",
 -            direction: "desc"
 -        },
 -        filters: ['collection', 'project']
 -    };
++    toggleSort = (column: DataColumn<ProjectPanelItem>) => {
++        this.props.dispatch(actions.TOGGLE_SORT({ id: PROJECT_PANEL_ID, columnName: column.name }));
 +    }
  
-     changeFilters = (filters: DataTableFilterItem[], updatedColumn: DataColumn<ProjectExplorerItem>) => {
-         this.props.dispatch(actions.SET_FILTERS({ id: PROJECT_EXPLORER_ID, columnName: updatedColumn.name, filters }));
 -    render() {
 -        const items = projectExplorerItems(
 -            this.props.projects.items,
 -            this.props.projects.currentItemId,
 -            this.props.collections
 -        );
 -        const [goBackItem, ...otherItems] = items;
 -        const filteredItems = otherItems.filter(i => this.state.filters.some(f => f === i.kind));
 -        const sortedItems = sortItems(this.state.sort, filteredItems);
 -        return (
 -            <div>
 -                <div className={this.props.classes.toolbar}>
 -                    <Button color="primary" variant="raised" className={this.props.classes.button}>
 -                        Create a collection
 -                    </Button>
 -                    <Button color="primary" variant="raised" className={this.props.classes.button}>
 -                        Run a process
 -                    </Button>
 -                    <Button color="primary" variant="raised" className={this.props.classes.button}>
 -                        Create a project
 -                    </Button>
 -                </div>
 -                <ProjectExplorer
 -                    items={goBackItem ? [goBackItem, ...sortedItems] : sortedItems}
 -                    onRowClick={this.goToItem}
 -                    onToggleSort={this.toggleSort}
 -                    onChangeFilters={this.changeFilters}
 -                />
 -            </div>
 -        );
++    changeFilters = (filters: DataTableFilterItem[], column: DataColumn<ProjectPanelItem>) => {
++        this.props.dispatch(actions.SET_FILTERS({ id: PROJECT_PANEL_ID, columnName: column.name, filters }));
      }
  
-     executeAction = (action: ContextMenuAction, item: ProjectExplorerItem) => {
 -    goToItem = (item: ProjectExplorerItem) => {
 -        this.props.dispatch<any>(setProjectItem(this.props.projects.items, item.uuid, item.kind, ItemMode.BOTH));
++    executeAction = (action: ContextMenuAction, item: ProjectPanelItem) => {
 +        alert(`Executing ${action.name} on ${item.name}`);
      }
  
 -    toggleSort = (column: DataColumn<ProjectExplorerItem>) => {
 -        this.setState({
 -            sort: {
 -                columnName: column.name,
 -                direction: column.sortDirection || "none"
 -            }
 -        });
 +    search = (searchValue: string) => {
-         this.props.dispatch(actions.SET_SEARCH_VALUE({ id: PROJECT_EXPLORER_ID, searchValue }));
++        this.props.dispatch(actions.SET_SEARCH_VALUE({ id: PROJECT_PANEL_ID, searchValue }));
      }
  
 -    changeFilters = (filters: DataTableFilterItem[]) => {
 -        this.setState({ filters: filters.filter(f => f.selected).map(f => f.name.toLowerCase()) });
 +    changePage = (page: number) => {
-         this.props.dispatch(actions.SET_PAGE({ id: PROJECT_EXPLORER_ID, page }));
++        this.props.dispatch(actions.SET_PAGE({ id: PROJECT_PANEL_ID, page }));
      }
 -}
  
 -const sortItems = (sort: { columnName: string, direction: SortDirection }, items: ProjectExplorerItem[]) => {
 -    const sortedItems = items.slice(0);
 -    const direction = sort.direction === "asc" ? -1 : 1;
 -    sortedItems.sort((a, b) => {
 -        if (sort.columnName === "Last modified") {
 -            return ((new Date(a.lastModified)).getTime() - (new Date(b.lastModified)).getTime()) * direction;
 -        } else {
 -            return a.name.localeCompare(b.name) * direction;
 -        }
 -    });
 -    return sortedItems;
 -};
 +    changeRowsPerPage = (rowsPerPage: number) => {
-         this.props.dispatch(actions.SET_ROWS_PER_PAGE({ id: PROJECT_EXPLORER_ID, rowsPerPage }));
++        this.props.dispatch(actions.SET_ROWS_PER_PAGE({ id: PROJECT_PANEL_ID, rowsPerPage }));
++    }
++
++    openProject = (item: ProjectPanelItem) => {
++        this.props.dispatch<any>(setProjectItem(item.uuid));
 +    }
 +}
  
  type CssRules = "toolbar" | "button";
  
@@@ -88,122 -116,10 +94,124 @@@ const styles: StyleRulesCallback<CssRul
      }
  });
  
- const renderName = (item: ProjectExplorerItem) =>
 -export default withStyles(styles)(
 -    connect(
 -        (state: RootState) => ({
 -            projects: state.projects,
 -            collections: state.collections
 -        })
 -    )(ProjectPanel));
++const renderName = (item: ProjectPanelItem) =>
 +    <Grid
 +        container
 +        alignItems="center"
 +        wrap="nowrap"
 +        spacing={16}>
 +        <Grid item>
 +            {renderIcon(item)}
 +        </Grid>
 +        <Grid item>
 +            <Typography color="primary">
 +                {item.name}
 +            </Typography>
 +        </Grid>
 +    </Grid>;
 +
- const renderIcon = (item: ProjectExplorerItem) => {
-     switch (item.type) {
-         case "arvados#group":
++
++const renderIcon = (item: ProjectPanelItem) => {
++    switch (item.kind) {
++        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 "arvados#groupList":
++        case ResourceKind.COLLECTION:
 +            return <i className="fas fa-th fa-lg" />;
 +        default:
 +            return <i />;
 +    }
 +};
 +
 +const renderDate = (date: string) =>
 +    <Typography noWrap>
 +        {formatDate(date)}
 +    </Typography>;
 +
 +const renderFileSize = (fileSize?: number) =>
 +    <Typography noWrap>
 +        {formatFileSize(fileSize)}
 +    </Typography>;
 +
 +const renderOwner = (owner: string) =>
 +    <Typography noWrap color="primary">
 +        {owner}
 +    </Typography>;
 +
 +const renderType = (type: string) =>
 +    <Typography noWrap>
 +        {type}
 +    </Typography>;
 +
- const renderStatus = (item: ProjectExplorerItem) =>
++const renderStatus = (item: ProjectPanelItem) =>
 +    <Typography noWrap align="center">
 +        {item.status || "-"}
 +    </Typography>;
 +
- const columns: DataColumns<ProjectExplorerItem> = [{
++const columns: DataColumns<ProjectPanelItem> = [{
 +    name: "Name",
 +    selected: true,
-     sortDirection: "asc",
-     render: renderName
++    sortDirection: "desc",
++    render: renderName,
++    width: "450px"
 +}, {
 +    name: "Status",
 +    selected: true,
-     filters: [{
-         name: "In progress",
-         selected: true
-     }, {
-         name: "Complete",
-         selected: true
-     }],
-     render: renderStatus
++    render: renderStatus,
++    width: "75px"
 +}, {
 +    name: "Type",
 +    selected: true,
 +    filters: [{
 +        name: "Collection",
 +        selected: true
 +    }, {
-         name: "Group",
++        name: "Project",
 +        selected: true
 +    }],
-     render: item => renderType(item.type)
++    render: item => renderType(item.kind),
++    width: "125px"
 +}, {
 +    name: "Owner",
 +    selected: true,
-     render: item => renderOwner(item.owner)
++    render: item => renderOwner(item.owner),
++    width: "200px"
 +}, {
 +    name: "File size",
 +    selected: true,
-     sortDirection: "none",
-     render: item => renderFileSize(item.fileSize)
++    render: item => renderFileSize(item.fileSize),
++    width: "50px"
 +}, {
 +    name: "Last modified",
 +    selected: true,
-     render: item => renderDate(item.lastModified)
++    sortDirection: "none",
++    render: item => renderDate(item.lastModified),
++    width: "150px"
 +}];
 +
 +const contextMenuActions = [[{
 +    icon: "fas fa-users fa-fw",
 +    name: "Share"
 +}, {
 +    icon: "fas fa-sign-out-alt fa-fw",
 +    name: "Move to"
 +}, {
 +    icon: "fas fa-star fa-fw",
 +    name: "Add to favourite"
 +}, {
 +    icon: "fas fa-edit fa-fw",
 +    name: "Rename"
 +}, {
 +    icon: "fas fa-copy fa-fw",
 +    name: "Make a copy"
 +}, {
 +    icon: "fas fa-download fa-fw",
 +    name: "Download"
 +}], [{
 +    icon: "fas fa-trash-alt fa-fw",
 +    name: "Remove"
 +}
 +]];
 +
- export default withStyles(styles)(connect()(ProjectExplorer));
++export default withStyles(styles)(connect()(ProjectPanel));
diff --cc src/views/workbench/workbench.tsx
index 92cbc5d,1069de5..72eb0dd
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@@ -8,21 -8,24 +8,25 @@@ import Drawer from '@material-ui/core/D
  import { connect, DispatchProp } from "react-redux";
  import { Route, Switch } from "react-router";
  import authActions from "../../store/auth/auth-action";
 +import dataExplorerActions from "../../store/data-explorer/data-explorer-action";
  import { User } from "../../models/user";
  import { RootState } from "../../store/store";
- import MainAppBar, { MainAppBarActionProps, MainAppBarMenuItem } from '../../views-components/main-app-bar/main-app-bar';
+ import MainAppBar, {
+     MainAppBarActionProps,
+     MainAppBarMenuItem
+ } from '../../views-components/main-app-bar/main-app-bar';
  import { Breadcrumb } from '../../components/breadcrumbs/breadcrumbs';
  import { push } from 'react-router-redux';
- import projectActions, { getProjectList } from "../../store/project/project-action";
  import ProjectTree from '../../views-components/project-tree/project-tree';
- import { TreeItem, TreeItemStatus } from "../../components/tree/tree";
+ import { TreeItem } from "../../components/tree/tree";
  import { Project } from "../../models/project";
 -import { getTreePath } from '../../store/project/project-reducer';
 -import ProjectPanel from '../project-panel/project-panel';
 +import { getTreePath, findTreeItem } from '../../store/project/project-reducer';
- import ProjectExplorer, { PROJECT_EXPLORER_ID } from '../../views-components/project-explorer/project-explorer';
- import { ProjectExplorerItem, mapProjectTreeItem } from '../../views-components/project-explorer/project-explorer-item';
  import sidePanelActions from '../../store/side-panel/side-panel-action';
  import SidePanel, { SidePanelItem } from '../../components/side-panel/side-panel';
+ import { ResourceKind } from "../../models/resource";
+ import { ItemMode, setProjectItem } from "../../store/navigation/navigation-action";
+ import projectActions from "../../store/project/project-action";
++import ProjectPanel from "../project-panel/project-panel";
  
  const drawerWidth = 240;
  const appBarHeight = 102;
@@@ -128,10 -130,11 +131,9 @@@ class Workbench extends React.Component
          }
      };
  
- 
      mainAppBarActions: MainAppBarActionProps = {
-         onBreadcrumbClick: ({ itemId, status }: NavBreadcrumb) => {
-             this.toggleProjectTreeItemOpen(itemId, status);
+         onBreadcrumbClick: ({ itemId }: NavBreadcrumb) => {
 -            this.props.dispatch<any>(
 -                setProjectItem(this.props.projects, itemId, ResourceKind.PROJECT, ItemMode.BOTH)
 -            );
++            this.props.dispatch<any>(setProjectItem(itemId, ResourceKind.PROJECT, ItemMode.BOTH));
          },
          onSearch: searchText => {
              this.setState({ searchText });
@@@ -221,11 -182,18 +181,18 @@@
                          <SidePanel
                              toggleOpen={this.toggleSidePanelOpen}
                              toggleActive={this.toggleSidePanelActive}
-                             sidePanelItems={sidePanelItems}>
+                             sidePanelItems={this.props.sidePanelItems}>
                              <ProjectTree
-                                 projects={projects}
-                                 toggleOpen={this.toggleProjectTreeItemOpen}
-                                 toggleActive={this.toggleProjectTreeItemActive} />
+                                 projects={this.props.projects}
+                                 toggleOpen={itemId =>
+                                     this.props.dispatch<any>(
 -                                        setProjectItem(this.props.projects, itemId, ResourceKind.PROJECT, ItemMode.OPEN)
++                                        setProjectItem(itemId, ResourceKind.PROJECT, ItemMode.OPEN)
+                                     )}
+                                 toggleActive={itemId =>
+                                     this.props.dispatch<any>(
 -                                        setProjectItem(this.props.projects, itemId, ResourceKind.PROJECT, ItemMode.ACTIVE)
++                                        setProjectItem(itemId, ResourceKind.PROJECT, ItemMode.ACTIVE)
+                                     )}
+                             />
                          </SidePanel>
                      </Drawer>}
                  <main className={classes.contentWrapper}>

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list