Merge branch '21128-toolbar-context-menu'
[arvados-workbench2.git] / src / views-components / sharing-dialog / sharing-dialog-component.tsx
index 9344deaecd126fbc58e0f75ab2bd8959ac5173e8..f83cec60f24ec2662a73b10fdb3764e7f332c324 100644 (file)
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import * as React from 'react';
-import { Dialog, DialogTitle, Button, Grid, DialogContent, CircularProgress, Paper } from '@material-ui/core';
+import React from 'react';
+import {
+    Dialog,
+    DialogTitle,
+    Button,
+    Grid,
+    DialogContent,
+    CircularProgress,
+    Paper,
+    Tabs,
+    Tab,
+    Checkbox,
+    FormControlLabel,
+    Typography,
+} from '@material-ui/core';
+import {
+    StyleRulesCallback,
+    WithStyles,
+    withStyles
+} from '@material-ui/core/styles';
 import { DialogActions } from 'components/dialog-actions/dialog-actions';
-import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
-
+import { SharingURLsContent } from './sharing-urls';
+import {
+    extractUuidObjectType,
+    ResourceObjectType
+} from 'models/resource';
+import { SharingInvitationForm } from './sharing-invitation-form';
+import { SharingManagementForm } from './sharing-management-form';
+import {
+    BasePicker,
+    Calendar,
+    MuiPickersUtilsProvider,
+    TimePickerView
+} from 'material-ui-pickers';
+import DateFnsUtils from "@date-io/date-fns";
+import moment from 'moment';
+import { SharingPublicAccessForm } from './sharing-public-access-form';
 
 export interface SharingDialogDataProps {
     open: boolean;
     loading: boolean;
     saveEnabled: boolean;
-    advancedEnabled: boolean;
-    children: React.ReactNode;
+    sharedResourceUuid: string;
+    sharingURLsNr: number;
+    privateAccess: boolean;
+    sharingURLsDisabled: boolean;
+    permissions: any[];
 }
 export interface SharingDialogActionProps {
     onClose: () => void;
-    onExited: () => void;
     onSave: () => void;
-    onAdvanced: () => void;
+    onCreateSharingToken: (d: Date | undefined) => () => void;
+    refreshPermissions: () => void;
+}
+enum SharingDialogTab {
+    PERMISSIONS = 0,
+    URLS = 1,
 }
