Add site manager and initial validation
[arvados-workbench2.git] / src / views / site-manager-panel / site-manager-panel-root.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 {
7     Card,
8     CardContent,
9     Grid,
10     StyleRulesCallback,
11     Table,
12     TableBody,
13     TableCell,
14     TableHead,
15     TableRow,
16     Typography,
17     WithStyles,
18     withStyles
19 } from '@material-ui/core';
20 import { ArvadosTheme } from '~/common/custom-theme';
21 import { Session } from "~/models/session";
22 import Button from "@material-ui/core/Button";
23 import { User } from "~/models/user";
24 import { compose } from "redux";
25 import { Field, InjectedFormProps, reduxForm, reset } from "redux-form";
26 import { TextField } from "~/components/text-field/text-field";
27 import { addSession } from "~/store/auth/auth-action-session";
28 import { SITE_MANAGER_REMOTE_HOST_VALIDATION } from "~/validators/validators";
29
30 type CssRules = 'root' | 'link' | 'buttonContainer' | 'table' | 'tableRow' | 'status' | 'remoteSiteInfo' | 'buttonAdd';
31
32 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
33     root: {
34        width: '100%',
35        overflow: 'auto'
36     },
37     link: {
38         color: theme.palette.primary.main,
39         textDecoration: 'none',
40         margin: '0px 4px'
41     },
42     buttonContainer: {
43         textAlign: 'right'
44     },
45     table: {
46         marginTop: theme.spacing.unit
47     },
48     tableRow: {
49         '& td, th': {
50             whiteSpace: 'nowrap'
51         }
52     },
53     status: {
54         width: 100,
55         padding: 5,
56         fontWeight: 'bold',
57         textAlign: 'center',
58         borderRadius: 4
59     },
60     remoteSiteInfo: {
61         marginTop: 20
62     },
63     buttonAdd: {
64         marginLeft: 10,
65         marginTop: theme.spacing.unit * 3
66     }
67 });
68
69 export interface SiteManagerPanelRootActionProps {
70 }
71
72 export interface SiteManagerPanelRootDataProps {
73     sessions: Session[];
74     user: User;
75 }
76
77 type SiteManagerPanelRootProps = SiteManagerPanelRootDataProps & SiteManagerPanelRootActionProps & WithStyles<CssRules> & InjectedFormProps;
78 const SITE_MANAGER_FORM_NAME = 'siteManagerForm';
79
80 export const SiteManagerPanelRoot = compose(
81     reduxForm<{remoteHost: string}>({
82         form: SITE_MANAGER_FORM_NAME,
83         onSubmit: (data, dispatch) => {
84             dispatch(addSession(data.remoteHost));
85             dispatch(reset(SITE_MANAGER_FORM_NAME));
86         }
87     }),
88     withStyles(styles))
89     (({ classes, sessions, handleSubmit }: SiteManagerPanelRootProps) =>
90         <Card className={classes.root}>
91             <CardContent>
92                 <Grid container direction="row">
93                     <Grid item xs={12}>
94                         <Typography variant='body1' paragraph={true} >
95                             You can log in to multiple Arvados sites here, then use the multi-site search page to search collections and projects on all sites at once.
96                         </Typography>
97                     </Grid>
98                 </Grid>
99                 <Grid item xs={12}>
100                     {sessions.length > 0 && <Table className={classes.table}>
101                         <TableHead>
102                             <TableRow className={classes.tableRow}>
103                                 <TableCell>Cluster ID</TableCell>
104                                 <TableCell>Username</TableCell>
105                                 <TableCell>Email</TableCell>
106                                 <TableCell>Status</TableCell>
107                             </TableRow>
108                         </TableHead>
109                         <TableBody>
110                             {sessions.map((session, index) =>
111                                 <TableRow key={index} className={classes.tableRow}>
112                                     <TableCell>{session.clusterId}</TableCell>
113                                     <TableCell>{session.username}</TableCell>
114                                     <TableCell>{session.email}</TableCell>
115                                     <TableCell>
116                                         <div className={classes.status} style={{
117                                             color: session.loggedIn ? '#fff' : '#000',
118                                             backgroundColor: session.loggedIn ? '#009966' : '#FFC414'
119                                         }}>
120                                             {session.loggedIn ? "Logged in" : "Logged out"}
121                                         </div>
122                                     </TableCell>
123                                 </TableRow>)}
124                         </TableBody>
125                     </Table>}
126                 </Grid>
127                 <form onSubmit={handleSubmit}>
128                     <Grid container direction="row">
129                         <Grid item xs={12}>
130                             <Typography variant='body1' paragraph={true} className={classes.remoteSiteInfo}>
131                                 To add a remote Arvados site, paste the remote site's host here (see "ARVADOS_API_HOST" on the "current token" page).
132                             </Typography>
133                         </Grid>
134                         <Grid item xs={8}>
135                             <Field
136                                 name='remoteHost'
137                                 validate={SITE_MANAGER_REMOTE_HOST_VALIDATION}
138                                 component={TextField}
139                                 placeholder="zzzz.arvadosapi.com"
140                                 margin="normal"
141                                 label="New cluster"/>
142                         </Grid>
143                         <Grid item xs={3}>
144                             <Button type="submit" variant="contained" color="primary"
145                                 className={classes.buttonAdd}>
146                                 {"ADD"}</Button>
147                         </Grid>
148                     </Grid>
149                 </form>
150             </CardContent>
151         </Card>
152     );