[ARVADOS-WORKBENCH2] created: 1.1.4-484-gada6711

Git user git at public.curoverse.com
Fri Aug 3 07:39:58 EDT 2018


        at  ada671101ba45837f90ef9fbb2129b243934c159 (commit)


commit ada671101ba45837f90ef9fbb2129b243934c159
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Fri Aug 3 13:39:38 2018 +0200

    restoring-correct-tree-state-and-panel-item-highlighting-on-page-refresh-with-given-url
    
    Feature #13905
    
    Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>

diff --git a/src/store/navigation/navigation-action.ts b/src/store/navigation/navigation-action.ts
index 1ab212f..9f49f25 100644
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@ -6,14 +6,16 @@ import { Dispatch } from "redux";
 import { projectActions, getProjectList } from "../project/project-action";
 import { push } from "react-router-redux";
 import { TreeItemStatus } from "../../components/tree/tree";
-import { findTreeItem, getTreePath } from "../project/project-reducer";
+import { findTreeItem } from "../project/project-reducer";
 import { RootState } from "../store";
 import { Resource, ResourceKind } from "../../models/resource";
 import { projectPanelActions } from "../project-panel/project-panel-action";
 import { getCollectionUrl } from "../../models/collection";
 import { getProjectUrl, ProjectResource } from "../../models/project";
-import { ServiceRepository } from "../../services/services";
 import { ProjectService } from "../../services/project-service/project-service";
+import { ServiceRepository } from "../../services/services";
+import { sidePanelActions } from "../side-panel/side-panel-action";
+import { SidePanelIdentifiers } from "../side-panel/side-panel-reducer";
 
 export const getResourceUrl = <T extends Resource>(resource: T): string => {
     switch (resource.kind) {
@@ -30,27 +32,19 @@ export enum ItemMode {
 }
 
 export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
-    (dispatch: Dispatch, getState: () => RootState) => {
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const { projects, router } = getState();
         const treeItem = findTreeItem(projects.items, itemId);
 
         if (treeItem) {
-            console.log('treeItem', treeItem);
-
-            const treePath = getTreePath(projects.items, treeItem.data.uuid);
 
-            console.log('treePath', treePath);
             const resourceUrl = getResourceUrl(treeItem.data);
 
-            console.log('resourceUrl', resourceUrl);
-            const ancestors = loadProjectAncestors(treeItem.data.uuid);
-            console.log('ancestors', ancestors);
-
             if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
                 if (router.location && !router.location.pathname.includes(resourceUrl)) {
                     dispatch(push(resourceUrl));
                 }
-                dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treePath[treePath.length - 1].id));
+                dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treeItem.data.uuid));
             }
 
             const promise = treeItem.status === TreeItemStatus.LOADED
@@ -69,14 +63,33 @@ export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
         }
     };
 
-    const USER_UUID_REGEX = /.*tpzed.*/;
+export const restoreBranch = (itemId: string) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        const ancestors = await loadProjectAncestors(itemId, services.projectService);
+        const uuids = ancestors.map(ancestor => ancestor.uuid);
+        await loadBranch(uuids, dispatch);
+        dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelIdentifiers.PROJECTS));
+        uuids.forEach(uuid => {
+            dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(uuid));
+        });
+    };
 
