From: Pawel Kowalczyk Date: Mon, 27 Aug 2018 11:52:38 +0000 (+0200) Subject: Merge branch 'master' into 13858-process-view-information-card X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/b4adbf55b9a1950d70e2e44c28efb13eb4d0f077?hp=605e792e4854c7aad2f08e08fa7a8d9eba9d64a1 Merge branch 'master' into 13858-process-view-information-card refs #13858 Arvados-DCO-1.1-Signed-off-by: Pawel Kowalczyk --- diff --git a/src/components/form-dialog/form-dialog.tsx b/src/components/form-dialog/form-dialog.tsx index dee89249e2..150dc4b665 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'>
{props.dialogTitle} diff --git a/src/store/collections/collection-create-actions.ts b/src/store/collections/collection-create-actions.ts new file mode 100644 index 0000000000..d8d292c068 --- /dev/null +++ b/src/store/collections/collection-create-actions.ts @@ -0,0 +1,55 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { Dispatch } from "redux"; +import { reset, startSubmit, stopSubmit, initialize } from 'redux-form'; +import { RootState } from '~/store/store'; +import { uploadCollectionFiles } from '~/store/collections/uploader/collection-uploader-actions'; +import { projectPanelActions } from "~/store/project-panel/project-panel-action"; +import { snackbarActions } from "~/store/snackbar/snackbar-actions"; +import { dialogActions } from "~/store/dialog/dialog-actions"; +import { CollectionResource } from '~/models/collection'; +import { ServiceRepository } from '~/services/services'; +import { getCommonResourceServiceError, CommonResourceServiceError } from "~/common/api/common-resource-service"; + +export interface CollectionCreateFormDialogData { + ownerUuid: string; + name: string; + description: string; + files: File[]; +} + +export const COLLECTION_CREATE_FORM_NAME = "collectionCreateFormName"; + +export const openCollectionCreateDialog = (ownerUuid: string) => + (dispatch: Dispatch) => { + dispatch(initialize(COLLECTION_CREATE_FORM_NAME, { ownerUuid })); + dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_CREATE_FORM_NAME, data: { ownerUuid } })); + }; + +export const addCollection = (data: CollectionCreateFormDialogData) => + async (dispatch: Dispatch) => { + await dispatch(createCollection(data)); + dispatch(snackbarActions.OPEN_SNACKBAR({ + message: "Collection has been successfully created.", + hideDuration: 2000 + })); + }; + +export const createCollection = (collection: Partial) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + dispatch(startSubmit(COLLECTION_CREATE_FORM_NAME)); + try { + const newCollection = await services.collectionService.create(collection); + await dispatch(uploadCollectionFiles(newCollection.uuid)); + dispatch(projectPanelActions.REQUEST_ITEMS()); + dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_CREATE_FORM_NAME })); + dispatch(reset(COLLECTION_CREATE_FORM_NAME)); + } catch (e) { + const error = getCommonResourceServiceError(e); + if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { + dispatch(stopSubmit(COLLECTION_CREATE_FORM_NAME, { name: 'Collection with the same name already exists.' })); + } + } + }; \ No newline at end of file diff --git a/src/store/move-collection-dialog/move-collection-dialog.ts b/src/store/collections/collection-move-actions.ts similarity index 72% rename from src/store/move-collection-dialog/move-collection-dialog.ts rename to src/store/collections/collection-move-actions.ts index 5950679956..6fc836f80e 100644 --- a/src/store/move-collection-dialog/move-collection-dialog.ts +++ b/src/store/collections/collection-move-actions.ts @@ -10,33 +10,33 @@ import { RootState } from '~/store/store'; import { getCommonResourceServiceError, CommonResourceServiceError } from "~/common/api/common-resource-service"; import { snackbarActions } from '~/store/snackbar/snackbar-actions'; import { projectPanelActions } from '~/store/project-panel/project-panel-action'; -import { MoveToFormDialogData } from '../move-to-dialog/move-to-dialog'; +import { MoveToFormDialogData } from '~/store/move-to-dialog/move-to-dialog'; import { resetPickerProjectTree } from '~/store/project-tree-picker/project-tree-picker-actions'; -export const MOVE_COLLECTION_DIALOG = 'moveCollectionDialog'; +export const COLLECTION_MOVE_FORM_NAME = 'collectionMoveFormName'; export const openMoveCollectionDialog = (resource: { name: string, uuid: string }) => (dispatch: Dispatch) => { dispatch(resetPickerProjectTree()); - dispatch(initialize(MOVE_COLLECTION_DIALOG, resource)); - dispatch(dialogActions.OPEN_DIALOG({ id: MOVE_COLLECTION_DIALOG, data: {} })); + dispatch(initialize(COLLECTION_MOVE_FORM_NAME, resource)); + dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_MOVE_FORM_NAME, data: {} })); }; export const moveCollection = (resource: MoveToFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - dispatch(startSubmit(MOVE_COLLECTION_DIALOG)); + dispatch(startSubmit(COLLECTION_MOVE_FORM_NAME)); try { const collection = await services.collectionService.get(resource.uuid); await services.collectionService.update(resource.uuid, { ...collection, ownerUuid: resource.ownerUuid }); dispatch(projectPanelActions.REQUEST_ITEMS()); - dispatch(dialogActions.CLOSE_DIALOG({ id: MOVE_COLLECTION_DIALOG })); + dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_MOVE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Collection has been moved', hideDuration: 2000 })); } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(MOVE_COLLECTION_DIALOG, { ownerUuid: 'A collection with the same name already exists in the target project.' })); + dispatch(stopSubmit(COLLECTION_MOVE_FORM_NAME, { ownerUuid: 'A collection with the same name already exists in the target project.' })); } else { - dispatch(dialogActions.CLOSE_DIALOG({ id: MOVE_COLLECTION_DIALOG })); + dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_MOVE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move the collection.', hideDuration: 2000 })); } } diff --git a/src/store/collections/collection-update-actions.ts b/src/store/collections/collection-update-actions.ts new file mode 100644 index 0000000000..27c3bfced5 --- /dev/null +++ b/src/store/collections/collection-update-actions.ts @@ -0,0 +1,58 @@ +// 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 { collectionPanelActions } from "~/store/collection-panel/collection-panel-action"; +import { updateDetails } from "~/store/details-panel/details-panel-action"; +import { dialogActions } from "~/store/dialog/dialog-actions"; +import { dataExplorerActions } from "~/store/data-explorer/data-explorer-action"; +import { snackbarActions } from "~/store/snackbar/snackbar-actions"; +import { ContextMenuResource } from '~/store/context-menu/context-menu-reducer'; +import { PROJECT_PANEL_ID } from "~/views/project-panel/project-panel"; +import { getCommonResourceServiceError, CommonResourceServiceError } from "~/common/api/common-resource-service"; +import { ServiceRepository } from "~/services/services"; +import { CollectionResource } from '~/models/collection'; + +export interface CollectionUpdateFormDialogData { + uuid: string; + name: string; + description: string; +} + +export const COLLECTION_UPDATE_FORM_NAME = 'collectionUpdateFormName'; + +export const openCollectionUpdateDialog = (resource: ContextMenuResource) => + (dispatch: Dispatch) => { + dispatch(initialize(COLLECTION_UPDATE_FORM_NAME, resource)); + dispatch(dialogActions.OPEN_DIALOG({ id: COLLECTION_UPDATE_FORM_NAME, data: {} })); + }; + +export const editCollection = (data: CollectionUpdateFormDialogData) => + async (dispatch: Dispatch) => { + await dispatch(updateCollection(data)); + dispatch(snackbarActions.OPEN_SNACKBAR({ + message: "Collection has been successfully updated.", + hideDuration: 2000 + })); + }; + +export const updateCollection = (collection: Partial) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + const uuid = collection.uuid || ''; + dispatch(startSubmit(COLLECTION_UPDATE_FORM_NAME)); + try { + const updatedCollection = await services.collectionService.update(uuid, collection); + dispatch(collectionPanelActions.LOAD_COLLECTION_SUCCESS({ item: updatedCollection as CollectionResource })); + dispatch(updateDetails(updatedCollection)); + dispatch(dataExplorerActions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); + dispatch(dialogActions.CLOSE_DIALOG({ id: COLLECTION_UPDATE_FORM_NAME })); + } catch(e) { + const error = getCommonResourceServiceError(e); + if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { + dispatch(stopSubmit(COLLECTION_UPDATE_FORM_NAME, { name: 'Collection with the same name already exists.' })); + } + } + }; \ No newline at end of file diff --git a/src/store/collections/collections-reducer.ts b/src/store/collections/collections-reducer.ts index b2ee455066..c7601505cb 100644 --- a/src/store/collections/collections-reducer.ts +++ b/src/store/collections/collections-reducer.ts @@ -3,18 +3,12 @@ // SPDX-License-Identifier: AGPL-3.0 import { combineReducers } from 'redux'; -import { collectionCreatorReducer, CollectionCreatorState } from "./creator/collection-creator-reducer"; -import { collectionUpdaterReducer, CollectionUpdaterState } from "./updater/collection-updater-reducer"; import { collectionUploaderReducer, CollectionUploaderState } from "./uploader/collection-uploader-reducer"; export type CollectionsState = { - creator: CollectionCreatorState; - updater: CollectionUpdaterState; uploader: CollectionUploaderState }; export const collectionsReducer = combineReducers({ - creator: collectionCreatorReducer, - updater: collectionUpdaterReducer, uploader: collectionUploaderReducer }); diff --git a/src/store/collections/creator/collection-creator-action.ts b/src/store/collections/creator/collection-creator-action.ts deleted file mode 100644 index 8c35ffa833..0000000000 --- a/src/store/collections/creator/collection-creator-action.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import { default as unionize, ofType, UnionOf } from "unionize"; -import { Dispatch } from "redux"; - -import { RootState } from "../../store"; -import { CollectionResource } from '~/models/collection'; -import { ServiceRepository } from "~/services/services"; -import { uploadCollectionFiles } from '../uploader/collection-uploader-actions'; -import { reset } from "redux-form"; - -export const collectionCreateActions = unionize({ - OPEN_COLLECTION_CREATOR: ofType<{ ownerUuid: string }>(), - CLOSE_COLLECTION_CREATOR: ofType<{}>(), - CREATE_COLLECTION: ofType<{}>(), - CREATE_COLLECTION_SUCCESS: ofType<{}>(), -}, { - tag: 'type', - value: 'payload' - }); - -export type CollectionCreateAction = UnionOf; - -export const createCollection = (collection: Partial, files: File[]) => - async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - const { ownerUuid } = getState().collections.creator; - const collectiontData = { ownerUuid, ...collection }; - dispatch(collectionCreateActions.CREATE_COLLECTION(collectiontData)); - const newCollection = await services.collectionService.create(collectiontData); - await dispatch(uploadCollectionFiles(newCollection.uuid)); - dispatch(collectionCreateActions.CREATE_COLLECTION_SUCCESS(collection)); - dispatch(reset('collectionCreateDialog')); - return newCollection; - }; - diff --git a/src/store/collections/creator/collection-creator-reducer.test.ts b/src/store/collections/creator/collection-creator-reducer.test.ts deleted file mode 100644 index 5aa9dcfe5a..0000000000 --- a/src/store/collections/creator/collection-creator-reducer.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import { collectionCreatorReducer } from "./collection-creator-reducer"; -import { collectionCreateActions } from "./collection-creator-action"; - -describe('collection-reducer', () => { - - it('should open collection creator dialog', () => { - const initialState = { opened: false, ownerUuid: "" }; - const collection = { opened: true, ownerUuid: "" }; - - const state = collectionCreatorReducer(initialState, collectionCreateActions.OPEN_COLLECTION_CREATOR(initialState)); - expect(state).toEqual(collection); - }); - - it('should close collection creator dialog', () => { - const initialState = { opened: true, ownerUuid: "" }; - const collection = { opened: false, ownerUuid: "" }; - - const state = collectionCreatorReducer(initialState, collectionCreateActions.CLOSE_COLLECTION_CREATOR()); - expect(state).toEqual(collection); - }); - - it('should reset collection creator dialog props', () => { - const initialState = { opened: true, ownerUuid: "test" }; - const collection = { opened: false, ownerUuid: "" }; - - const state = collectionCreatorReducer(initialState, collectionCreateActions.CREATE_COLLECTION_SUCCESS()); - expect(state).toEqual(collection); - }); -}); diff --git a/src/store/collections/creator/collection-creator-reducer.ts b/src/store/collections/creator/collection-creator-reducer.ts deleted file mode 100644 index 72c999d0d1..0000000000 --- a/src/store/collections/creator/collection-creator-reducer.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import { collectionCreateActions, CollectionCreateAction } from './collection-creator-action'; - -export interface CollectionCreatorState { - opened: boolean; - ownerUuid: string; -} - -const updateCreator = (state: CollectionCreatorState, creator?: Partial) => ({ - ...state, - ...creator -}); - -const initialState: CollectionCreatorState = { - opened: false, - ownerUuid: '' -}; - -export const collectionCreatorReducer = (state: CollectionCreatorState = initialState, action: CollectionCreateAction) => { - return collectionCreateActions.match(action, { - OPEN_COLLECTION_CREATOR: ({ ownerUuid }) => updateCreator(state, { ownerUuid, opened: true }), - CLOSE_COLLECTION_CREATOR: () => updateCreator(state, { opened: false }), - CREATE_COLLECTION: () => updateCreator(state), - CREATE_COLLECTION_SUCCESS: () => updateCreator(state, { opened: false, ownerUuid: "" }), - default: () => state - }); -}; diff --git a/src/store/collections/updater/collection-updater-action.ts b/src/store/collections/updater/collection-updater-action.ts deleted file mode 100644 index 2f520d4a38..0000000000 --- a/src/store/collections/updater/collection-updater-action.ts +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import { default as unionize, ofType, UnionOf } from "unionize"; -import { Dispatch } from "redux"; - -import { RootState } from "../../store"; -import { ServiceRepository } from "~/services/services"; -import { CollectionResource } from '~/models/collection'; -import { initialize } from 'redux-form'; -import { collectionPanelActions } from "../../collection-panel/collection-panel-action"; -import { ContextMenuResource } from "../../context-menu/context-menu-reducer"; -import { updateDetails } from "~/store/details-panel/details-panel-action"; - -export const collectionUpdaterActions = unionize({ - OPEN_COLLECTION_UPDATER: ofType<{ uuid: string }>(), - CLOSE_COLLECTION_UPDATER: ofType<{}>(), - UPDATE_COLLECTION_SUCCESS: ofType<{}>(), -}, { - tag: 'type', - value: 'payload' -}); - - -export const COLLECTION_FORM_NAME = 'collectionEditDialog'; - -export const openUpdater = (item: ContextMenuResource) => - (dispatch: Dispatch, getState: () => RootState) => { - if (item) { - dispatch(collectionUpdaterActions.OPEN_COLLECTION_UPDATER({ uuid: item.uuid })); - dispatch(initialize(COLLECTION_FORM_NAME, { name: item.name, description: item.description })); - } - }; - -export const updateCollection = (collection: Partial) => - (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - const { uuid } = getState().collections.updater; - return services.collectionService - .update(uuid, collection) - .then(collection => { - dispatch(collectionPanelActions.LOAD_COLLECTION_SUCCESS({ item: collection as CollectionResource })); - dispatch(collectionUpdaterActions.UPDATE_COLLECTION_SUCCESS()); - dispatch(updateDetails(collection)); - } - ); - }; - -export type CollectionUpdaterAction = UnionOf; diff --git a/src/store/collections/updater/collection-updater-reducer.ts b/src/store/collections/updater/collection-updater-reducer.ts deleted file mode 100644 index 97d010fca2..0000000000 --- a/src/store/collections/updater/collection-updater-reducer.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) The Arvados Authors. All rights reserved. -// -// SPDX-License-Identifier: AGPL-3.0 - -import { collectionUpdaterActions, CollectionUpdaterAction } from './collection-updater-action'; - -export interface CollectionUpdaterState { - opened: boolean; - uuid: string; -} - -const updateCollection = (state: CollectionUpdaterState, updater?: Partial) => ({ - ...state, - ...updater -}); - -const initialState: CollectionUpdaterState = { - opened: false, - uuid: '' -}; - -export const collectionUpdaterReducer = (state: CollectionUpdaterState = initialState, action: CollectionUpdaterAction) => { - return collectionUpdaterActions.match(action, { - OPEN_COLLECTION_UPDATER: ({ uuid }) => updateCollection(state, { uuid, opened: true }), - CLOSE_COLLECTION_UPDATER: () => updateCollection(state, { opened: false, uuid: "" }), - UPDATE_COLLECTION_SUCCESS: () => updateCollection(state, { opened: false, uuid: "" }), - default: () => state - }); -}; diff --git a/src/store/project/project-action.ts b/src/store/project/project-action.ts index 2017658916..ff66a9cf8a 100644 --- a/src/store/project/project-action.ts +++ b/src/store/project/project-action.ts @@ -9,17 +9,8 @@ import { FilterBuilder } from "~/common/api/filter-builder"; import { RootState } from "../store"; import { checkPresenceInFavorites } from "../favorites/favorites-actions"; import { ServiceRepository } from "~/services/services"; -import { projectPanelActions } from "~/store/project-panel/project-panel-action"; -import { updateDetails } from "~/store/details-panel/details-panel-action"; export const projectActions = unionize({ - OPEN_PROJECT_CREATOR: ofType<{ ownerUuid: string }>(), - CLOSE_PROJECT_CREATOR: ofType<{}>(), - CREATE_PROJECT: ofType>(), - CREATE_PROJECT_SUCCESS: ofType(), - OPEN_PROJECT_UPDATER: ofType<{ uuid: string}>(), - CLOSE_PROJECT_UPDATER: ofType<{}>(), - UPDATE_PROJECT_SUCCESS: ofType(), REMOVE_PROJECT: ofType(), PROJECTS_REQUEST: ofType(), PROJECTS_SUCCESS: ofType<{ projects: ProjectResource[], parentItemId?: string }>(), @@ -31,8 +22,6 @@ export const projectActions = unionize({ value: 'payload' }); -export const PROJECT_FORM_NAME = 'projectEditDialog'; - export const getProjectList = (parentUuid: string = '') => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { dispatch(projectActions.PROJECTS_REQUEST(parentUuid)); @@ -47,27 +36,4 @@ export const getProjectList = (parentUuid: string = '') => }); }; -export const createProject = (project: Partial) => - (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - const { ownerUuid } = getState().projects.creator; - const projectData = { ownerUuid, ...project }; - dispatch(projectActions.CREATE_PROJECT(projectData)); - return services.projectService - .create(projectData) - .then(project => dispatch(projectActions.CREATE_PROJECT_SUCCESS(project))); - }; - -export const updateProject = (project: Partial) => - (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(getProjectList(project.ownerUuid)); - dispatch(updateDetails(project)); - }); - }; - export type ProjectAction = UnionOf; diff --git a/src/store/project/project-reducer.test.ts b/src/store/project/project-reducer.test.ts index 8cd3121eec..56a6253465 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 bb0748657e..452f6be3e7 100644 --- a/src/store/project/project-reducer.ts +++ b/src/store/project/project-reducer.ts @@ -10,17 +10,9 @@ import { ProjectResource } from "~/models/project"; export type ProjectState = { items: Array>, - currentItemId: string, - creator: ProjectCreator, - updater: ProjectUpdater + currentItemId: string }; -interface ProjectCreator { - opened: boolean; - ownerUuid: string; - error?: string; -} - interface ProjectUpdater { opened: boolean; uuid: string; @@ -98,45 +90,14 @@ function updateProjectTree(tree: Array>, projects: Pro return items; } -const updateCreator = (state: ProjectState, creator: Partial) => ({ - ...state, - creator: { - ...state.creator, - ...creator - } -}); - -const updateProject = (state: ProjectState, updater?: Partial) => ({ - ...state, - updater: { - ...state.updater, - ...updater - } -}); - const initialState: ProjectState = { items: [], - currentItemId: "", - creator: { - opened: false, - ownerUuid: "" - }, - updater: { - opened: false, - uuid: '' - } + currentItemId: "" }; export const projectsReducer = (state: ProjectState = initialState, action: ProjectAction) => { return projectActions.match(action, { - OPEN_PROJECT_CREATOR: ({ ownerUuid }) => updateCreator(state, { ownerUuid, opened: true }), - CLOSE_PROJECT_CREATOR: () => updateCreator(state, { opened: false }), - CREATE_PROJECT: () => updateCreator(state, { error: undefined }), - CREATE_PROJECT_SUCCESS: () => updateCreator(state, { opened: false, ownerUuid: "" }), - 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-create-actions.ts b/src/store/projects/project-create-actions.ts new file mode 100644 index 0000000000..d1bc827ffb --- /dev/null +++ b/src/store/projects/project-create-actions.ts @@ -0,0 +1,56 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { Dispatch } from "redux"; +import { reset, startSubmit, stopSubmit, initialize } from 'redux-form'; +import { RootState } from '~/store/store'; +import { snackbarActions } from '~/store/snackbar/snackbar-actions'; +import { dialogActions } from "~/store/dialog/dialog-actions"; +import { projectPanelActions } from '~/store/project-panel/project-panel-action'; +import { getProjectList } from '~/store/project/project-action'; +import { getCommonResourceServiceError, CommonResourceServiceError } from '~/common/api/common-resource-service'; +import { ProjectResource } from '~/models/project'; +import { ServiceRepository } from '~/services/services'; + + +export interface ProjectCreateFormDialogData { + ownerUuid: string; + name: string; + description: string; +} + +export const PROJECT_CREATE_FORM_NAME = 'projectCreateFormName'; + +export const openProjectCreateDialog = (ownerUuid: string) => + (dispatch: Dispatch) => { + dispatch(initialize(PROJECT_CREATE_FORM_NAME, { ownerUuid })); + dispatch(dialogActions.OPEN_DIALOG({ id: PROJECT_CREATE_FORM_NAME, data: {} })); + }; + +export const addProject = (data: ProjectCreateFormDialogData) => + async (dispatch: Dispatch) => { + await dispatch(createProject(data)); + dispatch(snackbarActions.OPEN_SNACKBAR({ + message: "Project has been successfully created.", + hideDuration: 2000 + })); + }; + + +const createProject = (project: Partial) => + async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { + dispatch(startSubmit(PROJECT_CREATE_FORM_NAME)); + try { + const newProject = await services.projectService.create(project); + dispatch(getProjectList(newProject.ownerUuid)); + dispatch(projectPanelActions.REQUEST_ITEMS()); + dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_CREATE_FORM_NAME })); + dispatch(reset(PROJECT_CREATE_FORM_NAME)); + } catch (e) { + const error = getCommonResourceServiceError(e); + if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { + dispatch(stopSubmit(PROJECT_CREATE_FORM_NAME, { name: 'Project with the same name already exists.' })); + } + } + }; \ No newline at end of file diff --git a/src/store/move-project-dialog/move-project-dialog.ts b/src/store/projects/project-move-actions.ts similarity index 71% rename from src/store/move-project-dialog/move-project-dialog.ts rename to src/store/projects/project-move-actions.ts index 9e8e6f9b1a..52d17ac814 100644 --- a/src/store/move-project-dialog/move-project-dialog.ts +++ b/src/store/projects/project-move-actions.ts @@ -11,22 +11,22 @@ import { getCommonResourceServiceError, CommonResourceServiceError } from "~/com import { snackbarActions } from '~/store/snackbar/snackbar-actions'; import { projectPanelActions } from '~/store/project-panel/project-panel-action'; import { getProjectList } from '~/store/project/project-action'; -import { MoveToFormDialogData } from '../move-to-dialog/move-to-dialog'; +import { MoveToFormDialogData } from '~/store/move-to-dialog/move-to-dialog'; import { resetPickerProjectTree } from '~/store/project-tree-picker/project-tree-picker-actions'; -import { findTreeItem } from '../project/project-reducer'; +import { findTreeItem } from '~/store/project/project-reducer'; -export const MOVE_PROJECT_DIALOG = 'moveProjectDialog'; +export const PROJECT_MOVE_FORM_NAME = 'projectMoveFormName'; export const openMoveProjectDialog = (resource: { name: string, uuid: string }) => (dispatch: Dispatch) => { dispatch(resetPickerProjectTree()); - dispatch(initialize(MOVE_PROJECT_DIALOG, resource)); - dispatch(dialogActions.OPEN_DIALOG({ id: MOVE_PROJECT_DIALOG, data: {} })); + dispatch(initialize(PROJECT_MOVE_FORM_NAME, resource)); + dispatch(dialogActions.OPEN_DIALOG({ id: PROJECT_MOVE_FORM_NAME, data: {} })); }; export const moveProject = (resource: MoveToFormDialogData) => async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - dispatch(startSubmit(MOVE_PROJECT_DIALOG)); + dispatch(startSubmit(PROJECT_MOVE_FORM_NAME)); try { const project = await services.projectService.get(resource.uuid); await services.projectService.update(resource.uuid, { ...project, ownerUuid: resource.ownerUuid }); @@ -36,16 +36,16 @@ export const moveProject = (resource: MoveToFormDialogData) => if (findTreeItem(projects.items, resource.ownerUuid)) { dispatch(getProjectList(resource.ownerUuid)); } - dispatch(dialogActions.CLOSE_DIALOG({ id: MOVE_PROJECT_DIALOG })); + dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_MOVE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Project has been moved', hideDuration: 2000 })); } catch (e) { const error = getCommonResourceServiceError(e); if (error === CommonResourceServiceError.UNIQUE_VIOLATION) { - dispatch(stopSubmit(MOVE_PROJECT_DIALOG, { ownerUuid: 'A project with the same name already exists in the target project.' })); + dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'A project with the same name already exists in the target project.' })); } else if (error === CommonResourceServiceError.OWNERSHIP_CYCLE) { - dispatch(stopSubmit(MOVE_PROJECT_DIALOG, { ownerUuid: 'Cannot move a project into itself.' })); + dispatch(stopSubmit(PROJECT_MOVE_FORM_NAME, { ownerUuid: 'Cannot move a project into itself.' })); } else { - dispatch(dialogActions.CLOSE_DIALOG({ id: MOVE_PROJECT_DIALOG })); + dispatch(dialogActions.CLOSE_DIALOG({ id: PROJECT_MOVE_FORM_NAME })); dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Could not move the project.', hideDuration: 2000 })); } } diff --git a/src/store/projects/project-update-actions.ts b/src/store/projects/project-update-actions.ts new file mode 100644 index 0000000000..e674d2960d --- /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(updateProject(data)); + dispatch(snackbarActions.OPEN_SNACKBAR({ + message: "Project has been successfully updated.", + hideDuration: 2000 + })); + }; + +export const updateProject = (project: Partial) => + 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(getProjectList(updatedProject.ownerUuid)); + dispatch(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/collection-partial-copy-dialog/collection-partial-copy-dialog.tsx b/src/views-components/collection-partial-copy-dialog/collection-partial-copy-dialog.tsx index e230470b41..86fc360ef8 100644 --- a/src/views-components/collection-partial-copy-dialog/collection-partial-copy-dialog.tsx +++ b/src/views-components/collection-partial-copy-dialog/collection-partial-copy-dialog.tsx @@ -6,9 +6,9 @@ import * as React from "react"; import { compose } from "redux"; import { reduxForm, InjectedFormProps } from 'redux-form'; import { withDialog, WithDialogProps } from '~/store/dialog/with-dialog'; -import { CollectionPartialCopyFields } from '../form-dialog/collection-form-dialog'; -import { FormDialog } from '~/components/form-dialog/form-dialog'; import { COLLECTION_PARTIAL_COPY, doCollectionPartialCopy, CollectionPartialCopyFormData } from '~/store/collection-panel/collection-panel-files/collection-panel-files-actions'; +import { CollectionPartialCopyFields } from '~/views-components/form-fields/collection-form-fields'; +import { FormDialog } from '~/components/form-dialog/form-dialog'; export const CollectionPartialCopyDialog = compose( withDialog(COLLECTION_PARTIAL_COPY), diff --git a/src/views-components/context-menu/action-sets/collection-action-set.ts b/src/views-components/context-menu/action-sets/collection-action-set.ts index 2d3cd55935..b3fdc3fbab 100644 --- a/src/views-components/context-menu/action-sets/collection-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-action-set.ts @@ -6,9 +6,9 @@ import { ContextMenuActionSet } from "../context-menu-action-set"; import { ToggleFavoriteAction } from "../actions/favorite-action"; import { toggleFavorite } from "~/store/favorites/favorites-actions"; import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, ProvenanceGraphIcon, AdvancedIcon, RemoveIcon } from "~/components/icon/icon"; -import { openUpdater } from "~/store/collections/updater/collection-updater-action"; +import { openCollectionUpdateDialog } from "~/store/collections/collection-update-actions"; import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action"; -import { openMoveCollectionDialog } from '~/store/move-collection-dialog/move-collection-dialog'; +import { openMoveCollectionDialog } from '~/store/collections/collection-move-actions'; import { openCollectionCopyDialog } from "~/store/collections/collection-copy-actions"; export const collectionActionSet: ContextMenuActionSet = [[ @@ -16,7 +16,7 @@ export const collectionActionSet: ContextMenuActionSet = [[ icon: RenameIcon, name: "Edit collection", execute: (dispatch, resource) => { - dispatch(openUpdater(resource)); + dispatch(openCollectionUpdateDialog(resource)); } }, { diff --git a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts index fbabeee312..a299b9370c 100644 --- a/src/views-components/context-menu/action-sets/collection-resource-action-set.ts +++ b/src/views-components/context-menu/action-sets/collection-resource-action-set.ts @@ -6,9 +6,9 @@ import { ContextMenuActionSet } from "../context-menu-action-set"; import { ToggleFavoriteAction } from "../actions/favorite-action"; import { toggleFavorite } from "~/store/favorites/favorites-actions"; import { RenameIcon, ShareIcon, MoveToIcon, CopyIcon, DetailsIcon, RemoveIcon } from "~/components/icon/icon"; -import { openUpdater } from "~/store/collections/updater/collection-updater-action"; +import { openCollectionUpdateDialog } from "~/store/collections/collection-update-actions"; import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action"; -import { openMoveCollectionDialog } from '~/store/move-collection-dialog/move-collection-dialog'; +import { openMoveCollectionDialog } from '~/store/collections/collection-move-actions'; import { openCollectionCopyDialog } from '~/store/collections/collection-copy-actions'; export const collectionResourceActionSet: ContextMenuActionSet = [[ @@ -16,7 +16,7 @@ export const collectionResourceActionSet: ContextMenuActionSet = [[ icon: RenameIcon, name: "Edit collection", execute: (dispatch, resource) => { - dispatch(openUpdater(resource)); + dispatch(openCollectionUpdateDialog(resource)); } }, { 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 8ae60c8f58..bc5d739ab3 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 @@ -5,29 +5,28 @@ import { reset, initialize } from "redux-form"; import { ContextMenuActionSet } from "../context-menu-action-set"; -import { projectActions, PROJECT_FORM_NAME } from "~/store/project/project-action"; import { NewProjectIcon, RenameIcon, CopyIcon, MoveToIcon } from "~/components/icon/icon"; import { ToggleFavoriteAction } from "../actions/favorite-action"; import { toggleFavorite } from "~/store/favorites/favorites-actions"; import { favoritePanelActions } from "~/store/favorite-panel/favorite-panel-action"; -import { PROJECT_CREATE_DIALOG } from "../../dialog-create/dialog-project-create"; -import { openMoveProjectDialog } from '~/store/move-project-dialog/move-project-dialog'; +import { openMoveProjectDialog } from '~/store/projects/project-move-actions'; +import { PROJECT_CREATE_FORM_NAME, openProjectCreateDialog } from '~/store/projects/project-create-actions'; +import { openProjectUpdateDialog } from '~/store/projects/project-update-actions'; export const projectActionSet: ContextMenuActionSet = [[ { icon: NewProjectIcon, name: "New project", execute: (dispatch, resource) => { - dispatch(reset(PROJECT_CREATE_DIALOG)); - dispatch(projectActions.OPEN_PROJECT_CREATOR({ ownerUuid: resource.uuid })); + dispatch(reset(PROJECT_CREATE_FORM_NAME)); + dispatch(openProjectCreateDialog(resource.uuid)); } }, { 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(openProjectUpdateDialog(resource)); } }, { diff --git a/src/views-components/context-menu/action-sets/root-project-action-set.ts b/src/views-components/context-menu/action-sets/root-project-action-set.ts index de3b954f4c..2c71abc41e 100644 --- a/src/views-components/context-menu/action-sets/root-project-action-set.ts +++ b/src/views-components/context-menu/action-sets/root-project-action-set.ts @@ -6,26 +6,25 @@ import { reset } from "redux-form"; import { ContextMenuActionSet } from "../context-menu-action-set"; import { projectActions } from "~/store/project/project-action"; -import { collectionCreateActions } from "~/store/collections/creator/collection-creator-action"; -import { PROJECT_CREATE_DIALOG } from "../../dialog-create/dialog-project-create"; -import { COLLECTION_CREATE_DIALOG } from "../../dialog-create/dialog-collection-create"; +import { COLLECTION_CREATE_FORM_NAME, openCollectionCreateDialog } from '~/store/collections/collection-create-actions'; import { NewProjectIcon, CollectionIcon } from "~/components/icon/icon"; +import { PROJECT_CREATE_FORM_NAME, openProjectCreateDialog } from '~/store/projects/project-create-actions'; export const rootProjectActionSet: ContextMenuActionSet = [[ { icon: NewProjectIcon, name: "New project", execute: (dispatch, resource) => { - dispatch(reset(PROJECT_CREATE_DIALOG)); - dispatch(projectActions.OPEN_PROJECT_CREATOR({ ownerUuid: resource.uuid })); + dispatch(reset(PROJECT_CREATE_FORM_NAME)); + dispatch(openProjectCreateDialog(resource.uuid)); } }, { icon: CollectionIcon, name: "New Collection", execute: (dispatch, resource) => { - dispatch(reset(COLLECTION_CREATE_DIALOG)); - dispatch(collectionCreateActions.OPEN_COLLECTION_CREATOR({ ownerUuid: resource.uuid })); + dispatch(reset(COLLECTION_CREATE_FORM_NAME)); + dispatch(openCollectionCreateDialog(resource.uuid)); } } ]]; diff --git a/src/views-components/create-collection-dialog/create-collection-dialog.tsx b/src/views-components/create-collection-dialog/create-collection-dialog.tsx deleted file mode 100644 index 94eb82f94e..0000000000 --- a/src/views-components/create-collection-dialog/create-collection-dialog.tsx +++ /dev/null @@ -1,44 +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 { DialogCollectionCreate } from "../dialog-create/dialog-collection-create"; -import { collectionCreateActions, createCollection } from "~/store/collections/creator/collection-creator-action"; -import { snackbarActions } from "~/store/snackbar/snackbar-actions"; -import { UploadFile } from "~/store/collections/uploader/collection-uploader-actions"; -import { projectPanelActions } from "~/store/project-panel/project-panel-action"; - -const mapStateToProps = (state: RootState) => ({ - open: state.collections.creator.opened -}); - -const mapDispatchToProps = (dispatch: Dispatch) => ({ - handleClose: () => { - dispatch(collectionCreateActions.CLOSE_COLLECTION_CREATOR()); - }, - onSubmit: (data: { name: string, description: string }, files: UploadFile[]) => { - return dispatch(addCollection(data, files.map(f => f.file))) - .catch((e: any) => { - throw new SubmissionError({ name: e.errors.join("").includes("UniqueViolation") ? "Collection with this name already exists." : "" }); - }); - } -}); - -const addCollection = (data: { name: string, description: string }, files: File[]) => - (dispatch: Dispatch) => { - return dispatch(createCollection(data, files)).then(() => { - dispatch(snackbarActions.OPEN_SNACKBAR({ - message: "Collection has been successfully created.", - hideDuration: 2000 - })); - dispatch(projectPanelActions.REQUEST_ITEMS()); - }); - }; - -export const CreateCollectionDialog = connect(mapStateToProps, mapDispatchToProps)(DialogCollectionCreate); - diff --git a/src/views-components/create-project-dialog/create-project-dialog.tsx b/src/views-components/create-project-dialog/create-project-dialog.tsx deleted file mode 100644 index 43f56ed894..0000000000 --- a/src/views-components/create-project-dialog/create-project-dialog.tsx +++ /dev/null @@ -1,44 +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 { DialogProjectCreate } from "../dialog-create/dialog-project-create"; -import { projectActions, createProject, getProjectList } from "~/store/project/project-action"; -import { projectPanelActions } from "~/store/project-panel/project-panel-action"; -import { snackbarActions } from "~/store/snackbar/snackbar-actions"; - -const mapStateToProps = (state: RootState) => ({ - open: state.projects.creator.opened -}); - -const addProject = (data: { name: string, description: string }) => - (dispatch: Dispatch, getState: () => RootState) => { - const { ownerUuid } = getState().projects.creator; - return dispatch(createProject(data)).then(() => { - dispatch(snackbarActions.OPEN_SNACKBAR({ - message: "Project has been successfully created.", - hideDuration: 2000 - })); - dispatch(projectPanelActions.REQUEST_ITEMS()); - dispatch(getProjectList(ownerUuid)); - }); - }; - -const mapDispatchToProps = (dispatch: Dispatch) => ({ - handleClose: () => { - dispatch(projectActions.CLOSE_PROJECT_CREATOR()); - }, - onSubmit: (data: { name: string, description: string }) => { - return dispatch(addProject(data)) - .catch((e: any) => { - throw new SubmissionError({ name: e.errors.join("").includes("UniqueViolation") ? "Project with this name already exists." : "" }); - }); - } -}); - -export const CreateProjectDialog = connect(mapStateToProps, mapDispatchToProps)(DialogProjectCreate); diff --git a/src/views-components/dialog-collection-copy/dialog-collection-copy.tsx b/src/views-components/dialog-copy/dialog-collection-copy.tsx similarity index 100% rename from src/views-components/dialog-collection-copy/dialog-collection-copy.tsx rename to src/views-components/dialog-copy/dialog-collection-copy.tsx diff --git a/src/views-components/dialog-create/dialog-collection-create.tsx b/src/views-components/dialog-create/dialog-collection-create.tsx index af0e33f1b4..2fb007b8a6 100644 --- a/src/views-components/dialog-create/dialog-collection-create.tsx +++ b/src/views-components/dialog-create/dialog-collection-create.tsx @@ -3,113 +3,38 @@ // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; -import { reduxForm, Field } from 'redux-form'; -import { compose } from 'redux'; -import { TextField } from '~/components/text-field/text-field'; -import { Dialog, DialogActions, DialogContent, DialogTitle } from '@material-ui/core/'; -import { Button, StyleRulesCallback, WithStyles, withStyles, CircularProgress } from '@material-ui/core'; - -import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION } from '~/validators/validators'; -import { FileUpload } from "~/components/file-upload/file-upload"; -import { connect, DispatchProp } from "react-redux"; -import { RootState } from "~/store/store"; +import { InjectedFormProps } from 'redux-form'; +import { WithDialogProps } from '~/store/dialog/with-dialog'; +import { CollectionCreateFormDialogData } from '~/store/collections/collection-create-actions'; import { collectionUploaderActions, UploadFile } from "~/store/collections/uploader/collection-uploader-actions"; - -type CssRules = "button" | "lastButton" | "formContainer" | "createProgress" | "dialogActions"; - -const styles: StyleRulesCallback = theme => ({ - button: { - marginLeft: theme.spacing.unit - }, - lastButton: { - marginLeft: theme.spacing.unit, - marginRight: "20px", - }, - formContainer: { - display: "flex", - flexDirection: "column", - }, - createProgress: { - position: "absolute", - minWidth: "20px", - right: "110px" - }, - dialogActions: { - marginBottom: theme.spacing.unit * 3 - } -}); - -interface DialogCollectionDataProps { - open: boolean; - handleSubmit: any; - submitting: boolean; - invalid: boolean; - pristine: boolean; - files: UploadFile[]; -} - -interface DialogCollectionActionProps { - handleClose: () => void; - onSubmit: (data: { name: string, description: string }, files: UploadFile[]) => void; -} - -type DialogCollectionProps = DialogCollectionDataProps & DialogCollectionActionProps & DispatchProp & WithStyles; - -export const COLLECTION_CREATE_DIALOG = "collectionCreateDialog"; - -export const DialogCollectionCreate = compose( - connect((state: RootState) => ({ - files: state.collections.uploader - })), - reduxForm({ form: COLLECTION_CREATE_DIALOG }), - withStyles(styles))( - class DialogCollectionCreate extends React.Component { - render() { - const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine, files } = this.props; - const busy = submitting || files.reduce( - (prev, curr) => prev + (curr.loaded > 0 && curr.loaded < curr.total ? 1 : 0), 0 - ) > 0; - return ( - - onSubmit(data, files))}> - Create a collection - - - - this.props.dispatch(collectionUploaderActions.SET_UPLOAD_FILES(files))} /> - - - - - {busy && } - - - - ); - } - } - ); +import { FormDialog } from '~/components/form-dialog/form-dialog'; +import { CollectionNameField, CollectionDescriptionField } from '~/views-components/form-fields/collection-form-fields'; +import { FileUpload } from '~/components/file-upload/file-upload'; + +// interface DialogCollectionDataProps { +// open: boolean; +// handleSubmit: any; +// submitting: boolean; +// invalid: boolean; +// pristine: boolean; +// files: UploadFile[]; +// } + +type DialogCollectionProps = WithDialogProps<{}> & InjectedFormProps; + +export const DialogCollectionCreate = (props: DialogCollectionProps) => + ; + +const CollectionAddFields = () => + + + {/* this.props.dispatch(collectionUploaderActions.SET_UPLOAD_FILES(files))} /> */} +; \ No newline at end of file diff --git a/src/views-components/dialog-create/dialog-project-create.tsx b/src/views-components/dialog-create/dialog-project-create.tsx index e77114b369..8c1d3800a0 100644 --- a/src/views-components/dialog-create/dialog-project-create.tsx +++ b/src/views-components/dialog-create/dialog-project-create.tsx @@ -3,100 +3,23 @@ // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; -import { reduxForm, Field } from 'redux-form'; -import { compose } from 'redux'; -import { TextField } from '~/components/text-field/text-field'; -import { Dialog, DialogActions, DialogContent, DialogTitle } from '@material-ui/core/'; -import { Button, StyleRulesCallback, WithStyles, withStyles, CircularProgress } from '@material-ui/core'; +import { InjectedFormProps } from 'redux-form'; +import { WithDialogProps } from '~/store/dialog/with-dialog'; +import { ProjectCreateFormDialogData } from '~/store/projects/project-create-actions'; +import { FormDialog } from '~/components/form-dialog/form-dialog'; +import { ProjectNameField, ProjectDescriptionField } from '~/views-components/form-fields/project-form-fields'; -import { PROJECT_NAME_VALIDATION, PROJECT_DESCRIPTION_VALIDATION } from '~/validators/validators'; +type DialogCollectionProps = WithDialogProps<{}> & InjectedFormProps; -type CssRules = "button" | "lastButton" | "formContainer" | "dialog" | "dialogTitle" | "createProgress" | "dialogActions"; +export const DialogProjectCreate = (props: DialogCollectionProps) => + ; -const styles: StyleRulesCallback = theme => ({ - button: { - marginLeft: theme.spacing.unit - }, - lastButton: { - marginLeft: theme.spacing.unit, - marginRight: "20px", - }, - formContainer: { - display: "flex", - flexDirection: "column", - marginTop: "20px", - }, - dialogTitle: { - paddingBottom: "0" - }, - dialog: { - minWidth: "600px", - minHeight: "320px" - }, - createProgress: { - position: "absolute", - minWidth: "20px", - right: "95px" - }, - dialogActions: { - marginBottom: "24px" - } -}); -interface DialogProjectProps { - open: boolean; - handleClose: () => void; - onSubmit: (data: { name: string, description: string }) => void; - handleSubmit: any; - submitting: boolean; - invalid: boolean; - pristine: boolean; -} - -export const PROJECT_CREATE_DIALOG = "projectCreateDialog"; - -export const DialogProjectCreate = compose( - reduxForm({ form: PROJECT_CREATE_DIALOG }), - withStyles(styles))( - class DialogProjectCreate extends React.Component> { - render() { - const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine } = this.props; - - return ( - -
-
onSubmit(data))}> - Create a - project - - - - - - - - {submitting && } - -
-
-
- ); - } - } -); +const ProjectAddFields = () => + + +; diff --git a/src/views-components/dialog-forms/copy-collection-dialog.ts b/src/views-components/dialog-forms/copy-collection-dialog.ts index 9f25c14b81..ee6293abb8 100644 --- a/src/views-components/dialog-forms/copy-collection-dialog.ts +++ b/src/views-components/dialog-forms/copy-collection-dialog.ts @@ -6,7 +6,7 @@ import { compose } from "redux"; import { withDialog } from "~/store/dialog/with-dialog"; import { reduxForm } from 'redux-form'; import { COLLECTION_COPY_FORM_NAME, CollectionCopyFormDialogData, copyCollection } from '~/store/collections/collection-copy-actions'; -import { DialogCollectionCopy } from "~/views-components/dialog-collection-copy/dialog-collection-copy"; +import { DialogCollectionCopy } from "~/views-components/dialog-copy/dialog-collection-copy"; export const CopyCollectionDialog = compose( withDialog(COLLECTION_COPY_FORM_NAME), diff --git a/src/views-components/dialog-forms/create-collection-dialog.ts b/src/views-components/dialog-forms/create-collection-dialog.ts new file mode 100644 index 0000000000..d2699d8398 --- /dev/null +++ b/src/views-components/dialog-forms/create-collection-dialog.ts @@ -0,0 +1,22 @@ +// 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 { addCollection, COLLECTION_CREATE_FORM_NAME, CollectionCreateFormDialogData } from '~/store/collections/collection-create-actions'; +import { UploadFile } from "~/store/collections/uploader/collection-uploader-actions"; +import { DialogCollectionCreate } from "~/views-components/dialog-create/dialog-collection-create"; + +export const CreateCollectionDialog = compose( + withDialog(COLLECTION_CREATE_FORM_NAME), + reduxForm({ + form: COLLECTION_CREATE_FORM_NAME, + onSubmit: (data, dispatch) => { + dispatch(addCollection(data)); + } + }) +)(DialogCollectionCreate); + +// onSubmit: (data: { name: string, description: string }, files: UploadFile[]) => void; \ No newline at end of file diff --git a/src/views-components/dialog-forms/create-project-dialog.ts b/src/views-components/dialog-forms/create-project-dialog.ts new file mode 100644 index 0000000000..2e87517c50 --- /dev/null +++ b/src/views-components/dialog-forms/create-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 { addProject, PROJECT_CREATE_FORM_NAME, ProjectCreateFormDialogData } from '~/store/projects/project-create-actions'; +import { DialogProjectCreate } from '~/views-components/dialog-create/dialog-project-create'; + +export const CreateProjectDialog = compose( + withDialog(PROJECT_CREATE_FORM_NAME), + reduxForm({ + form: PROJECT_CREATE_FORM_NAME, + onSubmit: (data, dispatch) => { + dispatch(addProject(data)); + } + }) +)(DialogProjectCreate); \ No newline at end of file diff --git a/src/views-components/move-collection-dialog/move-collection-dialog.ts b/src/views-components/dialog-forms/move-collection-dialog.ts similarity index 63% rename from src/views-components/move-collection-dialog/move-collection-dialog.ts rename to src/views-components/dialog-forms/move-collection-dialog.ts index 783f0c7847..38d6d03392 100644 --- a/src/views-components/move-collection-dialog/move-collection-dialog.ts +++ b/src/views-components/dialog-forms/move-collection-dialog.ts @@ -5,16 +5,16 @@ import { compose } from "redux"; import { withDialog } from "~/store/dialog/with-dialog"; import { reduxForm } from 'redux-form'; -import { MoveToFormDialog } from '../move-to-dialog/move-to-dialog'; -import { MOVE_COLLECTION_DIALOG, moveCollection } from '~/store/move-collection-dialog/move-collection-dialog'; +import { DialogMoveTo } from '~/views-components/dialog-move/dialog-move-to'; +import { COLLECTION_MOVE_FORM_NAME, moveCollection } from '~/store/collections/collection-move-actions'; import { MoveToFormDialogData } from '~/store/move-to-dialog/move-to-dialog'; export const MoveCollectionDialog = compose( - withDialog(MOVE_COLLECTION_DIALOG), + withDialog(COLLECTION_MOVE_FORM_NAME), reduxForm({ - form: MOVE_COLLECTION_DIALOG, + form: COLLECTION_MOVE_FORM_NAME, onSubmit: (data, dispatch) => { dispatch(moveCollection(data)); } }) -)(MoveToFormDialog); +)(DialogMoveTo); diff --git a/src/views-components/move-project-dialog/move-project-dialog.ts b/src/views-components/dialog-forms/move-project-dialog.ts similarity index 59% rename from src/views-components/move-project-dialog/move-project-dialog.ts rename to src/views-components/dialog-forms/move-project-dialog.ts index 9ec67486f6..dd102b145f 100644 --- a/src/views-components/move-project-dialog/move-project-dialog.ts +++ b/src/views-components/dialog-forms/move-project-dialog.ts @@ -5,18 +5,18 @@ import { compose } from "redux"; import { withDialog } from "~/store/dialog/with-dialog"; import { reduxForm } from 'redux-form'; -import { MOVE_PROJECT_DIALOG } from '~/store/move-project-dialog/move-project-dialog'; -import { moveProject } from '~/store/move-project-dialog/move-project-dialog'; +import { PROJECT_MOVE_FORM_NAME } from '~/store/projects/project-move-actions'; +import { moveProject } from '~/store/projects/project-move-actions'; import { MoveToFormDialogData } from '~/store/move-to-dialog/move-to-dialog'; -import { MoveToFormDialog } from '../move-to-dialog/move-to-dialog'; +import { DialogMoveTo } from '~/views-components/dialog-move/dialog-move-to'; export const MoveProjectDialog = compose( - withDialog(MOVE_PROJECT_DIALOG), + withDialog(PROJECT_MOVE_FORM_NAME), reduxForm({ - form: MOVE_PROJECT_DIALOG, + form: PROJECT_MOVE_FORM_NAME, onSubmit: (data, dispatch) => { dispatch(moveProject(data)); } }) -)(MoveToFormDialog); +)(DialogMoveTo); diff --git a/src/views-components/dialog-forms/update-collection-dialog.ts b/src/views-components/dialog-forms/update-collection-dialog.ts new file mode 100644 index 0000000000..2c4296d816 --- /dev/null +++ b/src/views-components/dialog-forms/update-collection-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 { DialogCollectionUpdate } from '~/views-components/dialog-update/dialog-collection-update'; +import { editCollection, COLLECTION_UPDATE_FORM_NAME, CollectionUpdateFormDialogData } from '~/store/collections/collection-update-actions'; + +export const UpdateCollectionDialog = compose( + withDialog(COLLECTION_UPDATE_FORM_NAME), + reduxForm({ + form: COLLECTION_UPDATE_FORM_NAME, + onSubmit: (data, dispatch) => { + dispatch(editCollection(data)); + } + }) +)(DialogCollectionUpdate); \ No newline at end of file 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 0000000000..598d0b19f2 --- /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({ + form: PROJECT_UPDATE_FORM_NAME, + onSubmit: (data, dispatch) => { + dispatch(editProject(data)); + } + }) +)(DialogProjectUpdate); \ No newline at end of file diff --git a/src/views-components/move-to-dialog/move-to-dialog.tsx b/src/views-components/dialog-move/dialog-move-to.tsx similarity index 88% rename from src/views-components/move-to-dialog/move-to-dialog.tsx rename to src/views-components/dialog-move/dialog-move-to.tsx index d8f89d39ac..425b9e462a 100644 --- a/src/views-components/move-to-dialog/move-to-dialog.tsx +++ b/src/views-components/dialog-move/dialog-move-to.tsx @@ -10,7 +10,7 @@ import { ProjectTreePickerField } from '~/views-components/project-tree-picker/p import { MOVE_TO_VALIDATION } from '~/validators/validators'; import { MoveToFormDialogData } from '~/store/move-to-dialog/move-to-dialog'; -export const MoveToFormDialog = (props: WithDialogProps & InjectedFormProps) => +export const DialogMoveTo = (props: WithDialogProps & InjectedFormProps) => = (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 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; - -export const DialogCollectionUpdate = compose( - reduxForm({ form: COLLECTION_FORM_NAME }), - withStyles(styles))( - - class DialogCollectionUpdate extends React.Component { - - render() { - const { classes, open, handleClose, handleSubmit, onSubmit, submitting, invalid, pristine } = this.props; - return ( - - -
onSubmit(data))}> - Edit Collection - - - - - - -
- - {submitting && } -
-
-
-
- ); - } - } - ); +import { InjectedFormProps } from 'redux-form'; +import { WithDialogProps } from '~/store/dialog/with-dialog'; +import { CollectionUpdateFormDialogData } from '~/store/collections/collection-update-actions'; +import { FormDialog } from '~/components/form-dialog/form-dialog'; +import { CollectionNameField, CollectionDescriptionField } from '~/views-components/form-fields/collection-form-fields'; + +type DialogCollectionProps = WithDialogProps<{}> & InjectedFormProps; + +export const DialogCollectionUpdate = (props: DialogCollectionProps) => + ; + +const CollectionEditFields = () => + + +; diff --git a/src/views-components/dialog-update/dialog-project-update.tsx b/src/views-components/dialog-update/dialog-project-update.tsx index b5e788c026..49b97a6f9a 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 = (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; - -export const DialogProjectUpdate = compose( - reduxForm({ form: PROJECT_FORM_NAME }), - withStyles(styles))( - - class DialogProjectUpdate extends React.Component { - render() { - const { handleSubmit, handleClose, onSubmit, open, classes, submitting, invalid, pristine } = this.props; - return -
onSubmit(data))}> - Edit Project - - - - - - -
- - {submitting && } -
-
-
-
; - } - } - ); +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; + +export const DialogProjectUpdate = (props: DialogProjectProps) => + ; + +const ProjectEditFields = () => + + +; diff --git a/src/views-components/form-dialog/collection-form-dialog.tsx b/src/views-components/form-fields/collection-form-fields.tsx similarity index 93% rename from src/views-components/form-dialog/collection-form-dialog.tsx rename to src/views-components/form-fields/collection-form-fields.tsx index d5f1d8521a..10c807b621 100644 --- a/src/views-components/form-dialog/collection-form-dialog.tsx +++ b/src/views-components/form-fields/collection-form-fields.tsx @@ -6,7 +6,7 @@ import * as React from "react"; import { Field, WrappedFieldProps } from "redux-form"; import { TextField } from "~/components/text-field/text-field"; import { COLLECTION_NAME_VALIDATION, COLLECTION_DESCRIPTION_VALIDATION, COLLECTION_PROJECT_VALIDATION } from "~/validators/validators"; -import { ProjectTreePicker } from "../project-tree-picker/project-tree-picker"; +import { ProjectTreePicker } from "~/views-components/project-tree-picker/project-tree-picker"; export const CollectionPartialCopyFields = () =>
diff --git a/src/views-components/form-fields/project-form-fields.tsx b/src/views-components/form-fields/project-form-fields.tsx new file mode 100644 index 0000000000..630877e72f --- /dev/null +++ b/src/views-components/form-fields/project-form-fields.tsx @@ -0,0 +1,22 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import * as React from "react"; +import { Field } from "redux-form"; +import { TextField } from "~/components/text-field/text-field"; +import { PROJECT_NAME_VALIDATION, PROJECT_DESCRIPTION_VALIDATION } from "~/validators/validators"; + +export const ProjectNameField = () => + ; + +export const ProjectDescriptionField = () => + ; \ No newline at end of file diff --git a/src/views-components/update-collection-dialog/update-collection-dialog..tsx b/src/views-components/update-collection-dialog/update-collection-dialog..tsx deleted file mode 100644 index 239df58952..0000000000 --- a/src/views-components/update-collection-dialog/update-collection-dialog..tsx +++ /dev/null @@ -1,44 +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 { collectionUpdaterActions, updateCollection } from "~/store/collections/updater/collection-updater-action"; -import { dataExplorerActions } from "~/store/data-explorer/data-explorer-action"; -import { PROJECT_PANEL_ID } from "~/views/project-panel/project-panel"; -import { DialogCollectionUpdate } from "../dialog-update/dialog-collection-update"; - -const mapStateToProps = (state: RootState) => ({ - open: state.collections.updater.opened -}); - -const mapDispatchToProps = (dispatch: Dispatch) => ({ - handleClose: () => { - dispatch(collectionUpdaterActions.CLOSE_COLLECTION_UPDATER()); - }, - onSubmit: (data: { name: string, description: string }) => { - return dispatch(editCollection(data)) - .catch((e: any) => { - if(e.errors) { - throw new SubmissionError({ name: e.errors.join("").includes("UniqueViolation") ? "Collection with this name already exists." : "" }); - } - }); - } -}); - -const editCollection = (data: { name: string, description: string }) => - (dispatch: Dispatch) => { - return dispatch(updateCollection(data)).then(() => { - dispatch(snackbarActions.OPEN_SNACKBAR({ - message: "Collection has been successfully updated.", - hideDuration: 2000 - })); - dispatch(dataExplorerActions.REQUEST_ITEMS({ id: PROJECT_PANEL_ID })); - }); - }; - -export const UpdateCollectionDialog = connect(mapStateToProps, mapDispatchToProps)(DialogCollectionUpdate); 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 0ea23c8fe1..0000000000 --- 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(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(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 7b9701ad46..4640323f09 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -21,11 +21,8 @@ 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 { projectActions } from "~/store/project/project-action"; -import { collectionCreateActions } from '~/store/collections/creator/collection-creator-action'; -import { ProjectPanel } from "~/views/project-panel/project-panel"; import { DetailsPanel } from '~/views-components/details-panel/details-panel'; import { ArvadosTheme } from '~/common/custom-theme'; -import { CreateProjectDialog } from "~/views-components/create-project-dialog/create-project-dialog"; import { detailsPanelActions, loadDetails } from "~/store/details-panel/details-panel-action"; import { contextMenuActions } from "~/store/context-menu/context-menu-actions"; @@ -37,23 +34,27 @@ import { FavoritePanel } from "../favorite-panel/favorite-panel"; import { CurrentTokenDialog } from '~/views-components/current-token-dialog/current-token-dialog'; import { Snackbar } from '~/views-components/snackbar/snackbar'; import { favoritePanelActions } from '~/store/favorite-panel/favorite-panel-action'; -import { CreateCollectionDialog } from '~/views-components/create-collection-dialog/create-collection-dialog'; import { CollectionPanel } from '../collection-panel/collection-panel'; import { loadCollection, loadCollectionTags } from '~/store/collection-panel/collection-panel-action'; import { getCollectionUrl } from '~/models/collection'; -import { UpdateCollectionDialog } from '~/views-components/update-collection-dialog/update-collection-dialog.'; -import { UpdateProjectDialog } from '~/views-components/update-project-dialog/update-project-dialog'; + +import { PROJECT_CREATE_FORM_NAME, openProjectCreateDialog } from '~/store/projects/project-create-actions'; +import { COLLECTION_CREATE_FORM_NAME, openCollectionCreateDialog } from '~/store/collections/collection-create-actions'; +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/dialog-forms/update-project-dialog'; + +import { ProjectPanel } from "~/views/project-panel/project-panel"; import { AuthService } from "~/services/auth-service/auth-service"; import { RenameFileDialog } from '~/views-components/rename-file-dialog/rename-file-dialog'; import { FileRemoveDialog } from '~/views-components/file-remove-dialog/file-remove-dialog'; import { MultipleFilesRemoveDialog } from '~/views-components/file-remove-dialog/multiple-files-remove-dialog'; import { DialogCollectionCreateWithSelectedFile } from '~/views-components/create-collection-dialog-with-selected/create-collection-dialog-with-selected'; -import { COLLECTION_CREATE_DIALOG } from '~/views-components/dialog-create/dialog-collection-create'; -import { PROJECT_CREATE_DIALOG } from '~/views-components/dialog-create/dialog-project-create'; import { UploadCollectionFilesDialog } from '~/views-components/upload-collection-files-dialog/upload-collection-files-dialog'; -import { CollectionPartialCopyDialog } from '../../views-components/collection-partial-copy-dialog/collection-partial-copy-dialog'; -import { MoveProjectDialog } from '~/views-components/move-project-dialog/move-project-dialog'; -import { MoveCollectionDialog } from '~/views-components/move-collection-dialog/move-collection-dialog'; +import { CollectionPartialCopyDialog } from '~/views-components/collection-partial-copy-dialog/collection-partial-copy-dialog'; +import { MoveProjectDialog } from '~/views-components/dialog-forms/move-project-dialog'; +import { MoveCollectionDialog } from '~/views-components/dialog-forms/move-collection-dialog'; import { CopyCollectionDialog } from '~/views-components/dialog-forms/copy-collection-dialog'; const DRAWER_WITDH = 240; @@ -397,13 +398,13 @@ export const Workbench = withStyles(styles)( } handleProjectCreationDialogOpen = (itemUuid: string) => { - this.props.dispatch(reset(PROJECT_CREATE_DIALOG)); - this.props.dispatch(projectActions.OPEN_PROJECT_CREATOR({ ownerUuid: itemUuid })); + this.props.dispatch(reset(PROJECT_CREATE_FORM_NAME)); + this.props.dispatch(openProjectCreateDialog(itemUuid)); } handleCollectionCreationDialogOpen = (itemUuid: string) => { - this.props.dispatch(reset(COLLECTION_CREATE_DIALOG)); - this.props.dispatch(collectionCreateActions.OPEN_COLLECTION_CREATOR({ ownerUuid: itemUuid })); + this.props.dispatch(reset(COLLECTION_CREATE_FORM_NAME)); + this.props.dispatch(openCollectionCreateDialog(itemUuid)); } openContextMenu = (event: React.MouseEvent, resource: { name: string; uuid: string; description?: string; kind: ContextMenuKind; }) => {