[ARVADOS-WORKBENCH2] updated: 1.1.4-136-gc90e813

Git user git at public.curoverse.com
Mon Jun 25 06:05:19 EDT 2018


Summary of changes:
 Makefile                                           |  19 +-
 __mocks__/popper.js.js                             |  30 +++
 package.json                                       |   4 +-
 src/common/formatters.ts                           |  42 ++++
 src/components/breadcrumbs/breadcrumbs.test.tsx    |  20 +-
 src/components/breadcrumbs/breadcrumbs.tsx         |  31 ++-
 .../column-selector/column-selector.test.tsx       |  79 ++++++++
 src/components/column-selector/column-selector.tsx |  56 ++++++
 src/components/context-menu/context-menu.test.tsx  |  35 ++++
 src/components/context-menu/context-menu.tsx       |  51 +++++
 .../data-explorer/data-explorer.test.tsx           | 130 ++++++++++++
 src/components/data-explorer/data-explorer.tsx     | 149 ++++++++++++++
 .../data-table-filters/data-table-filters.test.tsx |  68 +++++++
 .../data-table-filters/data-table-filters.tsx      | 188 +++++++++++++++++
 src/components/data-table/data-column.ts           |  34 ++++
 src/components/data-table/data-table.test.tsx      | 185 +++++++++++++++++
 src/components/data-table/data-table.tsx           | 110 ++++++++++
 .../dropdown-menu/dropdown-menu.test.tsx           |   0
 .../dropdown-menu/dropdown-menu.tsx                |   0
 src/components/popover/helpers.ts                  |  24 +++
 src/components/popover/popover.test.tsx            |  69 +++++++
 src/components/popover/popover.tsx                 |  69 +++++++
 .../search-bar/search-bar.test.tsx                 |   0
 .../{main-app-bar => }/search-bar/search-bar.tsx   |   0
 .../search-input.test.tsx}                         |  50 ++---
 .../search-input.tsx}                              |  50 ++---
 src/components/tree/tree.tsx                       |   4 +-
 src/index.tsx                                      |   8 +-
 src/{common/actions.ts => models/collection.ts}    |   5 +
 src/models/project.ts                              |  10 +-
 src/models/resource.ts                             |   9 +
 src/services/auth-service/auth-service.ts          |  15 +-
 .../collection-service/collection-service.ts       |  53 +++++
 src/services/project-service/project-service.ts    |  44 ++--
 src/services/response.ts                           |  11 +
 src/services/services.ts                           |   2 +
 src/store/auth/auth-action.ts                      |  15 +-
 src/store/auth/auth-reducer.test.ts                |  11 +-
 src/store/auth/auth-reducer.ts                     |  10 +-
 src/store/collection/collection-action.ts          |  29 +++
 src/store/collection/collection-reducer.test.ts    |  41 ++++
 src/store/collection/collection-reducer.ts         |  25 +++
 src/store/project/project-action.ts                |  20 +-
 src/store/project/project-reducer.test.ts          |  65 +++++-
 src/store/project/project-reducer.ts               |  16 +-
 src/store/store.ts                                 |   2 +
 .../api-token/api-token.tsx                        |   9 +-
 .../main-app-bar/main-app-bar.test.tsx             |   8 +-
 .../main-app-bar/main-app-bar.tsx                  |   8 +-
 .../project-explorer/project-explorer-item.ts      |  13 ++
 .../project-explorer/project-explorer.tsx          | 224 +++++++++++++++++++++
 .../project-list/project-list.tsx                  |   0
 .../project-tree/project-tree.test.tsx             |  16 +-
 .../project-tree/project-tree.tsx                  |   4 +-
 src/views/project-panel/project-panel-selectors.ts |  15 ++
 src/views/project-panel/project-panel.tsx          |  34 ++++
 src/views/workbench/workbench.test.tsx             |   2 +-
 src/views/workbench/workbench.tsx                  | 114 +++++++----
 yarn.lock                                          |  14 +-
 59 files changed, 2140 insertions(+), 209 deletions(-)
 create mode 100644 __mocks__/popper.js.js
 create mode 100644 src/common/formatters.ts
 create mode 100644 src/components/column-selector/column-selector.test.tsx
 create mode 100644 src/components/column-selector/column-selector.tsx
 create mode 100644 src/components/context-menu/context-menu.test.tsx
 create mode 100644 src/components/context-menu/context-menu.tsx
 create mode 100644 src/components/data-explorer/data-explorer.test.tsx
 create mode 100644 src/components/data-explorer/data-explorer.tsx
 create mode 100644 src/components/data-table-filters/data-table-filters.test.tsx
 create mode 100644 src/components/data-table-filters/data-table-filters.tsx
 create mode 100644 src/components/data-table/data-column.ts
 create mode 100644 src/components/data-table/data-table.test.tsx
 create mode 100644 src/components/data-table/data-table.tsx
 rename src/components/{main-app-bar => }/dropdown-menu/dropdown-menu.test.tsx (100%)
 rename src/components/{main-app-bar => }/dropdown-menu/dropdown-menu.tsx (100%)
 create mode 100644 src/components/popover/helpers.ts
 create mode 100644 src/components/popover/popover.test.tsx
 create mode 100644 src/components/popover/popover.tsx
 copy src/components/{main-app-bar => }/search-bar/search-bar.test.tsx (100%)
 copy src/components/{main-app-bar => }/search-bar/search-bar.tsx (100%)
 rename src/components/{main-app-bar/search-bar/search-bar.test.tsx => search-input/search-input.test.tsx} (52%)
 rename src/components/{main-app-bar/search-bar/search-bar.tsx => search-input/search-input.tsx} (63%)
 copy src/{common/actions.ts => models/collection.ts} (52%)
 create mode 100644 src/models/resource.ts
 create mode 100644 src/services/collection-service/collection-service.ts
 create mode 100644 src/services/response.ts
 create mode 100644 src/store/collection/collection-action.ts
 create mode 100644 src/store/collection/collection-reducer.test.ts
 create mode 100644 src/store/collection/collection-reducer.ts
 rename src/{components => views-components}/api-token/api-token.tsx (77%)
 rename src/{components => views-components}/main-app-bar/main-app-bar.test.tsx (95%)
 rename src/{components => views-components}/main-app-bar/main-app-bar.tsx (94%)
 create mode 100644 src/views-components/project-explorer/project-explorer-item.ts
 create mode 100644 src/views-components/project-explorer/project-explorer.tsx
 rename src/{components => views-components}/project-list/project-list.tsx (100%)
 rename src/{components => views-components}/project-tree/project-tree.test.tsx (89%)
 rename src/{components => views-components}/project-tree/project-tree.tsx (94%)
 create mode 100644 src/views/project-panel/project-panel-selectors.ts
 create mode 100644 src/views/project-panel/project-panel.tsx

       via  c90e813adcec89899d9db95843295a84fb058c3e (commit)
       via  5e88476747d9fb0c77ef76d63430192fa4b77f22 (commit)
       via  0ab4372cd072b9fd8f619158615a32b19a52f208 (commit)
       via  9fdaf676b641f794c73e8604e498b7d803fd1110 (commit)
       via  cc9505ee86539329d5ae0c4809aa293c54c2a25c (commit)
       via  06a247fec429a11fb27c0ebf50ba9c31ffc8d0c2 (commit)
       via  e2ea1359533664ead0ae9b810fe56bf518846c78 (commit)
       via  ac57fa77b04d290285388036f7929631e05965e4 (commit)
       via  f0c4e703bd7bdcf90265c96d6f714bf831f6947a (commit)
       via  a21b35b41a8e69a4a1e287ce069dbc65c5c534f2 (commit)
       via  9e4aa2fd44835698c0a3e6f321a2cf88b6f11939 (commit)
       via  bca77b4dbbc90bc60de06bd90a20e9a46c02fcfa (commit)
       via  5925c0eb9468ffca9419e47ae333501968b4e24e (commit)
       via  fd79729916cf6ddf27063b1865d39a36abb9e038 (commit)
       via  1a9eb2261e6030ba78078e2a206bad27653f2475 (commit)
       via  7444429308f438fb2e29188db8f208223ed39128 (commit)
       via  e5b901f7d6f87b56f43d3dbe002c9c90a3d41349 (commit)
       via  8dc6f80d8dc2365248093ae7c402491d4614d7f4 (commit)
       via  a01f29eb2238fbab8c87254ab23bbc82107832be (commit)
       via  98b3d2afa476478fa3d1acbce7a0784a8daf6945 (commit)
       via  1cc633c7a6ad9609424580973da06c92839489e2 (commit)
       via  83ca43a7dccc99e1036992a7a968b0c8bd1bc9f1 (commit)
       via  c4d1ac35050791aabbd1665b55248f5e074eb337 (commit)
       via  7364c06cd354952de2d469aa6285b7624864acf7 (commit)
       via  04895cf6825dab872f91bf86941b51d5b00cb39a (commit)
       via  a93f9562ce74d8cfb1cb7a5808e2b355e8e370c2 (commit)
       via  4a5d370214feccdab2a9d3cf398471daa695d401 (commit)
       via  8b42552c3532c3c48237d8d71e6a3a0636a7c47e (commit)
       via  09c61f87d52388ebfe97f478d536f4f194755401 (commit)
       via  7966796b929e29fd647ed9d7839406d30921c52b (commit)
       via  df778b7e960b73a4f765c13d0e7ccc4525a27b56 (commit)
       via  9e4b7889a99ff2f76d8029aef3a85c4620178ba3 (commit)
       via  95262273a85a2002a9f614c045fe6b907ddcc106 (commit)
       via  39eac675b7a8977d6dbb3a5815eba2bbbffe1645 (commit)
       via  6f12d4bae0571b94ade65f0c0a1423056c8dc253 (commit)
       via  eede2d8dc696f24552414b2425bb5d3a745280cc (commit)
       via  01b9aef245d1e419bd77999c12b65742e1363bc9 (commit)
       via  4bbaf2a0cede89ea50d63d210c6631adc1970620 (commit)
       via  0dbd184178c1016a19828fa80df9f91dec907993 (commit)
       via  430515acafe8731fdbeea5f9caae58991683ad94 (commit)
       via  fbd2012fa56f6de44dfc4008d70e5a21cfcaf459 (commit)
       via  e70279bebea915b5ddbef11357ab7a36201d6d85 (commit)
       via  fbe620454ddcba2c96b7a0f6049e05e3d12e5422 (commit)
       via  9c9a7d6f64f1c7c1aa82ed7e1497a56da37e63ab (commit)
       via  d4fda9299d54818dea306400813cfbee2627a5bc (commit)
       via  95a149461f453589ff5eb8a21b00f032d1c132a2 (commit)
       via  89161730d7d5e7d16a8fe2f5494db6560e718fa3 (commit)
       via  7cea5abf194fe6709ec25dbbd819e4c4be2faba0 (commit)
       via  e806c7001a4be0bb4b5a27995d89bd560d5fe8db (commit)
       via  a0bace185804d0d263249d65af442bed2890ca7b (commit)
       via  ce3be10391676729b35aafcb8d525daf5c74ceea (commit)
       via  e25469d58a038391fa16184da4f7078a0eae805a (commit)
       via  9f2313889301e05c721d58a8a9c3a667da990495 (commit)
       via  7b5dbd45ca461a8c58cfb148980b1ffe3f6d801e (commit)
       via  60503a22e8681732571bbfb9840edb37908a62b0 (commit)
       via  be414d2f98cac5fb96cf16e78943e1ecb8945e0f (commit)
       via  9b9176157227d347493ad2a7572dbca57ed9308b (commit)
       via  e5e907eac3162ddf7e76a431f66b8c26e80b0acf (commit)
       via  dbb23fe7623260b495ad64f0601feefdd103d376 (commit)
       via  799ab572df62562e8634e0e76683c3973c8337c4 (commit)
       via  6d53fc76c84291e57f33d55cb1f211bfb63b9f19 (commit)
       via  5361dea818f3f5c2b71ba4ce7ecb97e601c0403a (commit)
       via  a3620f307448f7854be04a12bce741385cc27ddd (commit)
       via  6471df421940db8b44adc93171a27659f7e3bdf1 (commit)
       via  d183e99c2202a1bfce258af2fe96a6cb1d08cad7 (commit)
       via  7adbd161925c71840bf4ddb799b87f1734e5af7e (commit)
       via  973fce01f05a50d4aa0169a88281f20476b305b2 (commit)
      from  ae7d952a97542c2cfc12f6f41ab0de93af278919 (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 c90e813adcec89899d9db95843295a84fb058c3e
Merge: ae7d952 5e88476
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Mon Jun 25 12:05:09 2018 +0200

    merge-conflicts
    
    Feature ##13598
    
    Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>

diff --cc src/components/tree/tree.tsx
index 5dd4587,6731950..2c19a83
--- a/src/components/tree/tree.tsx
+++ b/src/components/tree/tree.tsx
@@@ -29,8 -61,7 +29,8 @@@ export interface TreeItem<T> 
  interface TreeProps<T> {
      items?: Array<TreeItem<T>>;
      render: (item: TreeItem<T>, level?: number) => ReactElement<{}>;
 -    toggleItem: (id: string, status: TreeItemStatus) => any;
 +    toggleItemOpen: (id: string, status: TreeItemStatus) => void;
-     toggleItemActive: (id: string) => void;
++    toggleItemActive: (id: string, status: TreeItemStatus) => void;
      level?: number;
  }
  
@@@ -50,7 -81,7 +50,7 @@@ class Tree<T> extends React.Component<T
          return <List component="div" className={list}>
              {items && items.map((it: TreeItem<T>, idx: number) =>
                  <div key={`item/${level}/${idx}`}>
-                     <ListItem button className={list} style={{ paddingLeft: (level + 1) * 20 }} onClick={() => toggleItemActive(it.id)}>
 -                    <ListItem button className={list} style={{ paddingLeft: (level + 1) * 20 }}>
++                    <ListItem button className={list} style={{ paddingLeft: (level + 1) * 20 }} onClick={() => toggleItemActive(it.id, it.status)}>
                          {it.status === TreeItemStatus.Pending ? <CircularProgress size={10} className={loader} /> : null}
                          {it.toggled && it.items && it.items.length === 0 ? null : this.renderArrow(it.status, it.active ? activeArrow : inactiveArrow, it.open, it.id)}
                          {render(it, level)}
diff --cc src/store/project/project-action.ts
index a58edd3,728b1cc..3c264d3
--- a/src/store/project/project-action.ts
+++ b/src/store/project/project-action.ts
@@@ -1,22 -1,30 +1,34 @@@
  // Copyright (C) The Arvados Authors. All rights reserved.
  //
  // SPDX-License-Identifier: AGPL-3.0
 +import { default as unionize, ofType, UnionOf } from "unionize";
  
  import { Project } from "../../models/project";
 -import { default as unionize, ofType, UnionOf } from "unionize";
+ import { projectService } from "../../services/services";
+ import { Dispatch } from "redux";
  
  const actions = unionize({
      CREATE_PROJECT: ofType<Project>(),
      REMOVE_PROJECT: ofType<string>(),
--    PROJECTS_REQUEST: ofType<any>(),
++    PROJECTS_REQUEST: ofType<string>(),
      PROJECTS_SUCCESS: ofType<{ projects: Project[], parentItemId?: string }>(),
 -    TOGGLE_PROJECT_TREE_ITEM: ofType<string>()
 +    TOGGLE_PROJECT_TREE_ITEM_OPEN: ofType<string>(),
 +    TOGGLE_PROJECT_TREE_ITEM_ACTIVE: ofType<string>(),
 +    RESET_PROJECT_TREE_ACTIVITY: ofType<string>(),
  }, {
--    tag: 'type',
--    value: 'payload'
--});
++        tag: 'type',
++        value: 'payload'
++    });
+ 
+ export const getProjectList = (parentUuid?: string) => (dispatch: Dispatch): Promise<Project[]> => {
 -    dispatch(actions.PROJECTS_REQUEST());
 -    return projectService.getProjectList(parentUuid).then(projects => {
 -        dispatch(actions.PROJECTS_SUCCESS({projects, parentItemId: parentUuid}));
 -        return projects;
 -    });
++    if (parentUuid) {
++        dispatch(actions.PROJECTS_REQUEST(parentUuid));
++        return projectService.getProjectList(parentUuid).then(projects => {
++            dispatch(actions.PROJECTS_SUCCESS({ projects, parentItemId: parentUuid }));
++            return projects;
++        });
++    } return Promise.resolve([]);
+ };
  
  export type ProjectAction = UnionOf<typeof actions>;
  export default actions;
diff --cc src/store/project/project-reducer.test.ts
index e5cd57e,f964e0e..e8d6afc
--- a/src/store/project/project-reducer.test.ts
+++ b/src/store/project/project-reducer.test.ts
@@@ -35,137 -38,70 +38,193 @@@ describe('project-reducer', () => 
          const projects = [project, project];
          const state = projectsReducer(initialState, actions.PROJECTS_SUCCESS({ projects, parentItemId: undefined }));
          expect(state).toEqual([{
 +            active: false,
 +            open: false,
 +            id: "test123",
 +            items: [],
 +            data: project,
 +            status: 0
 +        }, {
 +            active: false,
 +            open: false,
 +            id: "test123",
 +            items: [],
 +            data: project,
 +            status: 0
 +        }
 +        ]);
 +    });
 +
 +    it('should remove activity on projects list', () => {
 +        const initialState = [
 +            {
 +                data: {
 +                    name: 'test',
 +                    href: 'href',
 +                    createdAt: '2018-01-01',
 +                    modifiedAt: '2018-01-01',
 +                    ownerUuid: 'owner-test123',
 +                    uuid: 'test123',
++                    kind: 'example'
 +                },
 +                id: "1",
 +                open: true,
 +                active: true,
 +                status: 1
 +            }
 +        ];
 +        const project = [
 +            {
 +                data: {
 +                    name: 'test',
 +                    href: 'href',
 +                    createdAt: '2018-01-01',
 +                    modifiedAt: '2018-01-01',
 +                    ownerUuid: 'owner-test123',
 +                    uuid: 'test123',
++                    kind: 'example'
 +                },
 +                id: "1",
 +                open: true,
                  active: false,
 -                open: false,
 -                id: "test123",
 -                items: [],
 -                data: project,
 -                status: 0
 -            }, {
 +                status: 1
 +            }
 +        ];
 +
 +        const state = projectsReducer(initialState, actions.RESET_PROJECT_TREE_ACTIVITY(initialState[0].id));
 +        expect(state).toEqual(project);
 +    });
 +
 +    it('should toggle project tree item activity', () => {
 +        const initialState = [
 +            {
 +                data: {
 +                    name: 'test',
 +                    href: 'href',
 +                    createdAt: '2018-01-01',
 +                    modifiedAt: '2018-01-01',
 +                    ownerUuid: 'owner-test123',
 +                    uuid: 'test123',
++                    kind: 'example'
 +                },
 +                id: "1",
 +                open: true,
 +                active: false,
 +                status: 1
 +            }
 +        ];
 +        const project = [
 +            {
 +                data: {
 +                    name: 'test',
 +                    href: 'href',
 +                    createdAt: '2018-01-01',
 +                    modifiedAt: '2018-01-01',
 +                    ownerUuid: 'owner-test123',
 +                    uuid: 'test123',
++                    kind: 'example'
 +                },
 +                id: "1",
 +                open: true,
 +                active: true,
 +                status: 1
 +            }
 +        ];
 +
 +        const state = projectsReducer(initialState, actions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(initialState[0].id));
 +        expect(state).toEqual(project);
 +    });
 +
 +
 +    it('should close project tree item ', () => {
 +        const initialState = [
 +            {
 +                data: {
 +                    name: 'test',
 +                    href: 'href',
 +                    createdAt: '2018-01-01',
 +                    modifiedAt: '2018-01-01',
 +                    ownerUuid: 'owner-test123',
 +                    uuid: 'test123',
++                    kind: 'example'
 +                },
 +                id: "1",
 +                open: true,
                  active: false,
 +                status: 1,
 +                toggled: false,
 +            }
 +        ];
 +        const project = [
 +            {
 +                data: {
 +                    name: 'test',
 +                    href: 'href',
 +                    createdAt: '2018-01-01',
 +                    modifiedAt: '2018-01-01',
 +                    ownerUuid: 'owner-test123',
 +                    uuid: 'test123',
++                    kind: 'example'
 +                },
 +                id: "1",
                  open: false,
 -                id: "test123",
 -                items: [],
 -                data: project,
 -                status: 0
 +                active: false,
 +                status: 1,
 +                toggled: true
              }
 -        ]);
 +        ];
 +
 +        const state = projectsReducer(initialState, actions.TOGGLE_PROJECT_TREE_ITEM_OPEN(initialState[0].id));
 +        expect(state).toEqual(project);
      });
  });
