// Copyright (C) The Arvados Authors. All rights reserved. // // 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"; 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"; type CssRules = 'active' | 'row' | 'root' | 'list' | 'iconClose' | 'iconOpen' | 'toggableIconContainer' | 'toggableIcon'; const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({ root: { overflowY: 'auto', minWidth: '240px', whiteSpace: 'nowrap', marginTop: '52px', display: 'flex', flexGrow: 1, }, list: { padding: '5px 0px 5px 14px', minWidth: '240px', }, row: { display: 'flex', alignItems: 'center', }, toggableIconContainer: { color: theme.palette.grey["700"], height: '14px', width: '14px' }, toggableIcon: { fontSize: '14px' }, active: { color: theme.palette.primary.main, }, iconClose: { transition: 'all 0.1s ease', }, iconOpen: { transition: 'all 0.1s ease', transform: 'rotate(90deg)', } }); export interface SidePanelItem { id: string; name: string; icon: IconType; active?: boolean; open?: boolean; margin?: boolean; openAble?: boolean; activeAction?: (dispatch: Dispatch) => void; } interface SidePanelDataProps { toggleOpen: (id: string) => void; toggleActive: (id: string) => void; sidePanelItems: SidePanelItem[]; onContextMenu: (event: React.MouseEvent<HTMLElement>, item: SidePanelItem) => void; } type SidePanelProps = SidePanelDataProps & WithStyles<CssRules>; export const SidePanel = withStyles(styles)( class extends React.Component<SidePanelProps> { render(): ReactElement<any> { const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props; const { root, row, list, toggableIconContainer } = classes; return ( <div className={root}> <List> {sidePanelItems.map(it => ( <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)}> < SidePanelRightArrowIcon/> </ListItemIcon> </i> ) : null} <ListItemTextIcon icon={it.icon} name={it.name} isActive={it.active} hasMargin={it.margin}/> </span> </ListItem> {it.openAble ? ( <Collapse in={it.open} timeout="auto" unmountOnExit> {children} </Collapse> ) : null} </span> ))} </List> </div> ); } getToggableIconClassNames = (isOpen?: boolean, isActive ?: boolean) => { const { iconOpen, iconClose, active, toggableIcon } = this.props.classes; return classnames(toggableIcon, { [iconOpen]: isOpen, [iconClose]: !isOpen, [active]: isActive }); } handleRowContextMenu = (item: SidePanelItem) => (event: React.MouseEvent<HTMLElement>) => item.openAble ? this.props.onContextMenu(event, item) : null } );