[ARVADOS-WORKBENCH2] updated: 1.2.0-146-g7b2c1a2

Git user git at public.curoverse.com
Mon Aug 27 02:56:16 EDT 2018


Summary of changes:
 src/components/form-dialog/form-dialog.tsx         |   3 +-
 src/store/project/project-action.ts                |  16 ---
 src/store/project/project-reducer.test.ts          |  35 ++-----
 src/store/project/project-reducer.ts               |  20 +---
 src/store/projects/project-update-actions.ts       |  57 ++++++++++
 .../context-menu/action-sets/project-action-set.ts |   4 +-
 .../dialog-forms/update-project-dialog.ts          |  19 ++++
 .../dialog-update/dialog-project-update.tsx        | 116 ++++-----------------
 .../update-project-dialog.tsx                      |  42 --------
 src/views/workbench/workbench.tsx                  |   3 +-
 10 files changed, 110 insertions(+), 205 deletions(-)
 create mode 100644 src/store/projects/project-update-actions.ts
 create mode 100644 src/views-components/dialog-forms/update-project-dialog.ts
 delete mode 100644 src/views-components/update-project-dialog/update-project-dialog.tsx

       via  7b2c1a2e5b38246b9360fb062e66997ebfa888ea (commit)
      from  1bda4645781ebb80f6d0db901f857abff088d749 (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 7b2c1a2e5b38246b9360fb062e66997ebfa888ea
Author: Janicki Artur <artur.janicki at contractors.roche.com>
Date:   Mon Aug 27 08:56:06 2018 +0200

    Rewrite edit project - add dialog form, actions, remove old code
    
    Feature #14103
    
    Arvados-DCO-1.1-Signed-off-by: Janicki Artur <artur.janicki at contractors.roche.com>

diff --git a/src/components/form-dialog/form-dialog.tsx b/src/components/form-dialog/form-dialog.tsx
index dee8924..150dc4b 100644
--- a/src/components/form-dialog/form-dialog.tsx
+++ b/src/components/form-dialog/form-dialog.tsx
@@ -48,7 +48,8 @@ export const FormDialog = withStyles(styles)((props: DialogProjectProps & WithDi
         onClose={props.closeDialog}
         disableBackdropClick={props.submitting}
         disableEscapeKeyDown={props.submitting}
-        fullWidth>
+        fullWidth
+        maxWidth='sm'>
         <form>
             <DialogTitle className={props.classes.dialogTitle}>
                 {props.dialogTitle}
diff --git a/src/store/project/project-action.ts b/src/store/project/project-action.ts
index 7af2aba..0598f66 100644
--- a/src/store/project/project-action.ts
+++ b/src/store/project/project-action.ts
@@ -13,9 +13,6 @@ import { projectPanelActions } from "~/store/project-panel/project-panel-action"
 import { updateDetails } from "~/store/details-panel/details-panel-action";
 
 export const projectActions = unionize({
-    OPEN_PROJECT_UPDATER: ofType<{ uuid: string}>(),
-    CLOSE_PROJECT_UPDATER: ofType<{}>(),
-    UPDATE_PROJECT_SUCCESS: ofType<ProjectResource>(),
     REMOVE_PROJECT: ofType<string>(),
     PROJECTS_REQUEST: ofType<string>(),
     PROJECTS_SUCCESS: ofType<{ projects: ProjectResource[], parentItemId?: string }>(),
@@ -43,17 +40,4 @@ export const getProjectList = (parentUuid: string = '') =>
         });
     };
 
-export const updateProject = (project: Partial<ProjectResource>) =>
-    (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        const { uuid } = getState().projects.updater;
-        return services.projectService
-            .update(uuid, project)
-            .then(project => {
-                dispatch(projectActions.UPDATE_PROJECT_SUCCESS(project));
-                dispatch(projectPanelActions.REQUEST_ITEMS());
-                dispatch<any>(getProjectList(project.ownerUuid));
-                dispatch<any>(updateDetails(project));
-            });
-    };
-
 export type ProjectAction = UnionOf<typeof projectActions>;
diff --git a/src/store/project/project-reducer.test.ts b/src/store/project/project-reducer.test.ts
index 8cd3121..56a6253 100644
--- a/src/store/project/project-reducer.test.ts
+++ b/src/store/project/project-reducer.test.ts
@@ -31,15 +31,7 @@ describe('project-reducer', () => {
                 status: TreeItemStatus.INITIAL
             }
             ],
-            currentItemId: "",
-            creator: {
-                opened: false,
-                ownerUuid: "",
-            },
-            updater: {
-                opened: false,
-                uuid: ''
-            }
+            currentItemId: ""
         });
     });
 