-    export const loadProjectAncestors = async (uuid: string, services?: any): Promise<Array<ProjectResource>> => {
-        if (USER_UUID_REGEX.test(uuid)) {
-            return [];
-        } else {
-            const currentProject = await services.projectService.get(uuid);
-            const ancestors = await loadProjectAncestors(currentProject.ownerUuid);
-            return [...ancestors, currentProject];
-        }
-    };
\ No newline at end of file
+const USER_UUID_REGEX = /.*tpzed.*/;
+
+export const loadProjectAncestors = async (uuid: string, projectService: ProjectService): Promise<Array<ProjectResource>> => {
+    if (USER_UUID_REGEX.test(uuid)) {
+        return [];
+    } else {
+        const currentProject = await projectService.get(uuid);
+        const ancestors = await loadProjectAncestors(currentProject.ownerUuid, projectService);
+        return [...ancestors, currentProject];
+    }
+};
+
+const loadBranch = async (uuids: string[], dispatch: Dispatch): Promise<any> => {
+    const [uuid, ...rest] = uuids;
+    if (uuid) {
+        await dispatch<any>(getProjectList(uuid));
+        return loadBranch(rest, dispatch);
+    }
+};
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index bd8c28e..cd8d1ed 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -18,7 +18,7 @@ import { TreeItem } from "../../components/tree/tree";
 import { getTreePath } from '../../store/project/project-reducer';
 import { sidePanelActions } from '../../store/side-panel/side-panel-action';
 import { SidePanel, SidePanelItem } from '../../components/side-panel/side-panel';
-import { ItemMode, setProjectItem } from "../../store/navigation/navigation-action";
+import { ItemMode, setProjectItem, restoreBranch } from "../../store/navigation/navigation-action";
 import { projectActions } from "../../store/project/project-action";
 import { collectionCreateActions } from '../../store/collections/creator/collection-creator-action';
 import { ProjectPanel } from "../project-panel/project-panel";
@@ -171,9 +171,16 @@ export const Workbench = withStyles(styles)(
             };
 
             componentDidMount() {
-                if (this.props.router.pathname.includes("/projects")) {
-                    this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelIdentifiers.PROJECTS));
-                    this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(SidePanelIdentifiers.PROJECTS));
+                const PROJECT_URL_REGEX = /\/projects\/(.*)/;
+                const getProjectIdFromUrl = (url: string) => {
+                    const match = PROJECT_URL_REGEX.exec(url);
+                    return match ? match[1] : match;
+                };
+
+                const id = getProjectIdFromUrl(this.props.router.pathname);
+                if (id) {
+                    this.props.dispatch<any>(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(SidePanelIdentifiers.PROJECTS));
+                    this.props.dispatch<any>(restoreBranch(id));
                 }
             }
 
@@ -184,7 +191,6 @@ export const Workbench = withStyles(styles)(
                     itemId: item.data.uuid,
                     status: item.status
                 }));