+ 
+ describe("findTreeBranch", () => {
+ 
+     const createTreeItem = (id: string, items?: Array<TreeItem<string>>): TreeItem<string> => ({
+         id,
+         items,
+         active: false,
+         data: "",
+         open: false,
+         status: TreeItemStatus.Initial
+     });
+ 
+     it("should return an array that matches path to the given item", () => {
+         const tree: Array<TreeItem<string>> = [
+             createTreeItem("1", [
+                 createTreeItem("1.1", [
+                     createTreeItem("1.1.1"),
+                     createTreeItem("1.1.2")
+                 ])
+             ]),
+             createTreeItem("2", [
+                 createTreeItem("2.1", [
+                     createTreeItem("2.1.1"),
+                     createTreeItem("2.1.2")
+                 ])
+             ])
+         ];
+         const branch = getTreePath(tree, "2.1.1");
+         expect(branch.map(item => item.id)).toEqual(["2", "2.1", "2.1.1"]);
+     });
+ 
+     it("should return empty array if item is not found", () => {
+         const tree: Array<TreeItem<string>> = [
+             createTreeItem("1", [
+                 createTreeItem("1.1", [
+                     createTreeItem("1.1.1"),
+                     createTreeItem("1.1.2")
+                 ])
+             ]),
+             createTreeItem("2", [
+                 createTreeItem("2.1", [
+                     createTreeItem("2.1.1"),
+                     createTreeItem("2.1.2")
+                 ])
+             ])
+         ];
+         expect(getTreePath(tree, "3")).toHaveLength(0);
+     });
+ 
+ });
diff --cc src/store/store.ts
index 49e0b5f,6b9c31f..6089caf
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@@ -6,10 -6,9 +6,11 @@@ import { createStore, applyMiddleware, 
  import { routerMiddleware, routerReducer, RouterState } from "react-router-redux";
  import thunkMiddleware from 'redux-thunk';
  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";
  
  const composeEnhancers =
      (process.env.NODE_ENV === 'development' &&
@@@ -26,8 -24,8 +27,9 @@@ export interface RootState 
  const rootReducer = combineReducers({
      auth: authReducer,
      projects: projectsReducer,
+     collections: collectionsReducer,
 -    router: routerReducer
 +    router: routerReducer,
 +    sidePanel: sidePanelReducer
  });
  
  
diff --cc src/views-components/project-tree/project-tree.test.tsx
index 932a29c,d531213..1ba3abb
--- a/src/views-components/project-tree/project-tree.test.tsx
+++ b/src/views-components/project-tree/project-tree.test.tsx
@@@ -26,13 -26,13 +26,14 @@@ describe("ProjectTree component", () =
                  uuid: "uuid",
                  ownerUuid: "ownerUuid",
                  href: "href",
++                kind: 'example'
              },
              id: "3",
              open: true,
              active: true,
              status: 1
          };
--        const wrapper = mount(<ProjectTree projects={[project]} toggleProjectTreeItem={() => { }} />);
++        const wrapper = mount(<ProjectTree projects={[project]} toggleOpen={jest.fn()} toggleActive={jest.fn()} />);
  
          expect(wrapper.find(ListItemIcon)).toHaveLength(1);
      });
