20085: Fix quirky behavior when removing share with public/all users row
authorPeter Amstutz <peter.amstutz@curii.com>
Tue, 4 Apr 2023 17:37:36 +0000 (13:37 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Tue, 4 Apr 2023 17:37:36 +0000 (13:37 -0400)
Fix some runtime warnings

Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

src/services/common-service/common-service.ts
src/store/sharing-dialog/sharing-dialog-actions.ts
src/views-components/sharing-dialog/sharing-dialog-component.tsx
src/views-components/sharing-dialog/sharing-invitation-form-component.tsx
src/views-components/sharing-dialog/sharing-public-access-form-component.tsx
src/views-components/sharing-dialog/sharing-urls-component.tsx
src/views-components/sharing-dialog/visibility-level-select.tsx

index 4b857eddbb8233239d2d4d152928f0a93c86e9e1..8e9fe631701bd0877075774f6d3666dd9fa73ec1 100644 (file)
@@ -107,12 +107,14 @@ export class CommonService<T> {
         );
     }
 
-    delete(uuid: string): Promise<T> {
+    delete(uuid: string, showErrors?: boolean): Promise<T> {
         this.validateUuid(uuid);
         return CommonService.defaultResponse(
             this.serverApi
                 .delete(`/${this.resourceType}/${uuid}`),
-            this.actions
+            this.actions,
+            true, // mapKeys
+            showErrors
         );
     }
 
index c998e7671154843632eaa290eddfff369fcc4195..fb34398e8dfd6ff5b29dceec941aafddf1f108d4 100644 (file)
@@ -49,8 +49,8 @@ export const connectSharingDialogProgress = withProgress(SHARING_DIALOG_NAME);
 
 export const saveSharingDialogChanges = async (dispatch: Dispatch, getState: () => RootState) => {
     dispatch(progressIndicatorActions.START_WORKING(SHARING_DIALOG_NAME));
-    await dispatch<any>(saveManagementChanges);
     await dispatch<any>(savePublicPermissionChanges);
+    await dispatch<any>(saveManagementChanges);
     await dispatch<any>(sendInvitations);
     dispatch(reset(SHARING_INVITATION_FORM_NAME));
     await dispatch<any>(loadSharingDialog);
@@ -236,7 +236,7 @@ const savePublicPermissionChanges = async (_: Dispatch, getState: () => RootStat
         // If visibility level changed, delete the previous link to public/all users.
         // On PRIVATE this link will be deleted by saveManagementChanges
         // so don't double delete (which would show an error dialog).
-        if (permissionUuid !== "" && visibility !== initialVisibility && visibility !== VisibilityLevel.PRIVATE) {
+        if (permissionUuid !== "" && visibility !== initialVisibility) {
             await permissionService.delete(permissionUuid);
         }
         if (visibility === VisibilityLevel.ALL_USERS) {
@@ -272,10 +272,16 @@ const saveManagementChanges = async (_: Dispatch, getState: () => RootState, { p
                 (a, b) => a.permissionUuid === b.permissionUuid
             );
 
-        const deletions = cancelledPermissions.map(({ permissionUuid }) =>
-            permissionService.delete(permissionUuid));
-        const updates = permissions.map(update =>
-            permissionService.update(update.permissionUuid, { name: update.permissions }));
+        const deletions = cancelledPermissions.map(async ({ permissionUuid }) => {
+            try {
+                await permissionService.delete(permissionUuid, false);
+            } catch (e) { }
+        });
+        const updates = permissions.map(async update => {
+            try {
+                await permissionService.update(update.permissionUuid, { name: update.permissions }, false);
+            } catch (e) { }
+        });
         await Promise.all([...deletions, ...updates]);
     }
 };
index ac1ebde1a016a81e435235426ddd8881ed04c1de..089eee8d9683d82a0e2340be5deae3abb6f04204 100644 (file)
@@ -90,7 +90,7 @@ export default (props: SharingDialogComponentProps) => {
         {...{ open, onClose }}
         className="sharing-dialog"
         fullWidth
-        maxWidth='sm'
+        maxWidth='md'
         disableBackdropClick={saveEnabled}
         disableEscapeKeyDown={saveEnabled}>
         <DialogTitle>
index 17f3250a416c9b464c9117b7da0b41af2218779f..3ff98b0a291bd61b0e68f9d1cf7a97b621ba9307 100644 (file)
@@ -49,15 +49,15 @@ const StyledSharingInvitationFormComponent = withStyles(styles)(
             </Grid>
             <Grid data-cy="permission-select-field" item xs={4} container wrap='nowrap'>
                 <PermissionSelectField />
-                <Tooltip title="Add authorization">
-                    <IconButton onClick={onSave} disabled={!saveEnabled} color="primary" classes={{
-                        root: classes.addButtonRoot,
-                        colorPrimary: classes.addButtonPrimary,
-                        disabled: classes.addButtonDisabled
-                    }}>
+                <IconButton onClick={onSave} disabled={!saveEnabled} color="primary" classes={{
+                    root: classes.addButtonRoot,
+                    colorPrimary: classes.addButtonPrimary,
+                    disabled: classes.addButtonDisabled
+                }}>
+                    <Tooltip title="Add authorization">
                         <AddIcon />
-                    </IconButton>
-                </Tooltip>
+                    </Tooltip>
+                </IconButton>
             </Grid>
         </Grid >);
 
index a9c9d6fc1aef0ad0ae71ccbf4d7dd4fbdc97fa2a..bcee8dceae3f6bee49746666ebe000dc6211e5d4 100644 (file)
@@ -60,4 +60,4 @@ const SharingPublicAccessFormComponent = ({ visibility, includePublic, onSave }:
 export default SharingPublicAccessFormComponent;
 
 const VisibilityLevelSelectComponent = ({ input, includePublic }: { includePublic: boolean } & WrappedFieldProps) =>
-    <VisibilityLevelSelect fullWidth disableUnderline {...input} includePublic={includePublic} />;
+    <VisibilityLevelSelect fullWidth disableUnderline includePublic={includePublic} {...input} />;
index c9cbc0df3d5e2f20ad0818a6ee8281e91fb868f8..5facb2e3812e61b43394cb220c299741e64c6451 100644 (file)
@@ -14,7 +14,7 @@ import {
     withStyles
 } from '@material-ui/core';
 import { ApiClientAuthorization } from 'models/api-client-authorization';
-import { CopyIcon, RemoveIcon } from 'components/icon/icon';
+import { CopyIcon, CloseIcon } from 'components/icon/icon';
 import CopyToClipboard from 'react-copy-to-clipboard';
 import { ArvadosTheme } from 'common/custom-theme';
 import moment from 'moment';
@@ -58,38 +58,38 @@ export interface SharingURLsComponentActionProps {
 export type SharingURLsComponentProps = SharingURLsComponentDataProps & SharingURLsComponentActionProps;
 
 export const SharingURLsComponent = withStyles(styles)((props: SharingURLsComponentProps & WithStyles<CssRules>) => <Grid container direction='column' spacing={24} className={props.classes.sharingUrlList}>
-    { props.sharingTokens.length > 0
-    ? props.sharingTokens
-    .sort((a, b) => (new Date(a.expiresAt).getTime() - new Date(b.expiresAt).getTime()))
-    .map(token => {
-        const url = props.sharingURLsPrefix.includes('*')
-        ? `${props.sharingURLsPrefix.replace('*', props.collectionUuid)}/t=${token.apiToken}/_/`
-        : `${props.sharingURLsPrefix}/c=${props.collectionUuid}/t=${token.apiToken}/_/`;
-        const expDate = new Date(token.expiresAt);
-        const urlLabel = !!token.expiresAt
-        ? `Token ${token.apiToken.slice(0, 8)}... expiring at: ${expDate.toLocaleString()} (${moment(expDate).fromNow()})`
-        : `Token ${token.apiToken.slice(0, 8)}... with no expiration date`;
+    {props.sharingTokens.length > 0
+        ? props.sharingTokens
+            .sort((a, b) => (new Date(a.expiresAt).getTime() - new Date(b.expiresAt).getTime()))
+            .map(token => {
+                const url = props.sharingURLsPrefix.includes('*')
+                    ? `${props.sharingURLsPrefix.replace('*', props.collectionUuid)}/t=${token.apiToken}/_/`
+                    : `${props.sharingURLsPrefix}/c=${props.collectionUuid}/t=${token.apiToken}/_/`;
+                const expDate = new Date(token.expiresAt);
+                const urlLabel = !!token.expiresAt
+                    ? `Token ${token.apiToken.slice(0, 8)}... expiring at: ${expDate.toLocaleString()} (${moment(expDate).fromNow()})`
+                    : `Token ${token.apiToken.slice(0, 8)}... with no expiration date`;
 
-        return <Grid container alignItems='center' key={token.uuid}  className={props.classes.sharingUrlRow}>
-            <Grid item>
-            <Link className={props.classes.sharingUrlText} href={url} target='_blank'>
-                {urlLabel}
-            </Link>
-            </Grid>
-            <Grid item xs />
-            <Grid item>
-            <span className={props.classes.sharingUrlButton}><Tooltip title='Copy to clipboard'>
-                <CopyToClipboard text={url} onCopy={() => props.onCopy('Sharing URL copied')}>
-                    <CopyIcon />
-                </CopyToClipboard>
-            </Tooltip></span>
-            <span data-cy='remove-url-btn' className={props.classes.sharingUrlButton}><Tooltip title='Remove'>
-                <IconButton onClick={() => props.onDeleteSharingToken(token.uuid)}>
-                    <RemoveIcon />
-                </IconButton>
-            </Tooltip></span>
-            </Grid>
-        </Grid>
-    })
-    : <Grid item><Typography>No sharing URLs</Typography></Grid> }
+                return <Grid container alignItems='center' key={token.uuid} className={props.classes.sharingUrlRow}>
+                    <Grid item>
+                        <Link className={props.classes.sharingUrlText} href={url} target='_blank'>
+                            {urlLabel}
+                        </Link>
+                    </Grid>
+                    <Grid item xs />
+                    <Grid item>
+                        <span className={props.classes.sharingUrlButton}><Tooltip title='Copy to clipboard'>
+                            <CopyToClipboard text={url} onCopy={() => props.onCopy('Sharing URL copied')}>
+                                <CopyIcon />
+                            </CopyToClipboard>
+                        </Tooltip></span>
+                        <span data-cy='remove-url-btn' className={props.classes.sharingUrlButton}><Tooltip title='Remove'>
+                            <IconButton onClick={() => props.onDeleteSharingToken(token.uuid)}>
+                                <CloseIcon />
+                            </IconButton>
+                        </Tooltip></span>
+                    </Grid>
+                </Grid>
+            })
+        : <Grid item><Typography>No sharing URLs</Typography></Grid>}
 </Grid>);
index c869e739021daa1fda40dd0106f9a9f6062c0954..4f12e3eacd203b6ece64a848abcd0d36a8da6746 100644 (file)
@@ -13,20 +13,20 @@ import { SelectItem } from './select-item';
 import { VisibilityLevel } from 'store/sharing-dialog/sharing-dialog-types';
 
 
-type VisibilityLevelSelectClasses = 'value';
+type VisibilityLevelSelectClasses = 'root';
 
 const VisibilityLevelSelectStyles: StyleRulesCallback<VisibilityLevelSelectClasses> = theme => ({
-    value: {
+    root: {
         marginLeft: theme.spacing.unit,
     }
 });
 export const VisibilityLevelSelect = withStyles(VisibilityLevelSelectStyles)(
-    ({ classes, ...props }: { includePublic: boolean } & SelectProps & WithStyles<VisibilityLevelSelectClasses>) =>
+    ({ classes, includePublic, ...props }: { includePublic: boolean } & SelectProps & WithStyles<VisibilityLevelSelectClasses>) =>
         <Select
             {...props}
             renderValue={renderPermissionItem}
             inputProps={{ classes }}>
-            {props.includePublic && <MenuItem value={VisibilityLevel.PUBLIC}>
+            {includePublic && <MenuItem value={VisibilityLevel.PUBLIC}>
                 {renderPermissionItem(VisibilityLevel.PUBLIC)}
             </MenuItem>}
             <MenuItem value={VisibilityLevel.ALL_USERS}>