-                console.log("breadcrumbs", breadcrumbs);
 
                 const { classes, user } = this.props;
                 return (
@@ -283,7 +289,7 @@ export const Workbench = withStyles(styles)(
                         case ResourceKind.COLLECTION:
                             this.props.dispatch(loadCollection(item.uuid, item.kind as ResourceKind));
                             this.props.dispatch(push(getCollectionUrl(item.uuid)));
-                        default: 
+                        default:
                             this.props.dispatch(setProjectItem(item.uuid, ItemMode.ACTIVE));
                             this.props.dispatch(loadDetails(item.uuid, item.kind as ResourceKind));
                     }

commit 27bcade93df26e25bb2b4aff537875f78d3c1ff5
Merge: fed236c f724a56
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Fri Aug 3 09:22:05 2018 +0200

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

diff --cc src/store/navigation/navigation-action.ts
index 68d7fc5,ffb0f7a..1ab212f
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@@ -6,14 -6,12 +6,14 @@@ import { Dispatch } from "redux"
  import { projectActions, getProjectList } from "../project/project-action";
  import { push } from "react-router-redux";
  import { TreeItemStatus } from "../../components/tree/tree";
 -import { findTreeItem } from "../project/project-reducer";
 +import { findTreeItem, getTreePath } from "../project/project-reducer";
- import { dataExplorerActions } from "../data-explorer/data-explorer-action";
- import { PROJECT_PANEL_ID } from "../../views/project-panel/project-panel";
  import { RootState } from "../store";
  import { Resource, ResourceKind } from "../../models/resource";
+ import { projectPanelActions } from "../project-panel/project-panel-action";
  import { getCollectionUrl } from "../../models/collection";
 -import { getProjectUrl } from "../../models/project";
 +import { getProjectUrl, ProjectResource } from "../../models/project";
- import { projectService } from "../../services/services";
++import { ServiceRepository } from "../../services/services";
++import { ProjectService } from "../../services/project-service/project-service";
  
  export const getResourceUrl = <T extends Resource>(resource: T): string => {
      switch (resource.kind) {
@@@ -69,14 -59,3 +69,14 @@@ export const setProjectItem = (itemId: 
          }
      };
  
 +    const USER_UUID_REGEX = /.*tpzed.*/;
 +
-     export const loadProjectAncestors = async (uuid: string): Promise<Array<ProjectResource>> => {
++    export const loadProjectAncestors = async (uuid: string, services?: any): Promise<Array<ProjectResource>> => {
 +        if (USER_UUID_REGEX.test(uuid)) {
 +            return [];
 +        } else {
-             const currentProject = await projectService.get(uuid);
++            const currentProject = await services.projectService.get(uuid);
 +            const ancestors = await loadProjectAncestors(currentProject.ownerUuid);
 +            return [...ancestors, currentProject];
 +        }
 +    };
diff --cc src/views-components/create-project-dialog/create-project-dialog.tsx
index cbb80ff,1a52189..aa0dc7b
--- a/src/views-components/create-project-dialog/create-project-dialog.tsx
+++ b/src/views-components/create-project-dialog/create-project-dialog.tsx
@@@ -22,10 -21,10 +21,10 @@@ const addProject = (data: { name: strin
          const { ownerUuid } = getState().projects.creator;
          return dispatch<any>(createProject(data)).then(() => {
              dispatch(snackbarActions.OPEN_SNACKBAR({
 -                message: "Created a new project",
 +                message: "Project has been successfully created.",
                  hideDuration: 2000
              }));
-             dispatch(dataExplorerActions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID }));
+             dispatch(projectPanelActions.REQUEST_ITEMS());
              dispatch<any>(getProjectList(ownerUuid));
          });
      };
diff --cc src/views-components/dialog-create/dialog-collection-create.tsx
index 08f4702,3e3b74a..874ce13
--- a/src/views-components/dialog-create/dialog-collection-create.tsx
+++ b/src/views-components/dialog-create/dialog-collection-create.tsx
@@@ -12,9 -12,9 +12,9 @@@ import DialogContent from '@material-ui
  import DialogTitle from '@material-ui/core/DialogTitle';
  import { Button, StyleRulesCallback, WithStyles, withStyles, CircularProgress } from '@material-ui/core';
  
 -import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-project/create-project-validator';
 +import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-collection/create-collection-validator';
  
- type CssRules = "button" | "lastButton" | "formContainer" | "textField" | "dialog" | "dialogTitle" | "createProgress" | "dialogActions";
+ type CssRules = "button" | "lastButton" | "formContainer" | "textField" | "createProgress" | "dialogActions";
  
  const styles: StyleRulesCallback<CssRules> = theme => ({
      button: {
diff --cc src/views-components/dialog-update/dialog-collection-update.tsx
index 0000000,80a82b2..08eee41
mode 000000,100644..100644
--- a/src/views-components/dialog-update/dialog-collection-update.tsx
+++ b/src/views-components/dialog-update/dialog-collection-update.tsx
@@@ -1,0 -1,131 +1,131 @@@
+ // Copyright (C) The Arvados Authors. All rights reserved.
+ //
+ // SPDX-License-Identifier: AGPL-3.0
+ 
+ import * as React from 'react';
+ import { reduxForm, Field } from 'redux-form';
+ import { compose } from 'redux';
+ import { ArvadosTheme } from '../../common/custom-theme';
+ import { Dialog, DialogActions, DialogContent, DialogTitle, TextField, StyleRulesCallback, withStyles, WithStyles, Button, CircularProgress } from '../../../node_modules/@material-ui/core';
 -import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-project/create-project-validator';
++import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-collection/create-collection-validator';
+ import { COLLECTION_FORM_NAME } from '../../store/collections/updator/collection-updator-action';
+ 
+ type CssRules = 'content' | 'actions' | 'textField' | 'buttonWrapper' | 'saveButton' | 'circularProgress';
+ 
+ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
+     content: {
+         display: 'flex',
+         flexDirection: 'column'
+     },
+     actions: {
+         margin: 0,
+         padding: `${theme.spacing.unit}px ${theme.spacing.unit * 3 - theme.spacing.unit / 2}px 
+                 ${theme.spacing.unit * 3}px ${theme.spacing.unit * 3}px`
+     },
+     textField: {
+         marginBottom: theme.spacing.unit * 3
+     },
+     buttonWrapper: {
+         position: 'relative'
+     },
+     saveButton: {
+         boxShadow: 'none'
+     },
+     circularProgress: {
+         position: 'absolute',
+         top: 0,
+         bottom: 0,
+         left: 0,
+         right: 0,
+         margin: 'auto'
+     }
+ });
+ 
+ interface DialogCollectionDataProps {
+     open: boolean;
+     handleSubmit: any;
+     submitting: boolean;
+     invalid: boolean;
+     pristine: boolean;
+ }
+ 
+ interface DialogCollectionAction {
+     handleClose: () => void;
+     onSubmit: (data: { name: string, description: string }) => void;
+ }
+ 
+ type DialogCollectionProps = DialogCollectionDataProps & DialogCollectionAction & WithStyles<CssRules>;
+ 
+ interface TextFieldProps {
+     label: string;
+     floatinglabeltext: string;
+     className?: string;
+     input?: string;
+     meta?: any;
+ }
+ 
+ export const DialogCollectionUpdate = compose(
+     reduxForm({ form: COLLECTION_FORM_NAME }),
+     withStyles(styles))(
+ 
+         class DialogCollectionUpdate extends React.Component<DialogCollectionProps> {
+ 
+             render() {
+                 const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine } = this.props;
+                 return (
+                     <Dialog open={open}
+                         onClose={handleClose}
+                         fullWidth={true}
+                         maxWidth='sm'
+                         disableBackdropClick={true}
+                         disableEscapeKeyDown={true}>
+ 
+                         <form onSubmit={handleSubmit((data: any) => onSubmit(data))}>
+                             <DialogTitle>Edit Collection</DialogTitle>
+                             <DialogContent className={classes.content}>
+                                 <Field name="name"
+                                     disabled={submitting}
+                                     component={this.renderTextField}
+                                     floatinglabeltext="Collection Name"
+                                     validate={COLLECTION_NAME_VALIDATION}
+                                     className={classes.textField}
+                                     label="Collection Name" />
+                                 <Field name="description"
+                                     disabled={submitting}
+                                     component={this.renderTextField}
+                                     floatinglabeltext="Description - optional"
+                                     validate={COLLECTION_DESCRIPTION_VALIDATION}
+                                     className={classes.textField}
+                                     label="Description - optional" />
+                             </DialogContent>
+                             <DialogActions className={classes.actions}>
+                                 <Button onClick={handleClose} color="primary"
+                                     disabled={submitting}>CANCEL</Button>
+                                 <div className={classes.buttonWrapper}>
+                                     <Button type="submit" className={classes.saveButton}
+                                         color="primary"
+                                         disabled={invalid || submitting || pristine}
+                                         variant="contained">
+                                         SAVE
+                                     </Button>
+                                     {submitting && <CircularProgress size={20} className={classes.circularProgress} />}
+                                 </div>
+                             </DialogActions>
+                         </form>
+                     </Dialog>
+                 );
+             }
+ 
+             renderTextField = ({ input, label, meta: { touched, error }, ...custom }: TextFieldProps) => (
+                 <TextField
+                     helperText={touched && error}
+                     label={label}
+                     className={this.props.classes.textField}
+                     error={touched && !!error}
+                     autoComplete='off'
+                     {...input}
+                     {...custom}
+                 />
+             )
+         }
+     );
diff --cc src/views/workbench/workbench.tsx
index 1695201,dcce725..bd8c28e
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@@ -89,9 -91,12 +91,13 @@@ interface WorkbenchDataProps 
      user?: User;
      currentToken?: string;
      sidePanelItems: SidePanelItem[];
 +    router?: any;
  }
  
+ interface WorkbenchServiceProps {
+     authService: AuthService;
+ }
+ 
  interface WorkbenchActionProps {
  }
  
diff --cc yarn.lock
index 1eed5d2,1eed5d2..968562f
--- a/yarn.lock
+++ b/yarn.lock
@@@ -106,6 -106,6 +106,12 @@@
    version "10.5.2"
    resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.2.tgz#f19f05314d5421fe37e74153254201a7bf00a707"
  
++"@types/react-copy-to-clipboard at 4.2.5":
++  version "4.2.5"
++  resolved "https://registry.yarnpkg.com/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-4.2.5.tgz#bda288b4256288676019b75ca86f1714bbd206d4"
++  dependencies:
++    "@types/react" "*"
++
  "@types/react-dom at 16.0.6":
    version "16.0.6"
    resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.6.tgz#f1a65a4e7be8ed5d123f8b3b9eacc913e35a1a3c"
@@@ -1817,6 -1817,6 +1823,12 @@@ copy-descriptor@^0.1.0
    version "0.1.1"
    resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
  
++copy-to-clipboard@^3:
++  version "3.0.8"
++  resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9"
++  dependencies:
++    toggle-selection "^1.0.3"
++
  core-js@^1.0.0:
    version "1.2.7"
    resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
@@@ -6098,6 -6098,6 +6110,13 @@@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7
      minimist "^1.2.0"
      strip-json-comments "~2.0.1"
  
++react-copy-to-clipboard at 5.0.1:
++  version "5.0.1"
++  resolved "https://registry.yarnpkg.com/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz#8eae107bb400be73132ed3b6a7b4fb156090208e"
++  dependencies:
++    copy-to-clipboard "^3"
++    prop-types "^15.5.8"
++
  react-dev-utils@^5.0.1:
    version "5.0.1"
    resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-5.0.1.tgz#1f396e161fe44b595db1b186a40067289bf06613"
@@@ -7406,6 -7406,6 +7425,10 @@@ to-regex@^3.0.1, to-regex@^3.0.2
      regex-not "^1.0.2"
      safe-regex "^1.1.0"
  
++toggle-selection@^1.0.3:
++  version "1.0.6"
++  resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
++
  toposort@^1.0.0:
    version "1.0.7"
    resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"

commit fed236cf9d405efed2f5622ae58fd0e9974af30f
Author: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>
Date:   Fri Aug 3 08:51:55 2018 +0200

    getting tree path
    
    Feature #13905
    
    Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk <pawel.kowalczyk at contractors.roche.com>

diff --git a/src/store/navigation/navigation-action.ts b/src/store/navigation/navigation-action.ts
index f8687ed..68d7fc5 100644
--- a/src/store/navigation/navigation-action.ts
+++ b/src/store/navigation/navigation-action.ts
@@ -6,13 +6,14 @@ import { Dispatch } from "redux";
 import { projectActions, getProjectList } from "../project/project-action";
 import { push } from "react-router-redux";
 import { TreeItemStatus } from "../../components/tree/tree";
-import { findTreeItem } from "../project/project-reducer";
+import { findTreeItem, getTreePath } from "../project/project-reducer";
 import { dataExplorerActions } from "../data-explorer/data-explorer-action";
 import { PROJECT_PANEL_ID } from "../../views/project-panel/project-panel";
 import { RootState } from "../store";
 import { Resource, ResourceKind } from "../../models/resource";
 import { getCollectionUrl } from "../../models/collection";
-import { getProjectUrl } from "../../models/project";
+import { getProjectUrl, ProjectResource } from "../../models/project";
+import { projectService } from "../../services/services";
 
 export const getResourceUrl = <T extends Resource>(resource: T): string => {
     switch (resource.kind) {
@@ -34,14 +35,22 @@ export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
         const treeItem = findTreeItem(projects.items, itemId);
 
         if (treeItem) {
+            console.log('treeItem', treeItem);
 
+            const treePath = getTreePath(projects.items, treeItem.data.uuid);
+
+            console.log('treePath', treePath);
             const resourceUrl = getResourceUrl(treeItem.data);
 
+            console.log('resourceUrl', resourceUrl);
+            const ancestors = loadProjectAncestors(treeItem.data.uuid);
+            console.log('ancestors', ancestors);
+
             if (itemMode === ItemMode.ACTIVE || itemMode === ItemMode.BOTH) {
                 if (router.location && !router.location.pathname.includes(resourceUrl)) {
                     dispatch(push(resourceUrl));
                 }
-                dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treeItem.data.uuid));
+                dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(treePath[treePath.length - 1].id));
             }
 
             const promise = treeItem.status === TreeItemStatus.LOADED
@@ -60,3 +69,14 @@ export const setProjectItem = (itemId: string, itemMode: ItemMode) =>
         }
     };
 