-export default (props: SharingDialogDataProps & SharingDialogActionProps) => {
-    const { children, open, loading, advancedEnabled, saveEnabled, onAdvanced, onClose, onExited, onSave } = props;
+export type SharingDialogComponentProps = SharingDialogDataProps & SharingDialogActionProps;
+
+export default (props: SharingDialogComponentProps) => {
+    const { open, loading, saveEnabled, sharedResourceUuid,
+        sharingURLsNr, privateAccess, sharingURLsDisabled,
+        onClose, onSave, onCreateSharingToken, refreshPermissions } = props;
+    const showTabs = !sharingURLsDisabled && extractUuidObjectType(sharedResourceUuid) === ResourceObjectType.COLLECTION;
+    const [tabNr, setTabNr] = React.useState<number>(SharingDialogTab.PERMISSIONS);
+    const [expDate, setExpDate] = React.useState<Date>();
+    const [withExpiration, setWithExpiration] = React.useState<boolean>(false);
+
+    // Sets up the dialog depending on the resource type
+    if (!showTabs && tabNr !== SharingDialogTab.PERMISSIONS) {
+        setTabNr(SharingDialogTab.PERMISSIONS);
+    }
+
+    React.useEffect(() => {
+        if (!withExpiration) {
+            setExpDate(undefined);
+        } else {
+            setExpDate(moment().add(2, 'hour').minutes(0).seconds(0).toDate());
+        }
+    }, [withExpiration]);
+
     return <Dialog
-        {...{ open, onClose, onExited }}
+        {...{ open, onClose }}
         className="sharing-dialog"
         fullWidth
         maxWidth='sm'
-        disableBackdropClick
-        disableEscapeKeyDown>
+        disableBackdropClick={saveEnabled}
+        disableEscapeKeyDown={saveEnabled}>
         <DialogTitle>
             Sharing settings
-            </DialogTitle>
+        </DialogTitle>
+        {showTabs &&
+            <Tabs value={tabNr}
+                onChange={(_, tb) => {
+                    if (tb === SharingDialogTab.PERMISSIONS) {
+                        refreshPermissions();
+                    }
+                    setTabNr(tb)
+                }
+                }>
+                <Tab label="With users/groups" />
+                <Tab label={`Sharing URLs ${sharingURLsNr > 0 ? '(' + sharingURLsNr + ')' : ''}`} disabled={saveEnabled} />
+            </Tabs>
+        }
         <DialogContent>
-            {children}
+            {tabNr === SharingDialogTab.PERMISSIONS &&
+                <Grid container direction='column' spacing={24}>
+                    <Grid item>
+                        <SharingInvitationForm onSave={onSave} saveEnabled={saveEnabled} />
+                    </Grid>
+                    <Grid item>
+                        <SharingManagementForm onSave={onSave} />
+                    </Grid>
+                    <Grid item>
+                        <SharingPublicAccessForm onSave={onSave} />
+                    </Grid>
+                </Grid>
+            }
+            {tabNr === SharingDialogTab.URLS &&
+                <SharingURLsContent uuid={sharedResourceUuid} />
+            }
         </DialogContent>
         <DialogActions>
             <Grid container spacing={8}>
-                {advancedEnabled &&
-                    <Grid item>
-                        <Button
-                            color='primary'
-                            onClick={onAdvanced}>
-                            Advanced
-                    </Button>
+                {tabNr === SharingDialogTab.URLS && withExpiration && <>
+                    <Grid item container direction='row' md={12}>
+                        <MuiPickersUtilsProvider utils={DateFnsUtils}>
+                            <BasePicker autoOk value={expDate} onChange={setExpDate}>
+                                {({ date, handleChange }) => (<>
+                                    <Grid item md={6}>
+                                        <Calendar date={date} minDate={new Date()} maxDate={undefined}
+                                            onChange={handleChange} />
+                                    </Grid>
+                                    <Grid item md={6}>
+                                        <TimePickerView type="hours" date={date} ampm={false}
+                                            onMinutesChange={() => { }}
+                                            onSecondsChange={() => { }}
+                                            onHourChange={handleChange}
+                                        />
+                                    </Grid>
+                                </>)}
+                            </BasePicker>
+                        </MuiPickersUtilsProvider>
+                    </Grid>
+                    <Grid item md={12}>
+                        <Typography variant='caption' align='center'>
+                            Maximum expiration date may be limited by the cluster configuration.
+                        </Typography>
+                    </Grid>
+                </>
+                }
+                {tabNr === SharingDialogTab.PERMISSIONS && !sharingURLsDisabled &&
+                    privateAccess && sharingURLsNr > 0 &&
+                    <Grid item md={12}>
+                        <Typography variant='caption' align='center' color='error'>
+                            Although there aren't specific permissions set, this is publicly accessible via Sharing URL(s).
+                        </Typography>
                     </Grid>
                 }
                 <Grid item xs />
+                {tabNr === SharingDialogTab.URLS && <>
+                    <Grid item><FormControlLabel
+                        control={<Checkbox color="primary" checked={withExpiration}
+                            onChange={(e) => setWithExpiration(e.target.checked)} />}
+                        label="With expiration" />
+                    </Grid>
+                    <Grid item>
+                        <Button variant="contained" color="primary"
+                            disabled={expDate !== undefined && expDate <= new Date()}
+                            onClick={onCreateSharingToken(expDate)}>
+                            Create sharing URL
+                        </Button>
+                    </Grid>
+                </>
+                }
                 <Grid item>
-                    <Button onClick={onClose}>
+                    <Button onClick={() => {
+                        onClose();
+                        setWithExpiration(false);
+                    }}>
                         Close
                     </Button>
                 </Grid>
-                <Grid item>
-                    <Button
-                        variant='contained'
-                        color='primary'
-                        onClick={onSave}
-                        disabled={!saveEnabled}>
-                        Save
-                    </Button>
-                </Grid>
             </Grid>
         </DialogActions>
         {