@@@ -47,6 -47,6 +48,7 @@@
                      uuid: "uuid",
                      ownerUuid: "ownerUuid",
                      href: "href",
++                    kind: 'example'
                  },
                  id: "3",
                  open: false,
@@@ -61,6 -61,6 +63,7 @@@
                      uuid: "uuid",
                      ownerUuid: "ownerUuid",
                      href: "href",
++                    kind: 'example'
                  },
                  id: "3",
                  open: false,
@@@ -68,7 -68,7 +71,7 @@@
                  status: 1
              }
          ];
--        const wrapper = mount(<ProjectTree projects={project} toggleProjectTreeItem={() => { }} />);
++        const wrapper = mount(<ProjectTree projects={project} toggleOpen={jest.fn()} toggleActive={jest.fn()} />);
  
          expect(wrapper.find(ListItemIcon)).toHaveLength(2);
      });
@@@ -83,6 -83,6 +86,7 @@@
                      uuid: "uuid",
                      ownerUuid: "ownerUuid",
                      href: "href",
++                    kind: 'example'
                  },
                  id: "3",
                  open: true,
@@@ -97,6 -97,6 +101,7 @@@
                              uuid: "uuid",
                              ownerUuid: "ownerUuid",
                              href: "href",
++                            kind: 'example'
                          },
                          id: "3",
                          open: true,