+    const USER_UUID_REGEX = /.*tpzed.*/;
+
+    export const loadProjectAncestors = async (uuid: string): Promise<Array<ProjectResource>> => {
+        if (USER_UUID_REGEX.test(uuid)) {
+            return [];
+        } else {
+            const currentProject = await projectService.get(uuid);
+            const ancestors = await loadProjectAncestors(currentProject.ownerUuid);
+            return [...ancestors, currentProject];
+        }
+    };
\ No newline at end of file
diff --git a/src/validators/create-project/create-project-validator.tsx b/src/validators/create-collection/create-collection-validator.tsx
similarity index 70%
copy from src/validators/create-project/create-project-validator.tsx
copy to src/validators/create-collection/create-collection-validator.tsx
index 527043d..2d8e1f5 100644
--- a/src/validators/create-project/create-project-validator.tsx
+++ b/src/validators/create-collection/create-collection-validator.tsx
@@ -5,7 +5,5 @@
 import { require } from '../require';
 import { maxLength } from '../max-length';
 
-export const PROJECT_NAME_VALIDATION = [require, maxLength(255)];
-export const PROJECT_DESCRIPTION_VALIDATION = [maxLength(255)];
 export const COLLECTION_NAME_VALIDATION = [require, maxLength(255)];
-export const COLLECTION_DESCRIPTION_VALIDATION = [maxLength(255)];
+export const COLLECTION_DESCRIPTION_VALIDATION = [maxLength(255)];
\ No newline at end of file
diff --git a/src/validators/create-project/create-project-validator.tsx b/src/validators/create-project/create-project-validator.tsx
index 527043d..928efdd 100644
--- a/src/validators/create-project/create-project-validator.tsx
+++ b/src/validators/create-project/create-project-validator.tsx
@@ -7,5 +7,3 @@ import { maxLength } from '../max-length';
 
 export const PROJECT_NAME_VALIDATION = [require, maxLength(255)];
 export const PROJECT_DESCRIPTION_VALIDATION = [maxLength(255)];
