1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
7 import { ArvadosTheme } from '~/common/custom-theme';
8 import { List, ListItem, ListItemIcon, Collapse } from "@material-ui/core";
9 import { SidePanelRightArrowIcon, IconType } from '../icon/icon';
10 import * as classnames from "classnames";
11 import { ListItemTextIcon } from '../list-item-text-icon/list-item-text-icon';
12 import { Dispatch } from "redux";
13 import { RouteComponentProps, withRouter } from "react-router";
15 type CssRules = 'active' | 'row' | 'root' | 'list' | 'iconClose' | 'iconOpen' | 'toggableIconContainer' | 'toggableIcon';
17 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
27 padding: '5px 0px 5px 14px',
34 toggableIconContainer: {
35 color: theme.palette.grey["700"],
43 color: theme.palette.primary.main,
46 transition: 'all 0.1s ease',
49 transition: 'all 0.1s ease',
50 transform: 'rotate(90deg)',
54 export interface SidePanelItem {
62 activeAction?: (dispatch: Dispatch, uuid?: string) => void;
65 interface SidePanelDataProps {
66 toggleOpen: (id: string) => void;
67 toggleActive: (id: string) => void;
68 sidePanelItems: SidePanelItem[];
69 onContextMenu: (event: React.MouseEvent<HTMLElement>, item: SidePanelItem) => void;
72 type SidePanelProps = RouteComponentProps<{}> & SidePanelDataProps & WithStyles<CssRules>;
74 export const SidePanel = withStyles(styles)(withRouter(
75 class extends React.Component<SidePanelProps> {
77 const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props;
78 const { root, row, list, toggableIconContainer } = classes;
80 const path = this.props.location.pathname.split('/');
81 const activeUrl = path.length > 1 ? "/" + path[1] : "/";
83 <div className={root}>
85 {sidePanelItems.map(it => {
86 const active = it.url === activeUrl;
87 return <span key={it.name}>
88 <ListItem button className={list} onClick={() => toggleActive(it.id)}
89 onContextMenu={this.handleRowContextMenu(it)}>
90 <span className={row}>
92 <i onClick={() => toggleOpen(it.id)} className={toggableIconContainer}>
94 className={this.getToggableIconClassNames(it.open, active)}>
95 < SidePanelRightArrowIcon/>
99 <ListItemTextIcon icon={it.icon} name={it.name} isActive={active}
100 hasMargin={it.margin}/>
104 <Collapse in={it.open} timeout="auto" unmountOnExit>
115 getToggableIconClassNames = (isOpen?: boolean, isActive ?: boolean) => {
116 const { iconOpen, iconClose, active, toggableIcon } = this.props.classes;
117 return classnames(toggableIcon, {
119 [iconClose]: !isOpen,
124 handleRowContextMenu = (item: SidePanelItem) =>
125 (event: React.MouseEvent<HTMLElement>) =>
126 item.openAble ? this.props.onContextMenu(event, item) : null