@@@ -106,7 -106,7 +111,7 @@@
                  ]
              }
          ];
--        const wrapper = mount(<ProjectTree projects={project} toggleProjectTreeItem={() => { }} />);
++        const wrapper = mount(<ProjectTree projects={project} toggleOpen={jest.fn()} toggleActive={jest.fn()}/>);
  
          expect(wrapper.find(Collapse)).toHaveLength(1);
      });
@@@ -120,13 -120,13 +125,14 @@@
                  uuid: "uuid",
                  ownerUuid: "ownerUuid",
                  href: "href",
++                kind: 'example'
              },
              id: "3",
              open: false,
              active: true,
              status: 1
          };
--        const wrapper = mount(<ProjectTree projects={[project]} toggleProjectTreeItem={() => { }} />);
++        const wrapper = mount(<ProjectTree projects={[project]} toggleOpen={jest.fn()} toggleActive={jest.fn()} />);
  
          expect(wrapper.find(CircularProgress)).toHaveLength(1);
      });
diff --cc src/views-components/project-tree/project-tree.tsx
index 7406f7f,fd32ff0..f51b65e
--- a/src/views-components/project-tree/project-tree.tsx
+++ b/src/views-components/project-tree/project-tree.tsx
@@@ -9,39 -9,9 +9,39 @@@ import ListItemText from "@material-ui/
  import ListItemIcon from '@material-ui/core/ListItemIcon';
  import Typography from '@material-ui/core/Typography';
  
