From 4fe47dee802ef6491649317f335a8558f9f75c40 Mon Sep 17 00:00:00 2001 From: Daniel Kos <daniel.kos@contractors.roche.com> Date: Sat, 18 Aug 2018 22:05:22 +0200 Subject: [PATCH] Fix setting active side panel item on page reload Feature #13986 Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos@contractors.roche.com> --- src/components/side-panel/side-panel.tsx | 28 ++++++---- src/store/auth/auth-action.ts | 6 +- src/store/navigation/navigation-action.ts | 5 +- src/store/side-panel/side-panel-action.ts | 4 +- .../side-panel/side-panel-reducer.test.ts | 56 +------------------ src/store/side-panel/side-panel-reducer.ts | 24 ++++++-- src/views/workbench/workbench.tsx | 3 - 7 files changed, 43 insertions(+), 83 deletions(-) diff --git a/src/components/side-panel/side-panel.tsx b/src/components/side-panel/side-panel.tsx index 206cb6322b..84e5c5476f 100644 --- a/src/components/side-panel/side-panel.tsx +++ b/src/components/side-panel/side-panel.tsx @@ -3,7 +3,6 @@ // SPDX-License-Identifier: AGPL-3.0 import * as React from 'react'; -import { ReactElement } from 'react'; import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles'; import { ArvadosTheme } from '~/common/custom-theme'; import { List, ListItem, ListItemIcon, Collapse } from "@material-ui/core"; @@ -11,6 +10,7 @@ import { SidePanelRightArrowIcon, IconType } from '../icon/icon'; import * as classnames from "classnames"; import { ListItemTextIcon } from '../list-item-text-icon/list-item-text-icon'; import { Dispatch } from "redux"; +import { RouteComponentProps, withRouter } from "react-router"; type CssRules = 'active' | 'row' | 'root' | 'list' | 'iconClose' | 'iconOpen' | 'toggableIconContainer' | 'toggableIcon'; @@ -54,8 +54,8 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({ export interface SidePanelItem { id: string; name: string; + url: string; icon: IconType; - active?: boolean; open?: boolean; margin?: boolean; openAble?: boolean; @@ -69,30 +69,34 @@ interface SidePanelDataProps { onContextMenu: (event: React.MouseEvent<HTMLElement>, item: SidePanelItem) => void; } -type SidePanelProps = SidePanelDataProps & WithStyles<CssRules>; +type SidePanelProps = RouteComponentProps<{}> & SidePanelDataProps & WithStyles<CssRules>; -export const SidePanel = withStyles(styles)( +export const SidePanel = withStyles(styles)(withRouter( class extends React.Component<SidePanelProps> { - render(): ReactElement<any> { + render() { const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props; const { root, row, list, toggableIconContainer } = classes; + + const path = this.props.location.pathname.split('/'); + const activeUrl = path.length > 1 ? "/" + path[1] : "/"; return ( <div className={root}> <List> - {sidePanelItems.map(it => ( - <span key={it.name}> + {sidePanelItems.map(it => { + const active = it.url === activeUrl; + return <span key={it.name}> <ListItem button className={list} onClick={() => toggleActive(it.id)} onContextMenu={this.handleRowContextMenu(it)}> <span className={row}> {it.openAble ? ( <i onClick={() => toggleOpen(it.id)} className={toggableIconContainer}> <ListItemIcon - className={this.getToggableIconClassNames(it.open, it.active)}> + className={this.getToggableIconClassNames(it.open, active)}> < SidePanelRightArrowIcon/> </ListItemIcon> </i> ) : null} - <ListItemTextIcon icon={it.icon} name={it.name} isActive={it.active} + <ListItemTextIcon icon={it.icon} name={it.name} isActive={active} hasMargin={it.margin}/> </span> </ListItem> @@ -101,8 +105,8 @@ export const SidePanel = withStyles(styles)( {children} </Collapse> ) : null} - </span> - ))} + </span>; + })} </List> </div> ); @@ -121,4 +125,4 @@ export const SidePanel = withStyles(styles)( (event: React.MouseEvent<HTMLElement>) => item.openAble ? this.props.onContextMenu(event, item) : null } -); +)); diff --git a/src/store/auth/auth-action.ts b/src/store/auth/auth-action.ts index 33a5df9045..00af5ce5b0 100644 --- a/src/store/auth/auth-action.ts +++ b/src/store/auth/auth-action.ts @@ -17,9 +17,9 @@ export const authActions = unionize({ USER_DETAILS_REQUEST: {}, USER_DETAILS_SUCCESS: ofType<User>() }, { - tag: 'type', - value: 'payload' - }); + tag: 'type', + value: 'payload' +}); function setAuthorizationHeader(services: ServiceRepository, token: string) { services.apiClient.defaults.headers.common = { diff --git a/src/store/navigation/navigation-action.ts b/src/store/navigation/navigation-action.ts index 981b852fc6..593ff5d333 100644 --- a/src/store/navigation/navigation-action.ts +++ b/src/store/navigation/navigation-action.ts @@ -8,7 +8,7 @@ import { push } from "react-router-redux"; import { TreeItemStatus } from "~/components/tree/tree"; import { findTreeItem } from "../project/project-reducer"; import { RootState } from "../store"; -import { Resource, ResourceKind } from "~/models/resource"; +import { ResourceKind } from "~/models/resource"; import { projectPanelActions } from "../project-panel/project-panel-action"; import { getCollectionUrl } from "~/models/collection"; import { getProjectUrl, ProjectResource } from "~/models/project"; @@ -35,8 +35,6 @@ export enum ItemMode { export const setProjectItem = (itemId: string, itemMode: ItemMode) => (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => { - console.log("SetProjectItem!!", itemId); - debugger; const { projects, router } = getState(); const treeItem = findTreeItem(projects.items, itemId); @@ -78,7 +76,6 @@ export const restoreBranch = (itemId: string) => const uuids = ancestors.map(ancestor => ancestor.uuid); await loadBranch(uuids, dispatch); dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(SidePanelIdentifiers.PROJECTS)); - dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(SidePanelIdentifiers.PROJECTS)); uuids.forEach(uuid => { dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_OPEN(uuid)); }); diff --git a/src/store/side-panel/side-panel-action.ts b/src/store/side-panel/side-panel-action.ts index 0dd6aad19e..4aa5809c28 100644 --- a/src/store/side-panel/side-panel-action.ts +++ b/src/store/side-panel/side-panel-action.ts @@ -5,9 +5,7 @@ import { default as unionize, ofType, UnionOf } from "unionize"; export const sidePanelActions = unionize({ - TOGGLE_SIDE_PANEL_ITEM_OPEN: ofType<string>(), - TOGGLE_SIDE_PANEL_ITEM_ACTIVE: ofType<string>(), - RESET_SIDE_PANEL_ACTIVITY: ofType<{}>(), + TOGGLE_SIDE_PANEL_ITEM_OPEN: ofType<string>() }, { tag: 'type', value: 'payload' diff --git a/src/store/side-panel/side-panel-reducer.test.ts b/src/store/side-panel/side-panel-reducer.test.ts index 4872a72cf7..7210e1810a 100644 --- a/src/store/side-panel/side-panel-reducer.test.ts +++ b/src/store/side-panel/side-panel-reducer.test.ts @@ -7,39 +7,14 @@ import { sidePanelActions } from "./side-panel-action"; import { ProjectsIcon } from "~/components/icon/icon"; describe('side-panel-reducer', () => { - - it('should toggle activity on side-panel', () => { - const initialState = [ - { - id: "1", - name: "Projects", - icon: ProjectsIcon, - open: false, - active: false, - } - ]; - const project = [ - { - id: "1", - name: "Projects", - icon: ProjectsIcon, - open: false, - active: true, - } - ]; - - const state = sidePanelReducer(initialState, sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(initialState[0].id)); - expect(state).toEqual(project); - }); - it('should open side-panel item', () => { const initialState = [ { id: "1", name: "Projects", + url: "/projects", icon: ProjectsIcon, - open: false, - active: false, + open: false } ]; const project = [ @@ -47,36 +22,11 @@ describe('side-panel-reducer', () => { id: "1", name: "Projects", icon: ProjectsIcon, - open: true, - active: false, + open: true } ]; const state = sidePanelReducer(initialState, sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_OPEN(initialState[0].id)); expect(state).toEqual(project); }); - - it('should remove activity on side-panel item', () => { - const initialState = [ - { - id: "1", - name: "Projects", - icon: ProjectsIcon, - open: false, - active: true, - } - ]; - const project = [ - { - id: "1", - name: "Projects", - icon: ProjectsIcon, - open: false, - active: false, - } - ]; - - const state = sidePanelReducer(initialState, sidePanelActions.RESET_SIDE_PANEL_ACTIVITY(initialState[0].id)); - expect(state).toEqual(project); - }); }); diff --git a/src/store/side-panel/side-panel-reducer.ts b/src/store/side-panel/side-panel-reducer.ts index 5a45d29590..66c2289672 100644 --- a/src/store/side-panel/side-panel-reducer.ts +++ b/src/store/side-panel/side-panel-reducer.ts @@ -20,10 +20,6 @@ export const sidePanelReducer = (state: SidePanelState = sidePanelData, action: return sidePanelActions.match(action, { TOGGLE_SIDE_PANEL_ITEM_OPEN: itemId => state.map(it => ({...it, open: itemId === it.id && it.open === false})), - TOGGLE_SIDE_PANEL_ITEM_ACTIVE: itemId => - state.map(it => ({...it, active: it.id === itemId})), - RESET_SIDE_PANEL_ACTIVITY: () => - state.map(it => ({...it, active: false })), default: () => state }); }; @@ -41,14 +37,15 @@ export const sidePanelData = [ { id: SidePanelIdentifiers.PROJECTS, name: "Projects", + url: "/projects", icon: ProjectsIcon, open: false, active: false, margin: true, openAble: true, activeAction: (dispatch: Dispatch, uuid: string) => { - dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(uuid)); dispatch(push(getProjectUrl(uuid))); + dispatch(projectActions.TOGGLE_PROJECT_TREE_ITEM_ACTIVE(uuid)); dispatch(projectPanelActions.SET_COLUMNS({ columns: projectPanelColumns })); dispatch(projectPanelActions.RESET_PAGINATION()); dispatch(projectPanelActions.REQUEST_ITEMS()); @@ -57,24 +54,37 @@ export const sidePanelData = [ { id: SidePanelIdentifiers.SHARED_WITH_ME, name: "Shared with me", + url: "/shared", icon: ShareMeIcon, active: false, + activeAction: (dispatch: Dispatch) => { + dispatch(push("/shared")); + } }, { id: SidePanelIdentifiers.WORKFLOWS, name: "Workflows", + url: "/workflows", icon: WorkflowIcon, active: false, + activeAction: (dispatch: Dispatch) => { + dispatch(push("/workflows")); + } }, { id: SidePanelIdentifiers.RECENT_OPEN, name: "Recent open", + url: "/recent", icon: RecentIcon, active: false, + activeAction: (dispatch: Dispatch) => { + dispatch(push("/recent")); + } }, { id: SidePanelIdentifiers.FAVORITES, name: "Favorites", + url: "/favorites", icon: FavoriteIcon, active: false, activeAction: (dispatch: Dispatch) => { @@ -87,7 +97,11 @@ export const sidePanelData = [ { id: SidePanelIdentifiers.TRASH, name: "Trash", + url: "/trash", icon: TrashIcon, active: false, + activeAction: (dispatch: Dispatch) => { + dispatch(push("/trash")); + } } ]; diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index a38afb7ac3..4e00349f24 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -222,7 +222,6 @@ export const Workbench = withStyles(styles)( toggleActive={itemId => { this.props.dispatch(setProjectItem(itemId, ItemMode.ACTIVE)); this.props.dispatch(loadDetails(itemId, ResourceKind.PROJECT)); - this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(SidePanelIdentifiers.PROJECTS)); }} /> </SidePanel> </Drawer>} @@ -330,7 +329,6 @@ export const Workbench = withStyles(styles)( default: this.props.dispatch(loadDetails(item.uuid, ResourceKind.PROJECT)); this.props.dispatch(setProjectItem(item.uuid, ItemMode.ACTIVE)); - this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(SidePanelIdentifiers.PROJECTS)); } }} @@ -363,7 +361,6 @@ export const Workbench = withStyles(styles)( } toggleSidePanelActive = (itemId: string) => { - this.props.dispatch(sidePanelActions.TOGGLE_SIDE_PANEL_ITEM_ACTIVE(itemId)); this.props.dispatch(projectActions.RESET_PROJECT_TREE_ACTIVITY(itemId)); const panelItem = this.props.sidePanelItems.find(it => it.id === itemId); -- 2.30.2