1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import * as React from 'react';
6 import { ReactElement } from 'react';
7 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
8 import { ArvadosTheme } from '../../common/custom-theme';
9 import { List, ListItem, ListItemText, ListItemIcon, Collapse, Typography } from "@material-ui/core";
10 import IconBase, { IconTypes } from '../icon/icon';
11 import * as classnames from "classnames";
13 export interface SidePanelItem {
23 interface SidePanelProps {
24 toggleOpen: (id: string) => void;
25 toggleActive: (id: string) => void;
26 sidePanelItems: SidePanelItem[];
27 onContextMenu: (event: React.MouseEvent<HTMLElement>, item: SidePanelItem) => void;
30 class SidePanel extends React.Component<SidePanelProps & WithStyles<CssRules>> {
31 render(): ReactElement<any> {
32 const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props;
33 const { listItemText, leftSidePanelContainer, row, list, icon, projectIconMargin, active, iconArrowContainer } = classes;
35 <div className={leftSidePanelContainer}>
37 {sidePanelItems.map(it => (
39 <ListItem button className={list} onClick={() => toggleActive(it.id)} onContextMenu={this.handleRowContextMenu(it)}>
40 <span className={row}>
42 <i onClick={() => toggleOpen(it.id)} className={iconArrowContainer}>
43 <IconBase icon={IconTypes.PLAY_ARROW}
44 className={this.getIconClassNames(it.open, it.active)}/>
47 <ListItemIcon className={it.active ? active : ''}>
48 <IconBase icon={it.icon}
49 className={ `${icon} ${it.margin ? projectIconMargin : ''}` } />
51 <ListItemText className={listItemText}
52 primary={renderListItemText(it.name, active, it.active)} />
56 <Collapse in={it.open} timeout="auto" unmountOnExit>
67 getIconClassNames = (itemOpen ?: boolean, itemActive ?: boolean) => {
68 const { classes } = this.props;
69 return classnames(classes.iconArrow, {
70 [classes.iconOpen]: itemOpen,
71 [classes.iconClose]: !itemOpen,
72 [classes.active]: itemActive
76 handleRowContextMenu = (item: SidePanelItem) =>
77 (event: React.MouseEvent<HTMLElement>) =>
78 item.openAble ? this.props.onContextMenu(event, item) : null
82 const renderListItemText = (itemName: string, active: string, itemActive?: boolean) =>
83 <Typography className={itemActive ? active : ''}>{itemName}</Typography>;
85 type CssRules = 'active' | 'listItemText' | 'row' | 'leftSidePanelContainer' | 'list' | 'icon' |
86 'projectIconMargin' | 'iconClose' | 'iconOpen' | 'iconArrowContainer' | 'iconArrow';
88 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
90 color: theme.palette.primary.main,
100 color: theme.palette.grey["700"],
108 transition: 'all 0.1s ease',
111 transition: 'all 0.1s ease',
112 transform: 'rotate(90deg)',
114 leftSidePanelContainer: {
117 whiteSpace: 'nowrap',
123 padding: '5px 0px 5px 14px',
134 export default withStyles(styles)(SidePanel);