merge conflicts
[arvados-workbench2.git] / src / components / side-panel / side-panel.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
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, ListItemIcon, Collapse } from "@material-ui/core";
10 import { SidePanelRightArrowIcon, IconType } from '../icon/icon';
11 import * as classnames from "classnames";
12 import { ListItemTextIcon } from '../list-item-text-icon/list-item-text-icon';
13
14 type CssRules = 'active' | 'row' | 'root' | 'list' | 'iconClose' | 'iconOpen' | 'toggableIconContainer' | 'toggableIcon';
15
16 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
17     root: {
18         overflowY: 'auto',
19         minWidth: '240px',
20         whiteSpace: 'nowrap',
21         marginTop: '52px',
22         display: 'flex',
23         flexGrow: 1,
24     },
25     list: {
26         padding: '5px 0px 5px 14px',
27         minWidth: '240px',
28     },
29     row: {
30         display: 'flex',
31         alignItems: 'center',
32     },
33     toggableIconContainer: {
34         color: theme.palette.grey["700"],
35         height: '14px',
36         position: 'absolute'
37     },
38     toggableIcon: {
39         fontSize: '14px'
40     },
41     active: {
42         color: theme.palette.primary.main,
43     },
44     iconClose: {
45         transition: 'all 0.1s ease',
46     },
47     iconOpen: {
48         transition: 'all 0.1s ease',
49         transform: 'rotate(90deg)',
50     }
51 });
52
53 export interface SidePanelItem {
54     id: string;
55     name: string;
56     icon: IconType;
57     active?: boolean;
58     open?: boolean;
59     margin?: boolean;
60     openAble?: boolean;
61 }
62
63 interface SidePanelDataProps {
64     toggleOpen: (id: string) => void;
65     toggleActive: (id: string) => void;
66     sidePanelItems: SidePanelItem[];
67     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: SidePanelItem) => void;
68 }
69
70 type SidePanelProps = SidePanelDataProps & WithStyles<CssRules>;
71
72 export const SidePanel = withStyles(styles)(
73     class extends React.Component<SidePanelProps> {
74         render(): ReactElement<any> {
75             const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props;
76             const { root, row, list, toggableIconContainer } = classes;
77             return (
78                 <div className={root}>
79                     <List>
80                         {sidePanelItems.map(it => (
81                             <span key={it.name}>
82                                 <ListItem button className={list} onClick={() => toggleActive(it.id)}
83                                           onContextMenu={this.handleRowContextMenu(it)}>
84                                     <span className={row}>
85                                         {it.openAble ? (
86                                             <i onClick={() => toggleOpen(it.id)} className={toggableIconContainer}>
87                                                 <ListItemIcon
88                                                     className={this.getToggableIconClassNames(it.open, it.active)}>
89                                                     < SidePanelRightArrowIcon/>
90                                                 </ListItemIcon>
91                                             </i>
92                                         ) : null}
93                                         <ListItemTextIcon icon={it.icon} name={it.name} isActive={it.active}
94                                                           hasMargin={it.margin}/>
95                                     </span>
96                                 </ListItem>
97                                 {it.openAble ? (
98                                     <Collapse in={it.open} timeout="auto" unmountOnExit>
99                                         {children}
100                                     </Collapse>
101                                 ) : null}
102                             </span>
103                         ))}
104                     </List>
105                 </div>
106             );
107         }
108
109         getToggableIconClassNames = (isOpen?: boolean, isActive ?: boolean) => {
110             const { classes } = this.props;
111             return classnames(classes.toggableIcon, {
112                 [classes.iconOpen]: isOpen,
113                 [classes.iconClose]: !isOpen,
114                 [classes.active]: isActive
115             });
116         }
117
118         handleRowContextMenu = (item: SidePanelItem) =>
119             (event: React.MouseEvent<HTMLElement>) =>
120                 item.openAble ? this.props.onContextMenu(event, item) : null
121     }
122 );