-export const COLLECTION_NAME_VALIDATION = [require, maxLength(255)];
-export const COLLECTION_DESCRIPTION_VALIDATION = [maxLength(255)];
diff --git a/src/views-components/create-project-dialog/create-project-dialog.tsx b/src/views-components/create-project-dialog/create-project-dialog.tsx
index eacb1eb..cbb80ff 100644
--- a/src/views-components/create-project-dialog/create-project-dialog.tsx
+++ b/src/views-components/create-project-dialog/create-project-dialog.tsx
@@ -22,7 +22,7 @@ const addProject = (data: { name: string, description: string }) =>
         const { ownerUuid } = getState().projects.creator;
         return dispatch<any>(createProject(data)).then(() => {
             dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: "Created a new project",
+                message: "Project has been successfully created.",
                 hideDuration: 2000
             }));
             dispatch(dataExplorerActions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID }));
diff --git a/src/views-components/dialog-create/dialog-collection-create.tsx b/src/views-components/dialog-create/dialog-collection-create.tsx
index d0f793b..08f4702 100644
--- a/src/views-components/dialog-create/dialog-collection-create.tsx
+++ b/src/views-components/dialog-create/dialog-collection-create.tsx
@@ -12,7 +12,7 @@ import DialogContent from '@material-ui/core/DialogContent';
 import DialogTitle from '@material-ui/core/DialogTitle';
 import { Button, StyleRulesCallback, WithStyles, withStyles, CircularProgress } from '@material-ui/core';
 
