18284: Add update vm login dialog, remove default group, update tests
[arvados-workbench2.git] / src / views / virtual-machine-panel / virtual-machine-admin-panel.tsx
index a6ad24a7dbbc6c7206dcbe48d390efac7a24d6b9..468ef35a984da4f7a1198d886c576e4d9a9e33ba 100644 (file)
@@ -4,18 +4,19 @@
 
 import React from 'react';
 import { connect } from 'react-redux';
-import { Grid, Card, CardContent, TableBody, TableCell, TableHead, TableRow, Table, Tooltip, IconButton } from '@material-ui/core';
+import { Grid, Card, Chip, CardContent, TableBody, TableCell, TableHead, TableRow, Table, Tooltip, IconButton } from '@material-ui/core';
 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
 import { ArvadosTheme } from 'common/custom-theme';
 import { compose, Dispatch } from 'redux';
-import { loadVirtualMachinesAdminData } from 'store/virtual-machines/virtual-machines-actions';
+import { loadVirtualMachinesAdminData, openAddVirtualMachineLoginDialog, openRemoveVirtualMachineLoginDialog, openEditVirtualMachineLoginDialog } from 'store/virtual-machines/virtual-machines-actions';
 import { RootState } from 'store/store';
 import { ListResults } from 'services/common-service/common-service';
-import { MoreOptionsIcon } from 'components/icon/icon';
+import { MoreOptionsIcon, AddUserIcon } from 'components/icon/icon';
 import { VirtualMachineLogins, VirtualMachinesResource } from 'models/virtual-machines';
 import { openVirtualMachinesContextMenu } from 'store/context-menu/context-menu-actions';
+import { ResourceUuid, VirtualMachineHostname, VirtualMachineLogin } from 'views-components/data-explorer/renderers';
 
-type CssRules = 'moreOptionsButton' | 'moreOptions';
+type CssRules = 'moreOptionsButton' | 'moreOptions' | 'chipsRoot';
 
 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
     moreOptionsButton: {
@@ -27,6 +28,9 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
             paddingRight: 0
         }
     },
+    chipsRoot: {
+        margin: `0px -${theme.spacing.unit / 2}px`,
+    },
 });
 
 const mapStateToProps = (state: RootState) => {
@@ -36,22 +40,35 @@ const mapStateToProps = (state: RootState) => {
     };
 };
 
-const mapDispatchToProps = (dispatch: Dispatch): Pick<VirtualMachinesPanelActionProps, 'loadVirtualMachinesData' | 'onOptionsMenuOpen'> => ({
+const mapDispatchToProps = (dispatch: Dispatch): Pick<VirtualMachinesPanelActionProps, 'loadVirtualMachinesData' | 'onOptionsMenuOpen' | 'onAddLogin' | 'onDeleteLogin' | 'onLoginEdit'> => ({
     loadVirtualMachinesData: () => dispatch<any>(loadVirtualMachinesAdminData()),
     onOptionsMenuOpen: (event, virtualMachine) => {
         dispatch<any>(openVirtualMachinesContextMenu(event, virtualMachine));
     },
+    onAddLogin: (uuid: string) => {
+        dispatch<any>(openAddVirtualMachineLoginDialog(uuid));
+    },
+    onDeleteLogin: (uuid: string) => {
+        dispatch<any>(openRemoveVirtualMachineLoginDialog(uuid));
+    },
+    onLoginEdit: (uuid: string) => {
+        dispatch<any>(openEditVirtualMachineLoginDialog(uuid));
+    },
 });
 
 interface VirtualMachinesPanelDataProps {
     virtualMachines: ListResults<any>;
     logins: VirtualMachineLogins;
+    links: ListResults<any>;
     userUuid: string;
 }
 
 interface VirtualMachinesPanelActionProps {
     loadVirtualMachinesData: () => string;
     onOptionsMenuOpen: (event: React.MouseEvent<HTMLElement>, virtualMachine: VirtualMachinesResource) => void;
+    onAddLogin: (uuid: string) => void;
+    onDeleteLogin: (uuid: string) => void;
+    onLoginEdit: (uuid: string) => void;
 }
 
 type VirtualMachineProps = VirtualMachinesPanelActionProps & VirtualMachinesPanelDataProps & WithStyles<CssRules>;
@@ -85,24 +102,40 @@ const CardContentWithVirtualMachines = (props: VirtualMachineProps) =>
     </Grid>;
 
 const virtualMachinesTable = (props: VirtualMachineProps) =>
-    <Table>
+    <Table data-cy="vm-admin-table">
         <TableHead>
             <TableRow>
                 <TableCell>Uuid</TableCell>
                 <TableCell>Host name</TableCell>
                 <TableCell>Logins</TableCell>
                 <TableCell />
+                <TableCell />
             </TableRow>
         </TableHead>
         <TableBody>
-            {props.logins.items.length > 0 && props.virtualMachines.items.map((it, index) =>
+            {props.virtualMachines.items.map((machine, index) =>
                 <TableRow key={index}>
-                    <TableCell>{it.uuid}</TableCell>
-                    <TableCell>{it.hostname}</TableCell>
-                    <TableCell>["{props.logins.items.map(it => it.userUuid === props.userUuid ? it.username : '')}"]</TableCell>
+                    <TableCell><ResourceUuid uuid={machine.uuid} /></TableCell>
+                    <TableCell><VirtualMachineHostname uuid={machine.uuid} /></TableCell>
+                    <TableCell>
+                        <Grid container spacing={8} className={props.classes.chipsRoot}>
+                            {props.links.items.filter((link) => (link.headUuid === machine.uuid)).map((permission, i) => (
+                                <Grid item key={i}>
+                                    <Chip label={<VirtualMachineLogin linkUuid={permission.uuid} />} onDelete={event => props.onDeleteLogin(permission.uuid)} onClick={event => props.onLoginEdit(permission.uuid)} />
+                                </Grid>
+                            ))}
+                        </Grid>
+                    </TableCell>
+                    <TableCell>
+                        <Tooltip title="Add Login Permission" disableFocusListener>
+                            <IconButton onClick={event => props.onAddLogin(machine.uuid)} className={props.classes.moreOptionsButton}>
+                                <AddUserIcon />
+                            </IconButton>
+                        </Tooltip>
+                    </TableCell>
                     <TableCell className={props.classes.moreOptions}>
                         <Tooltip title="More options" disableFocusListener>
-                            <IconButton onClick={event => props.onOptionsMenuOpen(event, it)} className={props.classes.moreOptionsButton}>
+                            <IconButton onClick={event => props.onOptionsMenuOpen(event, machine)} className={props.classes.moreOptionsButton}>
                                 <MoreOptionsIcon />
                             </IconButton>
                         </Tooltip>