- import Tree, { TreeItem, TreeItemStatus } from '../tree/tree';
+ import Tree, { TreeItem, TreeItemStatus } from '../../components/tree/tree';
  import { Project } from '../../models/project';
  
 +export interface ProjectTreeProps {
 +    projects: Array<TreeItem<Project>>;
 +    toggleOpen: (id: string, status: TreeItemStatus) => void;
-     toggleActive: (id: string) => void;
++    toggleActive: (id: string, status: TreeItemStatus) => void;
 +}
 +
 +class ProjectTree<T> extends React.Component<ProjectTreeProps & WithStyles<CssRules>> {
 +    render(): ReactElement<any> {
 +        const { classes, projects, toggleOpen, toggleActive } = this.props;
 +        const { active, listItemText, row, treeContainer } = classes;
 +        return (
 +            <div className={treeContainer}>
 +                <Tree items={projects}
 +                    toggleItemOpen={toggleOpen}
 +                    toggleItemActive={toggleActive}
 +                    render={(project: TreeItem<Project>) =>
 +                        <span className={row}>
 +                            <ListItemIcon className={project.active ? active : ''}>
 +                                <i className="fas fa-folder" />
 +                            </ListItemIcon>
 +                            <ListItemText className={listItemText} primary={
 +                                <Typography className={project.active ? active : ''}>{project.data.name}</Typography>
 +                            } />
 +                        </span>
 +                    } />
 +            </div>
 +        );
 +    }
 +}
 +
  type CssRules = 'active' | 'listItemText' | 'row' | 'treeContainer';
  
  const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