-import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-project/create-project-validator';
+import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '../../validators/create-collection/create-collection-validator';
 
 type CssRules = "button" | "lastButton" | "formContainer" | "textField" | "dialog" | "dialogTitle" | "createProgress" | "dialogActions";
 
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 160e12f..1695201 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -89,6 +89,7 @@ interface WorkbenchDataProps {
     user?: User;
     currentToken?: string;
     sidePanelItems: SidePanelItem[];
+    router?: any;
 }
 
 interface WorkbenchActionProps {
@@ -122,7 +123,8 @@ export const Workbench = withStyles(styles)(
             currentProjectId: state.projects.currentItemId,
             user: state.auth.user,
             currentToken: state.auth.apiToken,
-            sidePanelItems: state.sidePanel
+            sidePanelItems: state.sidePanel,
+            router: state.router.location
         })
     )(
         class extends React.Component<WorkbenchProps, WorkbenchState> {
@@ -162,6 +164,13 @@ export const Workbench = withStyles(styles)(
                 }
             };
 
+            componentDidMount() {
+                if (this.props.router.pathname.includes("/projects")) {
+                    this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelIdentifiers.PROJECTS));
+                    this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(SidePanelIdentifiers.PROJECTS));
+                }
+            }
+
             render() {
                 const path = getTreePath(this.props.projects, this.props.currentProjectId);
                 const breadcrumbs = path.map(item => ({
@@ -169,6 +178,7 @@ export const Workbench = withStyles(styles)(
                     itemId: item.data.uuid,
                     status: item.status
                 }));
+                console.log("breadcrumbs", breadcrumbs);
 
                 const { classes, user } = this.props;
                 return (
@@ -234,7 +244,7 @@ export const Workbench = withStyles(styles)(
                 );
             }
 
-            renderCollectionPanel = (props: RouteComponentProps<{ id: string }>) => <CollectionPanel 
+            renderCollectionPanel = (props: RouteComponentProps<{ id: string }>) => <CollectionPanel
                 onItemRouteChange={(collectionId) => this.props.dispatch<any>(loadCollection(collectionId, ResourceKind.COLLECTION))}
                 onContextMenu={(event, item) => {
                     this.openContextMenu(event, {
@@ -266,7 +276,7 @@ export const Workbench = withStyles(styles)(
                         case ResourceKind.COLLECTION:
                             this.props.dispatch<any>(loadCollection(item.uuid, item.kind as ResourceKind));
                             this.props.dispatch(push(getCollectionUrl(item.uuid)));
-                        default: 
+                        default:
                             this.props.dispatch<any>(setProjectItem(item.uuid, ItemMode.ACTIVE));
                             this.props.dispatch<any>(loadDetails(item.uuid, item.kind as ResourceKind));
                     }

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list