* When dealing with collections, adds a new tab for sharing URLs.
* Removes the "Advanced" mode and always show the permissions.
* Moves the "invitation form" to the dialog's action section so that it
keeps being visible when lots of permissions are set.
* Allow closing the dialog by clicking away or using the Esc key when no
pending changes need saving.
Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima <lucas.dipentima@curii.com>
import { progressIndicatorActions } from 'store/progress-indicator/progress-indicator-actions';
import { snackbarActions, SnackbarKind } from "../snackbar/snackbar-actions";
import { extractUuidKind, extractUuidObjectType, ResourceKind, ResourceObjectType } from "models/resource";
-import { ApiClientAuthorizationService } from "services/api-client-authorization-service/api-client-authorization-service";
import { resourcesActions } from "store/resources/resources-actions";
export const openSharingDialog = (resourceUuid: string, refresh?: () => void) =>
+++ /dev/null
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import React from 'react';
-
-export interface AdvancedViewSwitchInjectedProps {
- toggleAdvancedView: () => void;
- advancedViewOpen: boolean;
-}
-
-export const connectAdvancedViewSwitch = (Component: React.ComponentType<AdvancedViewSwitchInjectedProps>) =>
- class extends React.Component<{}, { advancedViewOpen: boolean }> {
-
- state = { advancedViewOpen: false };
-
- toggleAdvancedView = () => {
- this.setState(({ advancedViewOpen }) => ({ advancedViewOpen: !advancedViewOpen }));
- }
-
- render() {
- return <Component {...this.state} {...this} />;
- }
- };
-
\ No newline at end of file
// SPDX-License-Identifier: AGPL-3.0
import React from 'react';
-import { Dialog, DialogTitle, Button, Grid, DialogContent, CircularProgress, Paper } from '@material-ui/core';
+import {
+ Dialog,
+ DialogTitle,
+ Button,
+ Grid,
+ DialogContent,
+ CircularProgress,
+ Paper,
+ Tabs,
+ Tab,
+} 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 { SharingDialogContent } from './sharing-dialog-content';
+import { SharingURLsContent } from './sharing-urls';
+import {
+ extractUuidObjectType,
+ ResourceObjectType
+} from 'models/resource';
+import { SharingInvitationForm } from './sharing-invitation-form';
export interface SharingDialogDataProps {
open: boolean;
loading: boolean;
saveEnabled: boolean;
- advancedEnabled: boolean;
- children: React.ReactNode;
+ sharedResourceUuid: string;
}
export interface SharingDialogActionProps {
onClose: () => void;
- onExited: () => void;
onSave: () => void;
- onAdvanced: () => void;
+ onCreateSharingToken: () => void;
+}
+enum SharingDialogTab {
+ PERMISSIONS = 0,
+ URLS = 1,
}
export default (props: SharingDialogDataProps & SharingDialogActionProps) => {
- const { children, open, loading, advancedEnabled, saveEnabled, onAdvanced, onClose, onExited, onSave } = props;
+ const { open, loading, saveEnabled, sharedResourceUuid,
+ onClose, onSave, onCreateSharingToken } = props;
+ const showTabs = extractUuidObjectType(sharedResourceUuid) === ResourceObjectType.COLLECTION;
+ const [tabNr, setTabNr] = React.useState<number>(SharingDialogTab.PERMISSIONS);
+
+ // Sets up the dialog depending on the resource type
+ if (!showTabs && tabNr !== SharingDialogTab.PERMISSIONS) {
+ setTabNr(SharingDialogTab.PERMISSIONS);
+ }
+
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) => setTabNr(tb)}>
+ <Tab label="With users/groups" />
+ <Tab label="Sharing URLs" disabled={saveEnabled} />
+ </Tabs>
+ }
<DialogContent>
- {children}
+ { tabNr === SharingDialogTab.PERMISSIONS &&
+ <SharingDialogContent />
+ }
+ { tabNr === SharingDialogTab.URLS &&
+ <SharingURLsContent uuid={sharedResourceUuid} />
+ }
</DialogContent>
<DialogActions>
<Grid container spacing={8}>
- {advancedEnabled &&
- <Grid item>
- <Button
- color='primary'
- onClick={onAdvanced}>
- Advanced
- </Button>
- </Grid>
- }
- <Grid item xs />
+ { tabNr === SharingDialogTab.PERMISSIONS &&
+ <Grid item md={12}>
+ <SharingInvitationForm />
+ </Grid> }
+ { tabNr === SharingDialogTab.URLS &&
<Grid item>
- <Button onClick={onClose}>
- Close
+ <Button
+ variant="contained"
+ color="primary"
+ onClick={onCreateSharingToken}>
+ Create sharing URL
</Button>
</Grid>
+ }
+ <Grid item xs />
+ { tabNr === SharingDialogTab.PERMISSIONS &&
<Grid item>
<Button
variant='contained'
Save
</Button>
</Grid>
+ }
+ <Grid item>
+ <Button onClick={onClose}>
+ Close
+ </Button>
+ </Grid>
</Grid>
</DialogActions>
{
// SPDX-License-Identifier: AGPL-3.0
import React from 'react';
-import { Grid, Typography } from '@material-ui/core';
+import { Grid } from '@material-ui/core';
-import { SharingInvitationForm } from './sharing-invitation-form';
import { SharingManagementForm } from './sharing-management-form';
-import { SharingPublicAccessForm } from './sharing-public-access-form';
-export const SharingDialogContent = (props: { advancedViewOpen: boolean }) =>
+export const SharingDialogContent = () =>
<Grid container direction='column' spacing={24}>
- {props.advancedViewOpen &&
- <>
- <Grid item>
- <Typography variant='subtitle1'>
- Who can access
- </Typography>
- <SharingPublicAccessForm />
- <SharingManagementForm />
- </Grid>
- </>
- }
<Grid item>
- <SharingInvitationForm />
+ <SharingManagementForm />
</Grid>
</Grid>;
import { compose, Dispatch } from 'redux';
import { connect } from 'react-redux';
-
-import React from 'react';
-import { connectSharingDialog, saveSharingDialogChanges, connectSharingDialogProgress, sendSharingInvitations } from 'store/sharing-dialog/sharing-dialog-actions';
-import { WithDialogProps } from 'store/dialog/with-dialog';
import { RootState } from 'store/store';
-
-import SharingDialogComponent, { SharingDialogDataProps, SharingDialogActionProps } from './sharing-dialog-component';
-import { SharingDialogContent } from './sharing-dialog-content';
-import { connectAdvancedViewSwitch, AdvancedViewSwitchInjectedProps } from './advanced-view-switch';
-import { hasChanges } from 'store/sharing-dialog/sharing-dialog-types';
+import {
+ connectSharingDialog,
+ saveSharingDialogChanges,
+ connectSharingDialogProgress,
+ SharingDialogData,
+ createSharingToken
+} from 'store/sharing-dialog/sharing-dialog-actions';
+import { WithDialogProps } from 'store/dialog/with-dialog';
+import SharingDialogComponent, {
+ SharingDialogDataProps,
+ SharingDialogActionProps
+} from './sharing-dialog-component';
+import {
+ hasChanges,
+ SHARING_DIALOG_NAME
+} from 'store/sharing-dialog/sharing-dialog-types';
import { WithProgressStateProps } from 'store/progress-indicator/with-progress';
+import { getDialog } from 'store/dialog/dialog-reducer';
-type Props = WithDialogProps<string> & AdvancedViewSwitchInjectedProps & WithProgressStateProps;
+type Props = WithDialogProps<string> & WithProgressStateProps;
-const mapStateToProps = (state: RootState, { advancedViewOpen, working, ...props }: Props): SharingDialogDataProps => ({
+const mapStateToProps = (state: RootState, { working, ...props }: Props): SharingDialogDataProps => {
+ const dialog = getDialog<SharingDialogData>(state.dialog, SHARING_DIALOG_NAME);
+ return ({
...props,
saveEnabled: hasChanges(state),
loading: working,
- advancedEnabled: !advancedViewOpen,
- children: <SharingDialogContent {...{ advancedViewOpen }} />,
-});
+ sharedResourceUuid: dialog?.data.resourceUuid || '',
+ })
+};
-const mapDispatchToProps = (dispatch: Dispatch, { toggleAdvancedView, advancedViewOpen, ...props }: Props): SharingDialogActionProps => ({
+const mapDispatchToProps = (dispatch: Dispatch, { ...props }: Props): SharingDialogActionProps => ({
...props,
onClose: props.closeDialog,
- onExited: () => {
- if (advancedViewOpen) {
- toggleAdvancedView();
- }
- },
onSave: () => {
- if (advancedViewOpen) {
- dispatch<any>(saveSharingDialogChanges);
- } else {
- dispatch<any>(sendSharingInvitations);
- }
+ dispatch<any>(saveSharingDialogChanges);
},
- onAdvanced: toggleAdvancedView,
+ onCreateSharingToken: () => {
+ dispatch<any>(createSharingToken);
+ }
});
export const SharingDialog = compose(
- connectAdvancedViewSwitch,
connectSharingDialog,
connectSharingDialogProgress,
connect(mapStateToProps, mapDispatchToProps)