From 5114536622bd9abf5bd729629b9249ccd11fd3ce Mon Sep 17 00:00:00 2001 From: Michal Klobukowski Date: Mon, 9 Jul 2018 17:53:23 +0200 Subject: [PATCH] Connect project dialog to the store Feature #13694 Arvados-DCO-1.1-Signed-off-by: Michal Klobukowski --- src/store/project/project-action.ts | 3 +- src/store/project/project-reducer.test.ts | 10 ++-- src/store/project/project-reducer.ts | 34 ++++++++++---- .../create-project-dialog.tsx | 21 +++++++++ src/views/project-panel/project-panel.tsx | 4 +- src/views/workbench/workbench.tsx | 46 +++++++++++-------- 6 files changed, 82 insertions(+), 36 deletions(-) create mode 100644 src/views-components/create-project-dialog/create-project-dialog.tsx diff --git a/src/store/project/project-action.ts b/src/store/project/project-action.ts index a02c9e7546..184922e3ec 100644 --- a/src/store/project/project-action.ts +++ b/src/store/project/project-action.ts @@ -11,7 +11,8 @@ import FilterBuilder from "../../common/api/filter-builder"; import { ThunkAction } from "../../../node_modules/redux-thunk"; const actions = unionize({ - OPEN_PROJECT_CREATOR: ofType<{}>(), + OPEN_PROJECT_CREATOR: ofType<{ownerUuid: string}>(), + CLOSE_PROJECT_CREATOR: ofType<{}>(), CREATE_PROJECT: ofType>(), CREATE_PROJECT_SUCCESS: ofType(), CREATE_PROJECT_ERROR: ofType(), diff --git a/src/store/project/project-reducer.test.ts b/src/store/project/project-reducer.test.ts index 724623e4c9..0862142d48 100644 --- a/src/store/project/project-reducer.test.ts +++ b/src/store/project/project-reducer.test.ts @@ -77,7 +77,7 @@ describe('project-reducer', () => { status: 1 }], currentItemId: "1", - creator: { opened: false, pending: false }, + creator: { opened: false, pending: false, ownerUuid: "" }, }; const project = { items: [{ @@ -120,7 +120,7 @@ describe('project-reducer', () => { status: 1 }], currentItemId: "1", - creator: { opened: false, pending: false } + creator: { opened: false, pending: false, ownerUuid: "" } }; const project = { items: [{ @@ -140,7 +140,7 @@ describe('project-reducer', () => { toggled: true }], currentItemId: "1", - creator: { opened: false, pending: false }, + creator: { opened: false, pending: false, ownerUuid: "" }, }; const state = projectsReducer(initialState, actions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(initialState.items[0].id)); @@ -167,7 +167,7 @@ describe('project-reducer', () => { toggled: false, }], currentItemId: "1", - creator: { opened: false, pending: false } + creator: { opened: false, pending: false, ownerUuid: "" } }; const project = { items: [{ @@ -187,7 +187,7 @@ describe('project-reducer', () => { toggled: true }], currentItemId: "1", - creator: { opened: false, pending: false }, + creator: { opened: false, pending: false, ownerUuid: "" }, }; const state = projectsReducer(initialState, actions.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 bb7d3d07e3..2c1ab81eb5 100644 --- a/src/store/project/project-reducer.ts +++ b/src/store/project/project-reducer.ts @@ -11,12 +11,15 @@ import { TreeItem, TreeItemStatus } from "../../components/tree/tree"; export type ProjectState = { items: Array>, currentItemId: string, - creator: { - opened: boolean, - pending: boolean - } + creator: ProjectCreator }; +interface ProjectCreator { + opened: boolean; + pending: boolean; + ownerUuid: string; +} + export function findTreeItem(tree: Array>, itemId: string): TreeItem | undefined { let item; for (const t of tree) { @@ -89,22 +92,32 @@ function updateProjectTree(tree: Array>, projects: Project[], return items; } +const updateCreator = (state: ProjectState, creator: Partial) => ({ + ...state, + creator: { + ...state.creator, + ...creator + } +}); + const initialState: ProjectState = { items: [], currentItemId: "", creator: { opened: false, - pending: false + pending: false, + ownerUuid: "" } }; const projectsReducer = (state: ProjectState = initialState, action: ProjectAction) => { return actions.match(action, { - OPEN_PROJECT_CREATOR: () => ({ ...state, creator: { opened: true, pending: false } }), - CREATE_PROJECT: () => ({ ...state, creator: { opened: false, pending: true } }), - CREATE_PROJECT_SUCCESS: () => ({ ...state, creator: { opened: false, pending: false } }), - CREATE_PROJECT_ERROR: () => ({ ...state, creator: { opened: false, pending: false } }), + OPEN_PROJECT_CREATOR: ({ ownerUuid }) => updateCreator(state, { ownerUuid, opened: true, pending: false }), + CLOSE_PROJECT_CREATOR: () => updateCreator(state, { opened: false }), + CREATE_PROJECT: () => updateCreator(state, { pending: true }), + CREATE_PROJECT_SUCCESS: () => updateCreator(state, { ownerUuid: "", pending: false }), + CREATE_PROJECT_ERROR: () => updateCreator(state, { ownerUuid: "", pending: false }), REMOVE_PROJECT: () => state, PROJECTS_REQUEST: itemId => { const items = _.cloneDeep(state.items); @@ -129,6 +142,7 @@ const projectsReducer = (state: ProjectState = initialState, action: ProjectActi item.open = !item.open; } return { + ...state, items, currentItemId: itemId }; @@ -142,6 +156,7 @@ const projectsReducer = (state: ProjectState = initialState, action: ProjectActi item.active = true; } return { + ...state, items, currentItemId: itemId }; @@ -150,6 +165,7 @@ const projectsReducer = (state: ProjectState = initialState, action: ProjectActi const items = _.cloneDeep(state.items); resetTreeActivity(items); return { + ...state, items, currentItemId: "" }; diff --git a/src/views-components/create-project-dialog/create-project-dialog.tsx b/src/views-components/create-project-dialog/create-project-dialog.tsx new file mode 100644 index 0000000000..d97eebcd1c --- /dev/null +++ b/src/views-components/create-project-dialog/create-project-dialog.tsx @@ -0,0 +1,21 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import { connect } from "react-redux"; +import { Dispatch } from "../../../node_modules/redux"; +import { RootState } from "../../store/store"; +import DialogProjectCreate from "../../components/dialog-create/dialog-project-create"; +import actions from "../../store/project/project-action"; + +const mapStateToProps = (state: RootState) => ({ + open: state.projects.creator.opened +}); + +const mapDispatchToProps = (dispatch: Dispatch) => ({ + handleClose: () => { + dispatch(actions.CLOSE_PROJECT_CREATOR()); + } +}); + +export default connect(mapStateToProps, mapDispatchToProps)(DialogProjectCreate); diff --git a/src/views/project-panel/project-panel.tsx b/src/views/project-panel/project-panel.tsx index f1b82357ec..d4e5e0a84e 100644 --- a/src/views/project-panel/project-panel.tsx +++ b/src/views/project-panel/project-panel.tsx @@ -27,7 +27,7 @@ type ProjectPanelProps = { onItemClick: (item: ProjectPanelItem) => void, onItemRouteChange: (itemId: string) => void, onContextMenu: (event: React.MouseEvent, item: ProjectPanelItem) => void; - onDialogOpen: () => void; + onDialogOpen: (ownerUuid: string) => void; } & DispatchProp & WithStyles @@ -43,7 +43,7 @@ class ProjectPanel extends React.Component { - diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index 9c1336c0d0..303d055aac 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -29,7 +29,9 @@ import DetailsPanel from '../../views-components/details-panel/details-panel'; import { ArvadosTheme } from '../../common/custom-theme'; import ContextMenu, { ContextMenuAction } from '../../components/context-menu/context-menu'; import { mockAnchorFromMouseEvent } from '../../components/popover/helpers'; -import DialogProjectCreate from '../../components/dialog-create/dialog-project-create'; +import CreateProjectDialog from "../../views-components/create-project-dialog/create-project-dialog"; +import { authService } from '../../services/services'; + const drawerWidth = 240; const appBarHeight = 100; @@ -95,8 +97,8 @@ interface NavMenuItem extends MainAppBarMenuItem { interface WorkbenchState { contextMenu: { anchorEl?: HTMLElement; + itemUuid?: string; }; - isCreationDialogOpen: boolean; anchorEl: any; searchText: string; menuItems: { @@ -110,7 +112,8 @@ interface WorkbenchState { class Workbench extends React.Component { state = { contextMenu: { - anchorEl: undefined + anchorEl: undefined, + itemUuid: undefined }, isCreationDialogOpen: false, anchorEl: null, @@ -155,8 +158,8 @@ class Workbench extends React.Component { onDetailsPanelToggle: () => { this.setState(prev => ({ isDetailsPanelOpened: !prev.isDetailsPanelOpened })); }, - onContextMenu: (event: React.MouseEvent, breadcrumb: Breadcrumb) => { - this.openContextMenu(event, breadcrumb); + onContextMenu: (event: React.MouseEvent, breadcrumb: NavBreadcrumb) => { + this.openContextMenu(event, breadcrumb.itemId); } }; @@ -169,27 +172,32 @@ class Workbench extends React.Component { this.props.dispatch(projectActions.RESET_PROJECT_TREE_ACTIVITY(itemId)); } - handleCreationDialogOpen = () => { + handleCreationDialogOpen = (itemUuid: string) => { this.closeContextMenu(); - this.setState({ isCreationDialogOpen: true }); + this.props.dispatch(projectActions.OPEN_PROJECT_CREATOR({ ownerUuid: itemUuid })); } - handleCreationDialogClose = () => { - this.setState({ isCreationDialogOpen: false }); - } - openContextMenu = (event: React.MouseEvent, item: any) => { + openContextMenu = (event: React.MouseEvent, itemUuid: string) => { event.preventDefault(); - this.setState({ contextMenu: { anchorEl: mockAnchorFromMouseEvent(event) } }); - console.log(item); + this.setState({ + contextMenu: { + anchorEl: mockAnchorFromMouseEvent(event), + itemUuid + } + }); } closeContextMenu = () => { this.setState({ contextMenu: {} }); } - openCreateDialog = (item: ContextMenuAction) => - item.openCreateDialog ? this.handleCreationDialogOpen() : void 0 + openCreateDialog = (item: ContextMenuAction) => { + const { itemUuid } = this.state.contextMenu; + if (item.openCreateDialog && itemUuid) { + this.handleCreationDialogOpen(itemUuid); + } + } render() { const path = getTreePath(this.props.projects, this.props.currentProjectId); @@ -221,12 +229,12 @@ class Workbench extends React.Component { toggleOpen={this.toggleSidePanelOpen} toggleActive={this.toggleSidePanelActive} sidePanelItems={this.props.sidePanelItems} - onContextMenu={this.openContextMenu}> + onContextMenu={(event) => this.openContextMenu(event, authService.getUuid() || "")}> this.props.dispatch(setProjectItem(itemId, ItemMode.OPEN))} toggleActive={itemId => this.props.dispatch(setProjectItem(itemId, ItemMode.ACTIVE))} - onContextMenu={this.openContextMenu} /> + onContextMenu={(event, item) => this.openContextMenu(event, item.data.uuid)} /> }
@@ -244,7 +252,7 @@ class Workbench extends React.Component { actions={contextMenuActions} onActionClick={this.openCreateDialog} onClose={this.closeContextMenu} /> - + ); } @@ -252,7 +260,7 @@ class Workbench extends React.Component { renderProjectPanel = (props: RouteComponentProps<{ id: string }>) => this.props.dispatch(setProjectItem(itemId, ItemMode.ACTIVE))} onItemClick={item => this.props.dispatch(setProjectItem(item.uuid, ItemMode.ACTIVE))} - onContextMenu={this.openContextMenu} + onContextMenu={(event, item) => this.openContextMenu(event, item.uuid)} onDialogOpen={this.handleCreationDialogOpen} {...props} /> } -- 2.30.2