21700: Install Bundler system-wide in Rails postinst
[arvados.git] / services / workbench2 / src / components / breadcrumbs / breadcrumbs.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { Button, Grid, StyleRulesCallback, WithStyles, Typography, Tooltip } from '@material-ui/core';
7 import ChevronRightIcon from '@material-ui/icons/ChevronRight';
8 import { withStyles } from '@material-ui/core';
9 import { IllegalNamingWarning } from '../warning/warning';
10 import { IconType, FreezeIcon } from 'components/icon/icon';
11 import grey from '@material-ui/core/colors/grey';
12 import { getResource, ResourcesState } from 'store/resources/resources';
13 import classNames from 'classnames';
14 import { ArvadosTheme } from 'common/custom-theme';
15 import { GroupClass } from "models/group";
16 import { navigateTo, navigateToGroupDetails } from 'store/navigation/navigation-action';
17 export interface Breadcrumb {
18     label: string;
19     icon?: IconType;
20     uuid: string;
21 }
22
23 type CssRules = "item" | "chevron" | "label" | "buttonLabel" | "icon" | "frozenIcon";
24
25 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
26     item: {
27         borderRadius: '16px',
28         height: '32px',
29         minWidth: '36px',
30         color: theme.customs.colors.grey700,
31         '&.parentItem': {
32             color: `${theme.palette.primary.main}`,
33         },
34     },
35     chevron: {
36         color: grey["600"],
37     },
38     label: {
39         textTransform: "none",
40         paddingRight: '3px',
41         paddingLeft: '3px',
42         lineHeight: '1.4',
43     },
44     buttonLabel: {
45         overflow: 'hidden',
46         justifyContent: 'flex-start',
47     },
48     icon: {
49         fontSize: 20,
50         color: grey["600"],
51         marginRight: '5px',
52     },
53     frozenIcon: {
54         fontSize: 20,
55         color: grey["600"],
56         marginLeft: '3px',
57     },
58 });
59
60 export interface BreadcrumbsProps {
61     items: Breadcrumb[];
62     resources: ResourcesState;
63     onClick: (navFunc: (uuid: string) => void, breadcrumb: Breadcrumb) => void;
64     onContextMenu: (event: React.MouseEvent<HTMLElement>, breadcrumb: Breadcrumb) => void;
65 }
66
67 export const Breadcrumbs = withStyles(styles)(
68     ({ classes, onClick, onContextMenu, items, resources }: BreadcrumbsProps & WithStyles<CssRules>) =>
69     <Grid container data-cy='breadcrumbs' alignItems="center" wrap="nowrap">
70     {
71         items.map((item, index) => {
72             const isLastItem = index === items.length - 1;
73             const isFirstItem = index === 0;
74             const Icon = item.icon || (() => (null));
75             const resource = getResource(item.uuid)(resources) as any;
76             const navFunc = resource && 'groupClass' in resource && resource.groupClass === GroupClass.ROLE ? navigateToGroupDetails : navigateTo;
77
78             return (
79                 <React.Fragment key={index}>
80                     {isFirstItem ? null : <IllegalNamingWarning name={item.label} />}
81                     <Tooltip title={item.label} disableFocusListener>
82                         <Button
83                             data-cy={
84                                 isFirstItem
85                                 ? 'breadcrumb-first'
86                                 : isLastItem
87                                     ? 'breadcrumb-last'
88                                     : false}
89                             className={classNames(
90                                 isLastItem ? null : 'parentItem',
91                                 classes.item
92                             )}
93                             classes={{
94                                 label: classes.buttonLabel
95                             }}
96                             color="inherit"
97                             onClick={() => onClick(navFunc, item)}
98                             onContextMenu={event => onContextMenu(event, item)}>
99                             <Icon className={classes.icon} />
100                             <Typography
101                                 noWrap
102                                 color="inherit"
103                                 className={classes.label}>
104                                 {item.label}
105                             </Typography>
106                             {
107                                 (resources[item.uuid] as any)?.frozenByUuid ? <FreezeIcon className={classes.frozenIcon} /> : null
108                             }
109                         </Button>
110                     </Tooltip>
111                     {!isLastItem && <ChevronRightIcon color="inherit" className={classNames('parentItem', classes.chevron)} />}
112                 </React.Fragment>
113             );
114         })
115     }
116     </Grid>
117 );