[ARVADOS-WORKBENCH2] updated: 2.3.0-43-g416d4f0f
Git user
git at public.arvados.org
Tue Nov 30 19:15:28 UTC 2021
Summary of changes:
cypress/integration/group-manage.spec.js | 9 +---
src/components/icon/icon.tsx | 5 ++
src/index.tsx | 2 +
src/store/context-menu/context-menu-actions.ts | 14 ++++++
.../group-details-panel-actions.ts | 30 ++---------
.../action-sets/permission-edit-action-set.ts | 28 +++++++++++
src/views-components/context-menu/context-menu.tsx | 1 +
src/views-components/data-explorer/renderers.tsx | 58 +++++++++++-----------
.../dialog-forms/edit-permission-level-dialog.tsx | 55 --------------------
.../group-details-panel/group-details-panel.tsx | 15 ------
src/views/workbench/workbench.tsx | 2 -
11 files changed, 82 insertions(+), 137 deletions(-)
create mode 100644 src/views-components/context-menu/action-sets/permission-edit-action-set.ts
delete mode 100644 src/views-components/dialog-forms/edit-permission-level-dialog.tsx
via 416d4f0f57336b2225bcc82b0f4db8873adf8cd2 (commit)
from 705b5cc1072bfb178195a90091e6d3dc120d193d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 416d4f0f57336b2225bcc82b0f4db8873adf8cd2
Author: Stephen Smith <stephen at curii.com>
Date: Tue Nov 30 14:15:11 2021 -0500
18123: Change edit permission level to context menu.
Arvados-DCO-1.1-Signed-off-by: Stephen Smith <stephen at curii.com>
diff --git a/cypress/integration/group-manage.spec.js b/cypress/integration/group-manage.spec.js
index 8f630033..690102c0 100644
--- a/cypress/integration/group-manage.spec.js
+++ b/cypress/integration/group-manage.spec.js
@@ -93,16 +93,9 @@ describe('Group manage tests', function() {
cy.get('button').click();
});
});
- cy.get('[data-cy=form-dialog]')
- .should('contain', 'Edit permission')
- .within(() => {
- cy.contains('Read').click();
- });
- cy.get('li span')
+ cy.get('[data-cy=context-menu]')
.contains('Write')
- .parents('li')
.click();
- cy.get('[data-cy=form-dialog] button[type=submit]').click();
cy.get('[data-cy=group-members-data-explorer]')
.contains('Other User')
.parents('tr')
diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx
index 26ce4fea..f4a1b1f3 100644
--- a/src/components/icon/icon.tsx
+++ b/src/components/icon/icon.tsx
@@ -61,6 +61,8 @@ import StarBorder from '@material-ui/icons/StarBorder';
import Warning from '@material-ui/icons/Warning';
import VpnKey from '@material-ui/icons/VpnKey';
import LinkOutlined from '@material-ui/icons/LinkOutlined';
+import RemoveRedEye from '@material-ui/icons/RemoveRedEye';
+import Computer from '@material-ui/icons/Computer';
// Import FontAwesome icons
import { library } from '@fortawesome/fontawesome-svg-core';
@@ -148,3 +150,6 @@ export const WorkflowIcon: IconType = (props) => <Code {...props} />;
export const WarningIcon: IconType = (props) => <Warning style={{ color: '#fbc02d', height: '30px', width: '30px' }} {...props} />;
export const Link: IconType = (props) => <LinkOutlined {...props} />;
export const FolderSharedIcon: IconType = (props) => <FolderShared {...props} />;
+export const CanReadIcon: IconType = (props) => <RemoveRedEye {...props} />;
+export const CanWriteIcon: IconType = (props) => <Edit {...props} />;
+export const CanManageIcon: IconType = (props) => <Computer {...props} />;
diff --git a/src/index.tsx b/src/index.tsx
index 6ad22a55..0b04c29e 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -59,6 +59,7 @@ import { linkActionSet } from 'views-components/context-menu/action-sets/link-ac
import { loadFileViewersConfig } from 'store/file-viewers/file-viewers-actions';
import { processResourceAdminActionSet } from 'views-components/context-menu/action-sets/process-resource-admin-action-set';
import { filterGroupAdminActionSet, projectAdminActionSet } from 'views-components/context-menu/action-sets/project-admin-action-set';
+import { permissionEditActionSet } from 'views-components/context-menu/action-sets/permission-edit-action-set';
import { snackbarActions, SnackbarKind } from "store/snackbar/snackbar-actions";
import { openNotFoundDialog } from './store/not-found-panel/not-found-panel-action';
import { storeRedirects } from './common/redirect-to';
@@ -99,6 +100,7 @@ addMenuActionSet(ContextMenuKind.COLLECTION_ADMIN, collectionAdminActionSet);
addMenuActionSet(ContextMenuKind.PROCESS_ADMIN, processResourceAdminActionSet);
addMenuActionSet(ContextMenuKind.PROJECT_ADMIN, projectAdminActionSet);
addMenuActionSet(ContextMenuKind.FILTER_GROUP_ADMIN, filterGroupAdminActionSet);
+addMenuActionSet(ContextMenuKind.PERMISSION_EDIT, permissionEditActionSet);
storeRedirects();
diff --git a/src/store/context-menu/context-menu-actions.ts b/src/store/context-menu/context-menu-actions.ts
index 59a6813b..9a8733ba 100644
--- a/src/store/context-menu/context-menu-actions.ts
+++ b/src/store/context-menu/context-menu-actions.ts
@@ -20,6 +20,7 @@ import { ProcessResource } from 'models/process';
import { CollectionResource } from 'models/collection';
import { GroupClass, GroupResource } from 'models/group';
import { GroupContentsResource } from 'services/groups-service/groups-service';
+import { LinkResource } from 'models/link';
export const contextMenuActions = unionize({
OPEN_CONTEXT_MENU: ofType<{ position: ContextMenuPosition, resource: ContextMenuResource }>(),
@@ -193,6 +194,19 @@ export const openProcessContextMenu = (event: React.MouseEvent<HTMLElement>, pro
}
};
+export const openPermissionEditContextMenu = (event: React.MouseEvent<HTMLElement>, link: LinkResource) =>
+ (dispatch: Dispatch, getState: () => RootState) => {
+ if (link) {
+ dispatch<any>(openContextMenu(event, {
+ name: link.name,
+ uuid: link.uuid,
+ kind: link.kind,
+ menuKind: ContextMenuKind.PERMISSION_EDIT,
+ ownerUuid: link.ownerUuid,
+ }));
+ }
+ };
+
export const resourceUuidToContextMenuKind = (uuid: string, readonly = false) =>
(dispatch: Dispatch, getState: () => RootState) => {
const { isAdmin: isAdminUser, uuid: userUuid } = getState().auth.user!;
diff --git a/src/store/group-details-panel/group-details-panel-actions.ts b/src/store/group-details-panel/group-details-panel-actions.ts
index 43349fa9..916d68a7 100644
--- a/src/store/group-details-panel/group-details-panel-actions.ts
+++ b/src/store/group-details-panel/group-details-panel-actions.ts
@@ -8,16 +8,14 @@ import { propertiesActions } from 'store/properties/properties-actions';
import { getProperty } from 'store/properties/properties';
import { Participant } from 'views-components/sharing-dialog/participant-select';
import { dialogActions } from 'store/dialog/dialog-actions';
-import { initialize, reset, startSubmit } from 'redux-form';
+import { reset, startSubmit } from 'redux-form';
import { addGroupMember, deleteGroupMember } from 'store/groups-panel/groups-panel-actions';
import { getResource } from 'store/resources/resources';
import { GroupResource } from 'models/group';
-import { Resource } from 'models/resource';
import { RootState } from 'store/store';
import { ServiceRepository } from 'services/services';
import { PermissionResource, PermissionLevel } from 'models/permission';
import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
-import { PermissionSelectValue, parsePermissionLevel, formatPermissionLevel } from 'views-components/sharing-dialog/permission-select';
import { LinkResource } from 'models/link';
import { deleteResources } from 'store/resources/resources-actions';
@@ -28,10 +26,6 @@ export const ADD_GROUP_MEMBERS_FORM = 'addGroupMembers';
export const ADD_GROUP_MEMBERS_USERS_FIELD_NAME = 'users';
export const MEMBER_ATTRIBUTES_DIALOG = 'memberAttributesDialog';
export const MEMBER_REMOVE_DIALOG = 'memberRemoveDialog';
-export const EDIT_PERMISSION_LEVEL_DIALOG = 'editPermissionLevel';
-export const EDIT_PERMISSION_LEVEL_FORM = 'editPermissionLevel';
-export const EDIT_PERMISSION_LEVEL_FIELD_NAME = 'name';
-export const EDIT_PERMISSION_LEVEL_UUID_FIELD_NAME = 'uuid';
export const GroupMembersPanelActions = bindDataExplorerActions(GROUP_DETAILS_MEMBERS_PANEL_ID);
export const GroupPermissionsPanelActions = bindDataExplorerActions(GROUP_DETAILS_PERMISSIONS_PANEL_ID);
@@ -50,11 +44,6 @@ export interface AddGroupMembersFormData {
[ADD_GROUP_MEMBERS_USERS_FIELD_NAME]: Participant[];
}
-export interface EditPermissionLevelFormData {
- [EDIT_PERMISSION_LEVEL_UUID_FIELD_NAME]: string;
- [EDIT_PERMISSION_LEVEL_FIELD_NAME]: PermissionSelectValue;
-}
-
export const openAddGroupMembersDialog = () =>
(dispatch: Dispatch) => {
dispatch(dialogActions.OPEN_DIALOG({ id: ADD_GROUP_MEMBERS_DIALOG, data: {} }));
@@ -93,23 +82,10 @@ export const addGroupMembers = ({ users }: AddGroupMembersFormData) =>
}
};
-export const openEditPermissionLevelDialog = (linkUuid: string, resourceUuid: string) =>
- async (dispatch: Dispatch, getState: () => RootState) => {
- const link = getResource<PermissionResource>(linkUuid)(getState().resources);
- const resource = getResource<Resource>(resourceUuid)(getState().resources);
-
- if (link) {
- dispatch(reset(EDIT_PERMISSION_LEVEL_FORM));
- dispatch<any>(initialize(EDIT_PERMISSION_LEVEL_FORM, {[EDIT_PERMISSION_LEVEL_UUID_FIELD_NAME]: link.uuid, [EDIT_PERMISSION_LEVEL_FIELD_NAME]: formatPermissionLevel(link.name as PermissionLevel)}));
- dispatch(dialogActions.OPEN_DIALOG({ id: EDIT_PERMISSION_LEVEL_DIALOG, data: resource }));
- }
- };
-
-export const editPermissionLevel = (data: EditPermissionLevelFormData) =>
+export const editPermissionLevel = (uuid: string, level: PermissionLevel) =>
async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => {
try {
- await permissionService.update(data[EDIT_PERMISSION_LEVEL_UUID_FIELD_NAME], {name: parsePermissionLevel(data[EDIT_PERMISSION_LEVEL_FIELD_NAME])});
- dispatch(dialogActions.CLOSE_DIALOG({ id: EDIT_PERMISSION_LEVEL_DIALOG }));
+ await permissionService.update(uuid, {name: level});
dispatch(GroupMembersPanelActions.REQUEST_ITEMS());
dispatch(GroupPermissionsPanelActions.REQUEST_ITEMS());
dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Permission level changed.', hideDuration: 2000 }));
diff --git a/src/views-components/context-menu/action-sets/permission-edit-action-set.ts b/src/views-components/context-menu/action-sets/permission-edit-action-set.ts
new file mode 100644
index 00000000..8663d3c7
--- /dev/null
+++ b/src/views-components/context-menu/action-sets/permission-edit-action-set.ts
@@ -0,0 +1,28 @@
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+import { ContextMenuActionSet } from "views-components/context-menu/context-menu-action-set";
+import { CanReadIcon, CanManageIcon, CanWriteIcon } from "components/icon/icon";
+import { editPermissionLevel } from 'store/group-details-panel/group-details-panel-actions';
+import { PermissionLevel } from "models/permission";
+
+export const permissionEditActionSet: ContextMenuActionSet = [[{
+ name: "Read",
+ icon: CanReadIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(editPermissionLevel(uuid, PermissionLevel.CAN_READ));
+ }
+}, {
+ name: "Write",
+ icon: CanWriteIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(editPermissionLevel(uuid, PermissionLevel.CAN_WRITE));
+ }
+}, {
+ name: "Manage",
+ icon: CanManageIcon,
+ execute: (dispatch, { uuid }) => {
+ dispatch<any>(editPermissionLevel(uuid, PermissionLevel.CAN_MANAGE));
+ }
+}]];
diff --git a/src/views-components/context-menu/context-menu.tsx b/src/views-components/context-menu/context-menu.tsx
index 603ee90b..f2c43ced 100644
--- a/src/views-components/context-menu/context-menu.tsx
+++ b/src/views-components/context-menu/context-menu.tsx
@@ -98,5 +98,6 @@ export enum ContextMenuKind {
USER = "User",
GROUPS = "Group",
GROUP_MEMBER = "GroupMember",
+ PERMISSION_EDIT = "PermissionEdit",
LINK = "Link",
}
diff --git a/src/views-components/data-explorer/renderers.tsx b/src/views-components/data-explorer/renderers.tsx
index 44326a85..39893392 100644
--- a/src/views-components/data-explorer/renderers.tsx
+++ b/src/views-components/data-explorer/renderers.tsx
@@ -29,10 +29,12 @@ import { CollectionResource } from 'models/collection';
import { IllegalNamingWarning } from 'components/warning/warning';
import { loadResource } from 'store/resources/resources-actions';
import { GroupClass, GroupResource } from 'models/group';
-import { openRemoveGroupMemberDialog, openEditPermissionLevelDialog } from 'store/group-details-panel/group-details-panel-actions';
+import { openRemoveGroupMemberDialog } from 'store/group-details-panel/group-details-panel-actions';
import { setMemberIsHidden } from 'store/group-details-panel/group-details-panel-actions';
import { formatPermissionLevel } from 'views-components/sharing-dialog/permission-select';
import { PermissionLevel } from 'models/permission';
+import { openPermissionEditContextMenu } from 'store/context-menu/context-menu-actions';
+import { getUserUuid } from 'common/getuser';
const renderName = (dispatch: Dispatch, item: GroupContentsResource) => {
@@ -357,14 +359,6 @@ const renderResourceLink = (dispatch: Dispatch, item: Resource) => {
</Typography>;
};
-const renderResource = (dispatch: Dispatch, item: Resource) => {
- var displayName = getResourceDisplayName(item);
-
- return <Typography variant='body2'>
- {resourceLabel(item.kind)}: {displayName || item.uuid}
- </Typography>;
-};
-
export const ResourceLinkTail = connect(
(state: RootState, props: { uuid: string }) => {
const resource = getResource<LinkResource>(props.uuid)(state.resources);
@@ -446,48 +440,52 @@ export const ResourceLinkTailUsername = connect(
return resource || { username: '' };
})(renderUsername);
-const renderPermissionLevel = (dispatch: Dispatch, link: LinkResource, resource: Resource) => {
+const renderPermissionLevel = (dispatch: Dispatch, link: LinkResource, canManage: boolean) => {
return <Typography noWrap>
{formatPermissionLevel(link.name as PermissionLevel)}
- <IconButton onClick={() => dispatch<any>(openEditPermissionLevelDialog(link.uuid, resource.uuid))}>
- <RenameIcon />
- </IconButton>
+ {canManage ?
+ <IconButton onClick={(event) => dispatch<any>(openPermissionEditContextMenu(event, link))}>
+ <RenameIcon />
+ </IconButton> :
+ ''
+ }
</Typography>;
}
export const ResourceLinkHeadPermissionLevel = connect(
(state: RootState, props: { uuid: string }) => {
const link = getResource<LinkResource>(props.uuid)(state.resources);
- const resource = getResource<Resource>(link?.headUuid || '')(state.resources);
return {
link: link || { uuid: '', name: '', kind: ResourceKind.NONE },
- resource: resource || { uuid: '', kind: ResourceKind.NONE }
+ canManage: link && getResourceLinkCanManage(state, link),
};
- })((props: { link: LinkResource, resource: Resource } & DispatchProp<any>) =>
- renderPermissionLevel(props.dispatch, props.link, props.resource));
+ })((props: { link: LinkResource, canManage: boolean } & DispatchProp<any>) =>
+ renderPermissionLevel(props.dispatch, props.link, props.canManage));
export const ResourceLinkTailPermissionLevel = connect(
(state: RootState, props: { uuid: string }) => {
const link = getResource<LinkResource>(props.uuid)(state.resources);
- const resource = getResource<Resource>(link?.tailUuid || '')(state.resources);
return {
link: link || { uuid: '', name: '', kind: ResourceKind.NONE },
- resource: resource || { uuid: '', kind: ResourceKind.NONE }
+ canManage: link && getResourceLinkCanManage(state, link),
};
- })((props: { link: LinkResource, resource: Resource } & DispatchProp<any>) =>
- renderPermissionLevel(props.dispatch, props.link, props.resource));
+ })((props: { link: LinkResource, canManage: boolean } & DispatchProp<any>) =>
+ renderPermissionLevel(props.dispatch, props.link, props.canManage));
-// Displays resource type and display name without link
-export const ResourceLabel = connect(
- (state: RootState, props: { uuid: string }) => {
- const resource = getResource<Resource>(props.uuid)(state.resources);
- return {
- item: resource || { uuid: '', kind: ResourceKind.NONE }
- };
- })((props: { item: Resource } & DispatchProp<any>) =>
- renderResource(props.dispatch, props.item));
+const getResourceLinkCanManage = (state: RootState, link: LinkResource) => {
+ const headResource = getResource<Resource>(link.headUuid)(state.resources);
+ // const tailResource = getResource<Resource>(link.tailUuid)(state.resources);
+ const userUuid = getUserUuid(state);
+
+ if (headResource && headResource.kind === ResourceKind.GROUP) {
+ return userUuid ? (headResource as GroupResource).writableBy?.includes(userUuid) : false;
+ } else {
+ // true for now
+ return true;
+ }
+}
// Process Resources
const resourceRunProcess = (dispatch: Dispatch, uuid: string) => {
diff --git a/src/views-components/dialog-forms/edit-permission-level-dialog.tsx b/src/views-components/dialog-forms/edit-permission-level-dialog.tsx
deleted file mode 100644
index 5479a0c6..00000000
--- a/src/views-components/dialog-forms/edit-permission-level-dialog.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) The Arvados Authors. All rights reserved.
-//
-// SPDX-License-Identifier: AGPL-3.0
-
-import React from 'react';
-import { compose } from "redux";
-import { reduxForm, InjectedFormProps, WrappedFieldProps, Field } from 'redux-form';
-import { withDialog, WithDialogProps } from "store/dialog/with-dialog";
-import { FormDialog } from 'components/form-dialog/form-dialog';
-import { EDIT_PERMISSION_LEVEL_DIALOG, EDIT_PERMISSION_LEVEL_FORM, EditPermissionLevelFormData, EDIT_PERMISSION_LEVEL_FIELD_NAME, editPermissionLevel } from 'store/group-details-panel/group-details-panel-actions';
-import { require } from 'validators/require';
-import { PermissionSelect } from 'views-components/sharing-dialog/permission-select';
-import { Grid } from '@material-ui/core';
-import { Resource } from 'models/resource';
-import { ResourceLabel } from 'views-components/data-explorer/renderers';
-
-export const EditPermissionLevelDialog = compose(
- withDialog(EDIT_PERMISSION_LEVEL_DIALOG),
- reduxForm<EditPermissionLevelFormData>({
- form: EDIT_PERMISSION_LEVEL_FORM,
- onSubmit: (data, dispatch) => {
- dispatch(editPermissionLevel(data));
- },
- })
-)(
- (props: EditPermissionLevelDialogProps) =>
- <FormDialog
- dialogTitle='Edit permission'
- formFields={PermissionField}
- submitLabel='Update'
- {...props}
- />
-);
-
-interface EditPermissionLevelDataProps {
- data: Resource;
-}
-
-type EditPermissionLevelDialogProps = EditPermissionLevelDataProps & WithDialogProps<{}> & InjectedFormProps<EditPermissionLevelFormData>;
-
-const PermissionField = (props: EditPermissionLevelDialogProps) =>
- <Grid container spacing={8}>
- <Grid item xs={8}>
- <ResourceLabel uuid={props.data.uuid} />
- </Grid>
- <Grid item xs={4} container wrap='nowrap'>
- <Field
- name={EDIT_PERMISSION_LEVEL_FIELD_NAME}
- component={PermissionSelectComponent as any}
- validate={require} />
- </Grid>
- </Grid>;
-
-const PermissionSelectComponent = ({ input }: WrappedFieldProps) =>
- <PermissionSelect fullWidth disableUnderline {...input} />;
diff --git a/src/views/group-details-panel/group-details-panel.tsx b/src/views/group-details-panel/group-details-panel.tsx
index 7c173b27..a44304c4 100644
--- a/src/views/group-details-panel/group-details-panel.tsx
+++ b/src/views/group-details-panel/group-details-panel.tsx
@@ -14,8 +14,6 @@ import { RootState } from 'store/store';
import { GROUP_DETAILS_MEMBERS_PANEL_ID, GROUP_DETAILS_PERMISSIONS_PANEL_ID, openAddGroupMembersDialog, getCurrentGroupDetailsPanelUuid } from 'store/group-details-panel/group-details-panel-actions';
import { openContextMenu } from 'store/context-menu/context-menu-actions';
import { ResourcesState, getResource } from 'store/resources/resources';
-import { ContextMenuKind } from 'views-components/context-menu/context-menu';
-import { PermissionResource } from 'models/permission';
import { Grid, Button, Tabs, Tab, Paper } from '@material-ui/core';
import { AddIcon } from 'components/icon/icon';
import { getUserUuid } from 'common/getuser';
@@ -215,19 +213,6 @@ export const GroupDetailsPanel = connect(
);
}
- handleContextMenu = (event: React.MouseEvent<HTMLElement>, resourceUuid: string) => {
- const resource = getResource<PermissionResource>(resourceUuid)(this.props.resources);
- if (resource) {
- this.props.onContextMenu(event, {
- name: '',
- uuid: resource.uuid,
- ownerUuid: resource.ownerUuid,
- kind: resource.kind,
- menuKind: ContextMenuKind.GROUP_MEMBER
- });
- }
- }
-
handleChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
this.setState({ value });
}
diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx
index 50194f9e..9ce93bf2 100644
--- a/src/views/workbench/workbench.tsx
+++ b/src/views/workbench/workbench.tsx
@@ -89,7 +89,6 @@ import { GroupDetailsPanel } from 'views/group-details-panel/group-details-panel
import { RemoveGroupMemberDialog } from 'views-components/groups-dialog/member-remove-dialog';
import { GroupMemberAttributesDialog } from 'views-components/groups-dialog/member-attributes-dialog';
import { AddGroupMembersDialog } from 'views-components/dialog-forms/add-group-member-dialog';
-import { EditPermissionLevelDialog } from 'views-components/dialog-forms/edit-permission-level-dialog';
import { PartialCopyToCollectionDialog } from 'views-components/dialog-forms/partial-copy-to-collection-dialog';
import { PublicFavoritePanel } from 'views/public-favorites-panel/public-favorites-panel';
import { LinkAccountPanel } from 'views/link-account-panel/link-account-panel';
@@ -214,7 +213,6 @@ export const WorkbenchPanel =
<DetailsPanel />
</Grid>
<AddGroupMembersDialog />
- <EditPermissionLevelDialog />
<AdvancedTabDialog />
<AttributesApiClientAuthorizationDialog />
<AttributesKeepServiceDialog />
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list