diff --cc src/views/workbench/workbench.test.tsx
index 7b9b74d,7b9b74d..6925792
--- a/src/views/workbench/workbench.test.tsx
+++ b/src/views/workbench/workbench.test.tsx
@@@ -14,7 -14,7 +14,7 @@@ const history = createBrowserHistory()
  
  it('renders without crashing', () => {
      const div = document.createElement('div');
--    const store = configureStore({ projects: [], router: { location: null }, auth: {} }, createBrowserHistory());
++    const store = configureStore({ projects: [], router: { location: null }, auth: {}, sidePanel: [] }, createBrowserHistory());
      ReactDOM.render(
          <Provider store={store}>
              <ConnectedRouter history={history}>
diff --cc src/views/workbench/workbench.tsx
index 9e27432,bac0b47..4f9843c
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@@ -12,20 -11,20 +10,23 @@@ import { Route, Switch } from "react-ro
  import authActions from "../../store/auth/auth-action";
  import { User } from "../../models/user";
  import { RootState } from "../../store/store";
- import MainAppBar, { MainAppBarActionProps, MainAppBarMenuItem } from '../../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 from "../../store/project/project-action";
- import sidePanelActions from '../../store/side-panel/side-panel-action';
- import ProjectTree from '../../components/project-tree/project-tree';
+ 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 { Project } from "../../models/project";
+ import { getTreePath } from '../../store/project/project-reducer';
+ import ProjectPanel from '../project-panel/project-panel';
++import sidePanelActions from '../../store/side-panel/side-panel-action';
 +import { projectService } from '../../services/services';
 +import SidePanel, { SidePanelItem } from '../../components/side-panel/side-panel';
  
  const drawerWidth = 240;
+ const appBarHeight = 102;
  
- type CssRules = 'root' | 'appBar' | 'drawerPaper' | 'content' | 'toolbar';
+ type CssRules = 'root' | 'appBar' | 'drawerPaper' | 'content' | 'contentWrapper' | 'toolbar';
  
  const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
      root: {
@@@ -46,15 -45,18 +47,20 @@@
      drawerPaper: {
          position: 'relative',
          width: drawerWidth,
 +        display: 'flex',
 +        flexDirection: 'column',
      },
-     content: {
-         flexGrow: 1,
+     contentWrapper: {
          backgroundColor: theme.palette.background.default,
-         padding: theme.spacing.unit * 3,
-         height: '100%',
+         display: "flex",
+         flexGrow: 1,
          minWidth: 0,
+         paddingTop: appBarHeight
+     },
+     content: {
+         padding: theme.spacing.unit * 3,
+         overflowY: "auto",
+         flexGrow: 1
      },
      toolbar: theme.mixins.toolbar
  });
@@@ -130,7 -124,9 +129,9 @@@ class Workbench extends React.Component
  
  
      mainAppBarActions: MainAppBarActionProps = {
-         onBreadcrumbClick: (breadcrumb: NavBreadcrumb) => this.props.dispatch(push(breadcrumb.path)),
+         onBreadcrumbClick: ({ itemId, status }: NavBreadcrumb) => {
 -            this.toggleProjectTreeItem(itemId, status);
++            this.toggleProjectTreeItemOpen(itemId, status);
+         },
          onSearch: searchText => {
              this.setState({ searchText });
              this.props.dispatch(push(`/search?q=${searchText}`));
@@@ -138,34 -134,30 +139,60 @@@
          onMenuItemClick: (menuItem: NavMenuItem) => menuItem.action()
      };
  
 -    toggleProjectTreeItem = (itemId: string, status: TreeItemStatus) => {
 +    toggleProjectTreeItemOpen = (itemId: string, status: TreeItemStatus) => {
          if (status === TreeItemStatus.Loaded) {
+             this.openProjectItem(itemId);
 +            this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(itemId));
 +            this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
          } else {
-             this.props.dispatch<any>(projectService.getProjectList(itemId)).then(() => {
-                 this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(itemId));
-                 this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
-             });
+             this.props.dispatch<any>(getProjectList(itemId))
 -                .then(() => this.openProjectItem(itemId));
++                .then(() => {
++                    this.openProjectItem(itemId);
++                    this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(itemId));
++                    this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
++                });
          }
      }
  
-     toggleProjectTreeItemActive = (itemId: string) => {
-         this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
-         this.props.dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(itemId));
++    toggleProjectTreeItemActive = (itemId: string, status: TreeItemStatus) => {
++        if (status === TreeItemStatus.Loaded) {
++            this.openProjectItem(itemId);
++            this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
++            this.props.dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(itemId));
++        } else {
++            this.props.dispatch<any>(getProjectList(itemId))
++                .then(() => {
++                    this.openProjectItem(itemId);
++                    this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
++                    this.props.dispatch(sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(itemId));
++                });
++        }
 +    }
 +
 +    toggleSidePanelOpen = (itemId: string) => {
 +        this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(itemId));
 +    }
 +
 +    toggleSidePanelActive = (itemId: string) => {
 +        this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(itemId));
 +        this.props.dispatch(projectActions.RESET_PROJECT_TREE_ACTIVITY(itemId));
 +    }
 +
