Merge branch 'main' into 21720-material-ui-upgrade
[arvados.git] / services / workbench2 / src / views-components / details-card / user-details-card.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 { CustomStyleRulesCallback } from 'common/custom-theme';
7 import { Card, CardHeader, Typography, Grid } from '@mui/material';
8 import { WithStyles } from '@mui/styles';
9 import withStyles from '@mui/styles/withStyles';
10 import { ArvadosTheme } from 'common/custom-theme';
11 import { UserResource } from 'models/user';
12 import { connect } from 'react-redux';
13 import { getResource } from 'store/resources/resources';
14 import { UserResourceAccountStatus } from 'views-components/data-explorer/renderers';
15 import { MultiselectToolbar } from 'components/multiselect-toolbar/MultiselectToolbar';
16 import { RootState } from 'store/store';
17 import { Dispatch } from 'redux';
18 import { loadDetailsPanel } from 'store/details-panel/details-panel-action';
19 import { setSelectedResourceUuid } from 'store/selected-resource/selected-resource-actions';
20 import { deselectAllOthers } from 'store/multiselect/multiselect-actions';
21 import { Resource } from 'models/resource';
22 import { ProjectResource } from 'models/project';
23
24 type CssRules = 'root' | 'cardHeaderContainer' | 'cardHeader' | 'userNameContainer' | 'accountStatusSection';
25
26 const styles: CustomStyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
27     root: {
28         width: '100%',
29         marginBottom: '1rem',
30         flex: '0 0 auto',
31         padding: 0,
32         minHeight: '3rem',
33     },
34     userNameContainer: {
35         display: 'flex',
36         alignItems: 'center',
37         minHeight: '2.7rem',
38     },
39     cardHeaderContainer: {
40         width: '100%',
41         display: 'flex',
42         flexDirection: 'row',
43         alignItems: 'center',
44         justifyContent: 'space-between',
45     },
46     cardHeader: {
47         minWidth: '30rem',
48         padding: '0.2rem 0.4rem 0.2rem 1rem',
49     },
50     accountStatusSection: {
51         display: 'flex',
52         flexDirection: 'row',
53         alignItems: 'center',
54         paddingLeft: '1rem',
55     },
56 });
57
58 const mapStateToProps = ({ auth, selectedResourceUuid, resources, properties }: RootState) => {
59     const currentResource = getResource(properties.currentRouteUuid)(resources);
60     const frozenByUser = currentResource && getResource((currentResource as ProjectResource).frozenByUuid as string)(resources);
61     const frozenByFullName = frozenByUser && (frozenByUser as Resource & { fullName: string }).fullName;
62     const isSelected = selectedResourceUuid === properties.currentRouteUuid;
63
64     return {
65         isAdmin: auth.user?.isAdmin,
66         currentResource,
67         frozenByFullName,
68         isSelected,
69     };
70 };
71
72 const mapDispatchToProps = (dispatch: Dispatch) => ({
73     handleCardClick: (uuid: string) => {
74         dispatch<any>(loadDetailsPanel(uuid));
75         dispatch<any>(setSelectedResourceUuid(uuid));
76         dispatch<any>(deselectAllOthers(uuid));
77     },
78 });
79
80 type UserCardProps = WithStyles<CssRules> & {
81     currentResource: UserResource;
82     isAdmin: boolean;
83     isSelected: boolean;
84     handleCardClick: (resource: any) => void;
85 };
86
87 export const UserCard = connect(
88     mapStateToProps,
89     mapDispatchToProps
90 )(
91     withStyles(styles)((props: UserCardProps) => {
92         const { classes, currentResource, handleCardClick, isSelected } = props;
93         const { fullName, uuid } = currentResource as UserResource & { fullName: string };
94
95         return (
96             <Card
97                 className={classes.root}
98                 onClick={() => handleCardClick(uuid)}
99                 data-cy='user-details-card'
100             >
101                 <Grid
102                     container
103                     wrap='nowrap'
104                     className={classes.cardHeaderContainer}
105                 >
106                     <CardHeader
107                         className={classes.cardHeader}
108                         title={
109                             <section className={classes.userNameContainer}>
110                                 <Typography
111                                     noWrap
112                                     variant='h6'
113                                 >
114                                     {fullName}
115                                 </Typography>
116                                 <section className={classes.accountStatusSection}>
117                                     {!currentResource.isActive && (
118                                         <Typography>
119                                             <UserResourceAccountStatus uuid={uuid} />
120                                         </Typography>
121                                     )}
122                                 </section>
123                             </section>
124                         }
125                     />
126                     {isSelected && <MultiselectToolbar />}
127                 </Grid>
128             </Card>
129         );
130     })
131 );