@@ -52,9 +44,7 @@ describe('project-reducer', () => {
                 active: true,
                 status: TreeItemStatus.PENDING
             }],
-            currentItemId: "1",
-            creator: { opened: false, ownerUuid: "" },
-            updater: { opened: false, uuid: '' }
+            currentItemId: "1"
         };
         const project = {
             items: [{
@@ -64,9 +54,7 @@ describe('project-reducer', () => {
                 active: false,
                 status: TreeItemStatus.PENDING
             }],
-            currentItemId: "",
-            creator: { opened: false, ownerUuid: "" },
-            updater: { opened: false, uuid: '' }
+            currentItemId: ""
         };
 
         const state = projectsReducer(initialState, projectActions.RESET_PROJECT_TREE_ACTIVITY(initialState.items[0].id));
@@ -82,9 +70,7 @@ describe('project-reducer', () => {
                 active: false,
                 status: TreeItemStatus.PENDING
             }],
-            currentItemId: "1",
-            creator: { opened: false, ownerUuid: "" },
-            updater: { opened: false, uuid: '' }
+            currentItemId: "1"
         };
         const project = {
             items: [{
@@ -94,9 +80,7 @@ describe('project-reducer', () => {
                 active: true,
                 status: TreeItemStatus.PENDING,
             }],
-            currentItemId: "1",
-            creator: { opened: false, ownerUuid: "" },
-            updater: { opened: false, uuid: '' }
+            currentItemId: "1"
         };
 
         const state = projectsReducer(initialState, projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(initialState.items[0].id));
@@ -113,9 +97,7 @@ describe('project-reducer', () => {
                 active: false,
                 status: TreeItemStatus.PENDING,
             }],
-            currentItemId: "1",
-            creator: { opened: false, ownerUuid: "" },
-            updater: { opened: false, uuid: '' }
+            currentItemId: "1"
         };
         const project = {
             items: [{
@@ -125,10 +107,7 @@ describe('project-reducer', () => {
                 active: false,
                 status: TreeItemStatus.PENDING,
             }],
-            currentItemId: "1",
-            creator: { opened: false, ownerUuid: "" },
-            updater: { opened: false, uuid: '' }
-
+            currentItemId: "1"
         };
 
         const state = projectsReducer(initialState, projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(initialState.items[0].id));
diff --git a/src/store/project/project-reducer.ts b/src/store/project/project-reducer.ts
index 848aed4..452f6be 100644
--- a/src/store/project/project-reducer.ts
+++ b/src/store/project/project-reducer.ts
@@ -10,8 +10,7 @@ import { ProjectResource } from "~/models/project";
 
 export type ProjectState = {
     items: Array<TreeItem<ProjectResource>>,
-    currentItemId: string,
-    updater: ProjectUpdater
+    currentItemId: string
 };
 
 interface ProjectUpdater {
@@ -91,29 +90,14 @@ function updateProjectTree(tree: Array<TreeItem<ProjectResource>>, projects: Pro
     return items;
 }
 
-const updateProject = (state: ProjectState, updater?: Partial<ProjectUpdater>) => ({
-    ...state,
-    updater: {
-        ...state.updater,
-        ...updater
-    }
-});
-
 const initialState: ProjectState = {
     items: [],
-    currentItemId: "",
-    updater: {
-        opened: false,
-        uuid: ''
-    }
+    currentItemId: ""
 };
 
 
 export const projectsReducer = (state: ProjectState = initialState, action: ProjectAction) => {
     return projectActions.match(action, {
-        OPEN_PROJECT_UPDATER: ({ uuid }) => updateProject(state, { uuid, opened: true }),
-        CLOSE_PROJECT_UPDATER: () => updateProject(state, { opened: false, uuid: "" }),
-        UPDATE_PROJECT_SUCCESS: () => updateProject(state, { opened: false, uuid: "" }),
         REMOVE_PROJECT: () => state,
         PROJECTS_REQUEST: itemId => {
             const items = _.cloneDeep(state.items);
diff --git a/src/store/projects/project-update-actions.ts b/src/store/projects/project-update-actions.ts
new file mode 100644
index 0000000..e674d29
--- /dev/null
+++ b/src/store/projects/project-update-actions.ts
@@ -0,0 +1,57 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { Dispatch } from "redux";
+import { initialize, startSubmit, stopSubmit } from 'redux-form';
+import { RootState } from "~/store/store";
+import { updateDetails } from "~/store/details-panel/details-panel-action";
+import { dialogActions } from "~/store/dialog/dialog-actions";
+import { snackbarActions } from "~/store/snackbar/snackbar-actions";
+import { ContextMenuResource } from '~/store/context-menu/context-menu-reducer';
+import { getCommonResourceServiceError, CommonResourceServiceError } from "~/common/api/common-resource-service";
+import { ServiceRepository } from "~/services/services";
+import { ProjectResource } from '~/models/project';
+import { getProjectList } from '~/store/project/project-action';
+import { projectPanelActions } from '~/store/project-panel/project-panel-action';
+
+export interface ProjectUpdateFormDialogData {
+    uuid: string;
+    name: string;
+    description: string;
+}
+
+export const PROJECT_UPDATE_FORM_NAME = 'projectUpdateFormName';
+
+export const openProjectUpdateDialog = (resource: ContextMenuResource) =>
+    (dispatch: Dispatch) => {
+        dispatch(initialize(PROJECT_UPDATE_FORM_NAME, resource));
+        dispatch(dialogActions.OPEN_DIALOG({ id: PROJECT_UPDATE_FORM_NAME, data: {} }));
+    };
+
+export const editProject = (data: ProjectUpdateFormDialogData) =>
+    async (dispatch: Dispatch) => {
+        await dispatch<any>(updateProject(data));
+        dispatch(snackbarActions.OPEN_SNACKBAR({
+            message: "Project has been successfully updated.",
+            hideDuration: 2000
+        }));
+    };
+
+export const updateProject = (project: Partial<ProjectResource>) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        const uuid = project.uuid || '';
+        dispatch(startSubmit(PROJECT_UPDATE_FORM_NAME));
+        try {
+            const updatedProject = await services.projectService.update(uuid, project);
+            dispatch(projectPanelActions.REQUEST_ITEMS());
+            dispatch<any>(getProjectList(updatedProject.ownerUuid));
+            dispatch<any>(updateDetails(updatedProject));
+            dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_UPDATE_FORM_NAME }));
+        } catch (e) {
+            const error = getCommonResourceServiceError(e);
+            if (error === CommonResourceServiceError.UNIQUE_VIOLATION) {
+                dispatch(stopSubmit(PROJECT_UPDATE_FORM_NAME, { name: 'Project with the same name already exists.' }));
+            }
+        }
+    };
\ No newline at end of file
diff --git a/src/views-components/context-menu/action-sets/project-action-set.ts b/src/views-components/context-menu/action-sets/project-action-set.ts
index 012beae..e466b94 100644
--- a/src/views-components/context-menu/action-sets/project-action-set.ts
+++ b/src/views-components/context-menu/action-sets/project-action-set.ts
@@ -12,6 +12,7 @@ import { toggleFavorite } from "~/store/favorites/favorites-actions";
 import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action";
 import { openMoveProjectDialog } from '~/store/move-project-dialog/move-project-dialog';
 import { PROJECT_CREATE_FORM_NAME, openProjectCreateDialog } from '~/store/projects/project-create-actions';
+import { openProjectUpdateDialog } from '~/store/projects/project-update-actions';
 
 export const projectActionSet: ContextMenuActionSet = [[
     {
@@ -26,8 +27,7 @@ export const projectActionSet: ContextMenuActionSet = [[
         icon: RenameIcon,
         name: "Edit project",
         execute: (dispatch, resource) => {
-            dispatch(projectActions.OPEN_PROJECT_UPDATER({ uuid: resource.uuid }));
-            dispatch(initialize(PROJECT_FORM_NAME, { name: resource.name, description: resource.description }));
+            dispatch<any>(openProjectUpdateDialog(resource));
         }
     },
     {
diff --git a/src/views-components/dialog-forms/update-project-dialog.ts b/src/views-components/dialog-forms/update-project-dialog.ts
new file mode 100644
index 0000000..598d0b1
--- /dev/null
+++ b/src/views-components/dialog-forms/update-project-dialog.ts
@@ -0,0 +1,19 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { compose } from "redux";
+import { reduxForm } from 'redux-form';
+import { withDialog } from "~/store/dialog/with-dialog";
+import { DialogProjectUpdate } from '~/views-components/dialog-update/dialog-project-update';
+import { editProject, PROJECT_UPDATE_FORM_NAME, ProjectUpdateFormDialogData } from '~/store/projects/project-update-actions';
+
+export const UpdateProjectDialog = compose(
+    withDialog(PROJECT_UPDATE_FORM_NAME),
+    reduxForm<ProjectUpdateFormDialogData>({
+        form: PROJECT_UPDATE_FORM_NAME,
+        onSubmit: (data, dispatch) => {
+            dispatch(editProject(data));
+        }
+    })
+)(DialogProjectUpdate);
\ No newline at end of file
diff --git a/src/views-components/dialog-update/dialog-project-update.tsx b/src/views-components/dialog-update/dialog-project-update.tsx
index b5e788c..49b97a6 100644
--- a/src/views-components/dialog-update/dialog-project-update.tsx
+++ b/src/views-components/dialog-update/dialog-project-update.tsx
@@ -3,99 +3,23 @@
 // 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 { StyleRulesCallback, WithStyles, withStyles, Dialog, DialogTitle, DialogContent, DialogActions, CircularProgress, Button } from '../../../node_modules/@material-ui/core';
-import { TextField } from '~/components/text-field/text-field';
-import { PROJECT_FORM_NAME } from '~/store/project/project-action';
-import { PROJECT_NAME_VALIDATION, PROJECT_DESCRIPTION_VALIDATION } from '~/validators/validators';
-
-type CssRules = 'content' | 'actions' | '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`
-    },
-    buttonWrapper: {
-        position: 'relative'
-    },
-    saveButton: {
-        boxShadow: 'none'
-    },
-    circularProgress: {
-        position: 'absolute',
-        top: 0,
-        bottom: 0,
-        left: 0,
-        right: 0,
-        margin: 'auto'
-    }
-});
-
-interface DialogProjectDataProps {
-    open: boolean;
-    handleSubmit: any;
-    submitting: boolean;
-    invalid: boolean;
-    pristine: boolean;
-}
-
-interface DialogProjectActionProps {
-    handleClose: () => void;
-    onSubmit: (data: { name: string, description: string }) => void;
-}
-
-type DialogProjectProps = DialogProjectDataProps & DialogProjectActionProps & WithStyles<CssRules>;
-
-export const DialogProjectUpdate = compose(
-    reduxForm({ form: PROJECT_FORM_NAME }),
-    withStyles(styles))(
-
-        class DialogProjectUpdate extends React.Component<DialogProjectProps> {
-            render() {
-                const { handleSubmit, handleClose, onSubmit, open, classes, 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 Project</DialogTitle>
-                        <DialogContent className={classes.content}>
-                            <Field name='name' 
-                                disabled={submitting}
-                                component={TextField}
-                                validate={PROJECT_NAME_VALIDATION}
-                                label="Project Name" />
-                            <Field name='description' 
-                                disabled={submitting}
-                                component={TextField} 
-                                validate={PROJECT_DESCRIPTION_VALIDATION}
-                                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>;
-            }
-        }
-    );
+import { InjectedFormProps } from 'redux-form';
+import { WithDialogProps } from '~/store/dialog/with-dialog';
+import { ProjectUpdateFormDialogData } from '~/store/projects/project-update-actions';
+import { FormDialog } from '~/components/form-dialog/form-dialog';
+import { ProjectNameField, ProjectDescriptionField } from '~/views-components/form-fields/project-form-fields';
+
+type DialogProjectProps = WithDialogProps<{}> & InjectedFormProps<ProjectUpdateFormDialogData>;
+
+export const DialogProjectUpdate = (props: DialogProjectProps) =>
+    <FormDialog
+        dialogTitle='Edit Project'
+        formFields={ProjectEditFields}
+        submitLabel='Save'
+        {...props}
+    />;
+
+const ProjectEditFields = () => <span>
+    <ProjectNameField />
+    <ProjectDescriptionField />
+</span>;
diff --git a/src/views-components/update-project-dialog/update-project-dialog.tsx b/src/views-components/update-project-dialog/update-project-dialog.tsx
deleted file mode 100644
index 0ea23c8..0000000
--- a/src/views-components/update-project-dialog/update-project-dialog.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import { connect } from "react-redux";
-import { Dispatch } from "redux";
-import { SubmissionError } from "redux-form";
-import { RootState } from "~/store/store";
-import { snackbarActions } from "~/store/snackbar/snackbar-actions";
-import { DialogProjectUpdate } from "../dialog-update/dialog-project-update";
-import { projectActions, updateProject } from "~/store/project/project-action";
-
-const mapStateToProps = (state: RootState) => ({
-    open: state.projects.updater.opened
-});
-
-const mapDispatchToProps = (dispatch: Dispatch) => ({
-    handleClose: () => {
-        dispatch(projectActions.CLOSE_PROJECT_UPDATER());
-    },
-    onSubmit: (data: { name: string, description: string }) => {
-        return dispatch<any>(editProject(data))
-            .catch((e: any) => {
-                if (e.errors) {
-                    throw new SubmissionError({ name: e.errors.join("").includes("UniqueViolation") ? "Project with this name already exists." : "" });
-                }
-            });
-    }
-});
-
-const editProject = (data: { name: string, description: string }) =>
-    (dispatch: Dispatch, getState: () => RootState) => {
-        const { uuid } = getState().projects.updater;
-        return dispatch<any>(updateProject(data)).then(() => {
-            dispatch(snackbarActions.OPEN_SNACKBAR({
-                message: "Project has been successfully updated.",
-                hideDuration: 2000
-            }));
-        });
-    };
-
-export const UpdateProjectDialog = connect(mapStateToProps, mapDispatchToProps)(DialogProjectUpdate);
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 77fab3d..a7c5f46 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -42,8 +42,7 @@ import { COLLECTION_CREATE_FORM_NAME, openCollectionCreateDialog } from '~/store
 import { CreateCollectionDialog } from '~/views-components/dialog-forms/create-collection-dialog';
 import { UpdateCollectionDialog } from '~/views-components/dialog-forms/update-collection-dialog';
 import { CreateProjectDialog } from '~/views-components/dialog-forms/create-project-dialog';
-
-import { UpdateProjectDialog } from '~/views-components/update-project-dialog/update-project-dialog';
+import { UpdateProjectDialog } from '~/views-components/dialog-forms/update-project-dialog';
 
 import { ProjectPanel } from "~/views/project-panel/project-panel";
 import { AuthService } from "~/services/auth-service/auth-service";

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


hooks/post-receive
-- 




More information about the arvados-commits mailing list