Merge branch '19675-instance-types-panel' into main. Closes #19675
[arvados.git] / services / workbench2 / src / views-components / side-panel / side-panel-collapsed.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { ReactElement } from 'react'
6 import { connect } from 'react-redux'
7 import { ProjectsIcon, ProcessIcon, FavoriteIcon, ShareMeIcon, TrashIcon, PublicFavoriteIcon, GroupsIcon, ResourceIcon } from 'components/icon/icon'
8 import { TerminalIcon } from 'components/icon/icon'
9 import { IconButton, List, ListItem, Tooltip } from '@material-ui/core'
10 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles'
11 import { ArvadosTheme } from 'common/custom-theme'
12 import { navigateTo, navigateToInstanceTypes } from 'store/navigation/navigation-action'
13 import { RootState } from 'store/store'
14 import { Dispatch } from 'redux'
15 import {
16     navigateToSharedWithMe,
17     navigateToPublicFavorites,
18     navigateToFavorites,
19     navigateToGroups,
20     navigateToAllProcesses,
21     navigateToTrash,
22 } from 'store/navigation/navigation-action'
23 import { navigateToUserVirtualMachines } from 'store/navigation/navigation-action'
24 import { RouterAction } from 'react-router-redux'
25 import { User } from 'models/user'
26
27 type CssRules = 'button' | 'unselected' | 'selected'
28
29 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
30     button: {
31         width: '40px',
32         height: '40px',
33         paddingLeft: '-2rem',
34         marginLeft: '-0.6rem',
35         marginBottom: '-1rem'
36     },
37     unselected: {
38         color: theme.customs.colors.grey600,
39     },
40     selected: {
41         color: theme.palette.primary.main,
42     },
43 })
44
45 enum SidePanelCollapsedCategory {
46     PROJECTS = 'Home Projects',
47     FAVORITES = 'My Favorites',
48     PUBLIC_FAVORITES = 'Public Favorites',
49     SHARED_WITH_ME = 'Shared with me',
50     ALL_PROCESSES = 'All Processes',
51     INSTANCE_TYPES = 'Instance Types',
52     SHELL_ACCESS = 'Shell Access',
53     GROUPS = 'Groups',
54     TRASH = 'Trash',
55 }
56
57 type TCollapsedCategory = {
58     name: SidePanelCollapsedCategory
59     icon: ReactElement
60     navTarget: RouterAction | ''
61 }
62
63 const sidePanelCollapsedCategories: TCollapsedCategory[] = [
64     {
65         name: SidePanelCollapsedCategory.PROJECTS,
66         icon: <ProjectsIcon />,
67         navTarget: '',
68     },
69     {
70         name: SidePanelCollapsedCategory.FAVORITES,
71         icon: <FavoriteIcon />,
72         navTarget: navigateToFavorites,
73     },
74     {
75         name: SidePanelCollapsedCategory.PUBLIC_FAVORITES,
76         icon: <PublicFavoriteIcon />,
77         navTarget: navigateToPublicFavorites,
78     },
79     {
80         name: SidePanelCollapsedCategory.SHARED_WITH_ME,
81         icon: <ShareMeIcon />,
82         navTarget: navigateToSharedWithMe,
83     },
84     {
85         name: SidePanelCollapsedCategory.ALL_PROCESSES,
86         icon: <ProcessIcon />,
87         navTarget: navigateToAllProcesses,
88     },
89     {
90         name: SidePanelCollapsedCategory.INSTANCE_TYPES,
91         icon: <ResourceIcon />,
92         navTarget: navigateToInstanceTypes,
93     },
94     {
95         name: SidePanelCollapsedCategory.SHELL_ACCESS,
96         icon: <TerminalIcon />,
97         navTarget: navigateToUserVirtualMachines,
98     },
99     {
100         name: SidePanelCollapsedCategory.GROUPS,
101         icon: <GroupsIcon style={{marginLeft: '2px', scale: '85%'}}/>,
102         navTarget: navigateToGroups,
103     },
104     {
105         name: SidePanelCollapsedCategory.TRASH,
106         icon: <TrashIcon />,
107         navTarget: navigateToTrash,
108     },
109 ]
110
111 type SidePanelCollapsedProps = {
112     user: User;
113     selectedPath: string;
114     navToHome: (uuid: string) => void;
115     navTo: (navTarget: RouterAction | '') => void;
116 };
117
118 const mapStateToProps = ({auth, properties }: RootState) => {
119         return {
120             user: auth.user,
121             selectedPath: properties.breadcrumbs
122                 ? properties.breadcrumbs[0].label !== 'Virtual Machines'
123                 ? properties.breadcrumbs[0].label
124                 : SidePanelCollapsedCategory.SHELL_ACCESS
125                 : SidePanelCollapsedCategory.PROJECTS,
126         }
127 }
128
129 const mapDispatchToProps = (dispatch: Dispatch) => {
130     return {
131         navToHome: (navTarget) => dispatch<any>(navigateTo(navTarget)),
132         navTo: (navTarget) => dispatch<any>(navTarget),
133     }
134 }
135
136 export const SidePanelCollapsed = withStyles(styles)(
137     connect(mapStateToProps, mapDispatchToProps)(({ classes, user, selectedPath, navToHome, navTo }: WithStyles & SidePanelCollapsedProps) => {
138
139         const handleClick = (cat: TCollapsedCategory) => {
140             if (cat.name === SidePanelCollapsedCategory.PROJECTS) navToHome(user.uuid)
141             else navTo(cat.navTarget)
142         }
143
144         const { button, unselected, selected } = classes
145         return (
146             <List data-cy='side-panel-collapsed'>
147                 {sidePanelCollapsedCategories.map((cat) => (
148                     <ListItem
149                         key={cat.name}
150                         data-cy={`collapsed-${cat.name.toLowerCase().replace(/\s+/g, '-')}`}
151                         onClick={() => handleClick(cat)}
152                         >
153                         <Tooltip
154                             className={selectedPath === cat.name ? selected : unselected}
155                             title={cat.name}
156                             disableFocusListener
157                             >
158                             <IconButton className={button}>{cat.icon}</IconButton>
159                         </Tooltip>
160                     </ListItem>
161                 ))}
162             </List>
163         );
164     })
165 )