merge-commit
[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, Theme, WithStyles, withStyles } from '@material-ui/core/styles';
8 import List from "@material-ui/core/List/List";
9 import ListItem from "@material-ui/core/ListItem/ListItem";
10 import ListItemText from "@material-ui/core/ListItemText/ListItemText";
11 import ListItemIcon from '@material-ui/core/ListItemIcon';
12 import Collapse from "@material-ui/core/Collapse/Collapse";
13
14 import { Typography } from '@material-ui/core';
15
16 export interface SidePanelItem {
17     id: string;
18     name: string;
19     icon: string;
20     active?: boolean;
21     open?: boolean;
22     margin?: boolean;
23     openAble?: boolean;
24 }
25
26 interface SidePanelProps {
27     toggleOpen: (id: string) => void;
28     toggleActive: (id: string) => void;
29     sidePanelItems: SidePanelItem[];
30     handleCreationDialogOpen: () => void;
31     handleCreationDialogClose: () => void;
32 }
33
34 class SidePanel extends React.Component<SidePanelProps & WithStyles<CssRules>> {
35     render(): ReactElement<any> {
36         const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props;
37         const { listItemText, leftSidePanelContainer, row, list, icon, projectIconMargin, active, activeArrow, inactiveArrow, arrowTransition, arrowRotate } = classes;
38         return (
39             <div className={leftSidePanelContainer}>
40                 <List>
41                     {sidePanelItems.map(it => (
42                         <span key={it.name}>
43                             <ListItem button className={list} onClick={() => toggleActive(it.id)}>
44                                 <span className={row}>
45                                     {it.openAble ? <i onClick={() => toggleOpen(it.id)} className={`${it.active ? activeArrow : inactiveArrow} 
46                                         ${it.open ? `fas fa-caret-down ${arrowTransition}` : `fas fa-caret-down ${arrowRotate}`}`} /> : null}
47                                     <ListItemIcon className={it.active ? active : ''}>
48                                         <i className={`${it.icon} ${icon} ${it.margin ? projectIconMargin : ''}`} />
49                                     </ListItemIcon>
50                                     <ListItemText className={listItemText} primary={<Typography className={it.active ? active : ''}>{it.name}</Typography>} />
51                                 </span>
52                             </ListItem>
53                             {it.openAble ? (
54                                 <Collapse in={it.open} timeout="auto" unmountOnExit>
55                                     {children}
56                                 </Collapse>) : null}
57                         </span>
58                     ))}
59                 </List>
60             </div>
61         );
62     }
63 }
64
65 type CssRules = 'active' | 'listItemText' | 'row' | 'leftSidePanelContainer' | 'list' | 'icon' | 'projectIconMargin' |
66     'activeArrow' | 'inactiveArrow' | 'arrowRotate' | 'arrowTransition';
67
68 const styles: StyleRulesCallback<CssRules> = (theme: Theme) => ({
69     active: {
70         color: '#4285F6',
71     },
72     listItemText: {
73         padding: '0px',
74     },
75     row: {
76         display: 'flex',
77         alignItems: 'center',
78     },
79     activeArrow: {
80         color: '#4285F6',
81         position: 'absolute',
82     },
83     inactiveArrow: {
84         position: 'absolute',
85     },
86     arrowTransition: {
87         transition: 'all 0.1s ease',
88     },
89     arrowRotate: {
90         transition: 'all 0.1s ease',
91         transform: 'rotate(-90deg)',
92     },
93     leftSidePanelContainer: {
94         overflowY: 'auto',
95         minWidth: '240px',
96         whiteSpace: 'nowrap',
97         marginTop: '52px',
98         display: 'flex',
99         flexGrow: 1,
100     },
101     list: {
102         paddingBottom: '5px',
103         paddingTop: '5px',
104         paddingLeft: '14px',
105         minWidth: '240px',
106     },
107     icon: {
108         minWidth: '20px',
109     },
110     projectIconMargin: {
111         marginLeft: '17px',
112     }
113 });
114
115 export default withStyles(styles)(SidePanel);