15088: Adds invalid states and UI and improves action error handling
[arvados-workbench2.git] / src / views / link-account-panel / link-account-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     StyleRulesCallback,
8     WithStyles,
9     withStyles,
10     Card,
11     CardContent,
12     Button,
13     Typography,
14     Grid,
15 } from '@material-ui/core';
16 import { ArvadosTheme } from '~/common/custom-theme';
17 import { UserResource } from "~/models/user";
18 import { LinkAccountType } from "~/models/link-account";
19 import { formatDate } from "~/common/formatters";
20 import { LinkAccountPanelStatus, LinkAccountPanelError } from "~/store/link-account-panel/link-account-panel-reducer";
21
22 type CssRules = 'root';// | 'gridItem' | 'label' | 'title' | 'actions';
23
24 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
25     root: {
26         width: '100%',
27         overflow: 'auto'
28     }
29 });
30
31 export interface LinkAccountPanelRootDataProps {
32     user?: UserResource;
33     userToLink?: UserResource;
34     status : LinkAccountPanelStatus;
35     error: LinkAccountPanelError;
36 }
37
38 export interface LinkAccountPanelRootActionProps {
39     saveAccountLinkData: (type: LinkAccountType) => void;
40     removeAccountLinkData: () => void;
41     linkAccount: () => void;
42 }
43
44 function displayUser(user: UserResource, showCreatedAt: boolean = false) {
45     const disp = [];
46     disp.push(<span><b>{user.email}</b> ({user.username}, {user.uuid})</span>);
47     if (showCreatedAt) {
48         disp.push(<span> created on <b>{formatDate(user.createdAt)}</b></span>);
49     }
50     return disp;
51 }
52
53 type LinkAccountPanelRootProps = LinkAccountPanelRootDataProps & LinkAccountPanelRootActionProps & WithStyles<CssRules>;
54
55 export const LinkAccountPanelRoot = withStyles(styles) (
56     ({classes, user, userToLink, status, error, saveAccountLinkData, removeAccountLinkData, linkAccount}: LinkAccountPanelRootProps) => {
57         return <Card className={classes.root}>
58             <CardContent>
59             { status === LinkAccountPanelStatus.INITIAL && user &&
60             <Grid container spacing={24}>
61                 <Grid container item direction="column" spacing={24}>
62                     <Grid item>
63                         You are currently logged in as {displayUser(user, true)}
64                     </Grid>
65                     <Grid item>
66                         You can link Arvados accounts. After linking, either login will take you to the same account.
67                     </Grid>
68                 </Grid>
69                 <Grid container item direction="row" spacing={24}>
70                     <Grid item>
71                         <Button color="primary" variant="contained" onClick={() => saveAccountLinkData(LinkAccountType.ADD_OTHER_LOGIN)}>
72                             Add another login to this account
73                         </Button>
74                     </Grid>
75                     <Grid item>
76                         <Button color="primary" variant="contained" onClick={() => saveAccountLinkData(LinkAccountType.ACCESS_OTHER_ACCOUNT)}>
77                             Use this login to access another account
78                         </Button>
79                     </Grid>
80                 </Grid>
81             </Grid> }
82             { (status === LinkAccountPanelStatus.LINKING || status === LinkAccountPanelStatus.ERROR) && userToLink && user &&
83             <Grid container spacing={24}>
84                 { status === LinkAccountPanelStatus.LINKING && <Grid container item direction="column" spacing={24}>
85                     <Grid item>
86                         Clicking 'Link accounts' will link {displayUser(user, true)} to {displayUser(userToLink, true)}.
87                     </Grid>
88                     <Grid item>
89                         After linking, logging in as {displayUser(user)} will log you into the same account as {displayUser(userToLink)}.
90                     </Grid>
91                     <Grid item>
92                        Any object owned by {displayUser(user)} will be transfered to {displayUser(userToLink)}.
93                     </Grid>
94                 </Grid> }
95                 { error === LinkAccountPanelError.NON_ADMIN && <Grid item>
96                     Cannot link admin account {displayUser(userToLink)} to non-admin account {displayUser(user)}.
97                 </Grid> }
98                 { error === LinkAccountPanelError.SAME_USER && <Grid item>
99                     Cannot link {displayUser(userToLink)} to the same account.
100                 </Grid> }
101                 <Grid container item direction="row" spacing={24}>
102                     <Grid item>
103                         <Button variant="contained" onClick={() => removeAccountLinkData()}>
104                             Cancel
105                         </Button>
106                     </Grid>
107                     <Grid item>
108                         <Button disabled={status === LinkAccountPanelStatus.ERROR} color="primary" variant="contained" onClick={() => linkAccount()}>
109                             Link accounts
110                         </Button>
111                     </Grid>
112                 </Grid>
113             </Grid> }
114             </CardContent>
115         </Card> ;
116 });