+     openProjectItem = (itemId: string) => {
+         const branch = getTreePath(this.props.projects, itemId);
+         this.setState({
+             breadcrumbs: branch.map(item => ({
+                 label: item.data.name,
+                 itemId: item.data.uuid,
+                 status: item.status
+             }))
+         });
 -        this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM(itemId));
++        this.props.dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(itemId));
+         this.props.dispatch(push(`/project/${itemId}`));
+     }
+ 
      render() {
 -        const { classes, user } = this.props;
 +        const { classes, user, projects, sidePanelItems } = this.props;
          return (
              <div className={classes.root}>
                  <div className={classes.appBar}>
@@@ -184,21 -176,16 +211,22 @@@
                              paper: classes.drawerPaper,
                          }}>
                          <div className={classes.toolbar} />
-                             <SidePanel
-                                 toggleOpen={this.toggleSidePanelOpen}
-                                 toggleActive={this.toggleSidePanelActive}
-                                 sidePanelItems={sidePanelItems}>
-                                 <ProjectTree
-                                     projects={projects}
-                                     toggleOpen={this.toggleProjectTreeItemOpen}
-                                     toggleActive={this.toggleProjectTreeItemActive} />
-                             </SidePanel>
 -                        <ProjectTree
 -                            projects={this.props.projects}
 -                            toggleProjectTreeItem={this.toggleProjectTreeItem} />
++                        <SidePanel
++                            toggleOpen={this.toggleSidePanelOpen}
++                            toggleActive={this.toggleSidePanelActive}
++                            sidePanelItems={sidePanelItems}>
++                            <ProjectTree
++                                projects={projects}
++                                toggleOpen={this.toggleProjectTreeItemOpen}
++                                toggleActive={this.toggleProjectTreeItemActive} />
++                        </SidePanel>
                      </Drawer>}
-                 <main className={classes.content}>
-                     <div className={classes.toolbar} />
-                     <Switch>
-                         <Route path="/project/:name" component={ProjectList} />
-                     </Switch>
+                 <main className={classes.contentWrapper}>
+                     <div className={classes.content}>
+                         <Switch>
+                             <Route path="/project/:name" component={ProjectPanel} />
+                         </Switch>
+                     </div>
                  </main>
              </div>
          );

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list