From: Stephen Smith Date: Mon, 13 Dec 2021 00:19:18 +0000 (-0500) Subject: 18123: Use sharing dialog to add users to groups X-Git-Tag: 2.4.0~22^2~6 X-Git-Url: https://git.arvados.org/arvados-workbench2.git/commitdiff_plain/e63239560b1393a8b306a4353719d4fe85698f04 18123: Use sharing dialog to add users to groups Arvados-DCO-1.1-Signed-off-by: Stephen Smith --- diff --git a/cypress/integration/group-manage.spec.js b/cypress/integration/group-manage.spec.js index d17cefe9..e638c648 100644 --- a/cypress/integration/group-manage.spec.js +++ b/cypress/integration/group-manage.spec.js @@ -58,13 +58,13 @@ describe('Group manage tests', function() { it('adds users to the group', function() { // Add other user to the group cy.get('[data-cy=group-member-add]').click(); - cy.get('[data-cy=form-dialog]') - .should('contain', 'Add users') + cy.get('.sharing-dialog') + .should('contain', 'Sharing settings') .within(() => { - cy.get('input').type("other"); + cy.get('[data-cy=invite-people-field] input').type("other"); }); - cy.contains('Other User').click(); - cy.get('[data-cy=form-dialog] button[type=submit]').click(); + cy.get('[role=tooltip]').click(); + cy.get('.sharing-dialog').contains('Save').click(); // Check that both users are present with appropriate permissions cy.get('[data-cy=group-members-data-explorer]') 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 916d68a7..8130869f 100644 --- a/src/store/group-details-panel/group-details-panel-actions.ts +++ b/src/store/group-details-panel/group-details-panel-actions.ts @@ -6,24 +6,19 @@ import { bindDataExplorerActions } from 'store/data-explorer/data-explorer-actio import { Dispatch } from 'redux'; 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 { reset, startSubmit } from 'redux-form'; -import { addGroupMember, deleteGroupMember } from 'store/groups-panel/groups-panel-actions'; +import { deleteGroupMember } from 'store/groups-panel/groups-panel-actions'; import { getResource } from 'store/resources/resources'; -import { GroupResource } from 'models/group'; 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 { LinkResource } from 'models/link'; import { deleteResources } from 'store/resources/resources-actions'; +import { openSharingDialog } from 'store/sharing-dialog/sharing-dialog-actions'; export const GROUP_DETAILS_MEMBERS_PANEL_ID = 'groupDetailsMembersPanel'; export const GROUP_DETAILS_PERMISSIONS_PANEL_ID = 'groupDetailsPermissionsPanel'; -export const ADD_GROUP_MEMBERS_DIALOG = 'addGroupMembers'; -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'; @@ -40,45 +35,13 @@ export const loadGroupDetailsPanel = (groupUuid: string) => export const getCurrentGroupDetailsPanelUuid = getProperty(GROUP_DETAILS_MEMBERS_PANEL_ID); -export interface AddGroupMembersFormData { - [ADD_GROUP_MEMBERS_USERS_FIELD_NAME]: Participant[]; -} - export const openAddGroupMembersDialog = () => - (dispatch: Dispatch) => { - dispatch(dialogActions.OPEN_DIALOG({ id: ADD_GROUP_MEMBERS_DIALOG, data: {} })); - dispatch(reset(ADD_GROUP_MEMBERS_FORM)); - }; - -export const addGroupMembers = ({ users }: AddGroupMembersFormData) => - - async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => { - + (dispatch: Dispatch, getState: () => RootState) => { const groupUuid = getCurrentGroupDetailsPanelUuid(getState().properties); - if (groupUuid) { - - dispatch(startSubmit(ADD_GROUP_MEMBERS_FORM)); - - const group = getResource(groupUuid)(getState().resources); - - for (const user of users) { - - await addGroupMember({ - user, - group: { - uuid: groupUuid, - name: group ? group.name : groupUuid, - }, - dispatch, - permissionService, - }); - - } - - dispatch(dialogActions.CLOSE_DIALOG({ id: ADD_GROUP_MEMBERS_FORM })); - dispatch(GroupMembersPanelActions.REQUEST_ITEMS()); - + dispatch(openSharingDialog(groupUuid, () => { + dispatch(GroupMembersPanelActions.REQUEST_ITEMS()); + })); } }; diff --git a/src/store/sharing-dialog/sharing-dialog-actions.ts b/src/store/sharing-dialog/sharing-dialog-actions.ts index 54ad6791..4c0b8825 100644 --- a/src/store/sharing-dialog/sharing-dialog-actions.ts +++ b/src/store/sharing-dialog/sharing-dialog-actions.ts @@ -21,9 +21,9 @@ import { progressIndicatorActions } from 'store/progress-indicator/progress-indi import { snackbarActions, SnackbarKind } from "../snackbar/snackbar-actions"; import { extractUuidKind, ResourceKind } from "models/resource"; -export const openSharingDialog = (resourceUuid: string) => +export const openSharingDialog = (resourceUuid: string, refresh?: () => void) => (dispatch: Dispatch) => { - dispatch(dialogActions.OPEN_DIALOG({ id: SHARING_DIALOG_NAME, data: resourceUuid })); + dispatch(dialogActions.OPEN_DIALOG({ id: SHARING_DIALOG_NAME, data: {resourceUuid, refresh} })); dispatch(loadSharingDialog); }; @@ -34,16 +34,21 @@ export const connectSharingDialog = withDialog(SHARING_DIALOG_NAME); export const connectSharingDialogProgress = withProgress(SHARING_DIALOG_NAME); -export const saveSharingDialogChanges = async (dispatch: Dispatch) => { +export const saveSharingDialogChanges = async (dispatch: Dispatch, getState: () => RootState) => { dispatch(progressIndicatorActions.START_WORKING(SHARING_DIALOG_NAME)); await dispatch(savePublicPermissionChanges); await dispatch(saveManagementChanges); await dispatch(sendInvitations); dispatch(reset(SHARING_INVITATION_FORM_NAME)); await dispatch(loadSharingDialog); + + const dialog = getDialog(getState().dialog, SHARING_DIALOG_NAME); + if (dialog && dialog.data.refresh) { + dialog.data.refresh(); + } }; -export const sendSharingInvitations = async (dispatch: Dispatch) => { +export const sendSharingInvitations = async (dispatch: Dispatch, getState: () => RootState) => { dispatch(progressIndicatorActions.START_WORKING(SHARING_DIALOG_NAME)); await dispatch(sendInvitations); dispatch(closeSharingDialog()); @@ -52,15 +57,25 @@ export const sendSharingInvitations = async (dispatch: Dispatch) => { kind: SnackbarKind.SUCCESS, })); dispatch(progressIndicatorActions.STOP_WORKING(SHARING_DIALOG_NAME)); + + const dialog = getDialog(getState().dialog, SHARING_DIALOG_NAME); + if (dialog && dialog.data.refresh) { + dialog.data.refresh(); + } }; +interface SharingDialogData { + resourceUuid: string; + refresh: () => void; +} + const loadSharingDialog = async (dispatch: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => { - const dialog = getDialog(getState().dialog, SHARING_DIALOG_NAME); + const dialog = getDialog(getState().dialog, SHARING_DIALOG_NAME); if (dialog) { dispatch(progressIndicatorActions.START_WORKING(SHARING_DIALOG_NAME)); try { - const { items } = await permissionService.listResourcePermissions(dialog.data); + const { items } = await permissionService.listResourcePermissions(dialog.data.resourceUuid); dispatch(initializePublicAccessForm(items)); await dispatch(initializeManagementForm(items)); dispatch(progressIndicatorActions.STOP_WORKING(SHARING_DIALOG_NAME)); @@ -133,7 +148,7 @@ const initializePublicAccessForm = (permissionLinks: PermissionResource[]) => const savePublicPermissionChanges = async (_: Dispatch, getState: () => RootState, { permissionService }: ServiceRepository) => { const state = getState(); const { user } = state.auth; - const dialog = getDialog(state.dialog, SHARING_DIALOG_NAME); + const dialog = getDialog(state.dialog, SHARING_DIALOG_NAME); if (dialog && user) { const { permissionUuid, visibility } = getSharingPublicAccessFormData(state); @@ -150,7 +165,7 @@ const savePublicPermissionChanges = async (_: Dispatch, getState: () => RootStat await permissionService.create({ ownerUuid: user.uuid, - headUuid: dialog.data, + headUuid: dialog.data.resourceUuid, tailUuid: getPublicGroupUuid(state), name: PermissionLevel.CAN_READ, }); @@ -197,7 +212,7 @@ const saveManagementChanges = async (_: Dispatch, getState: () => RootState, { p const sendInvitations = async (_: Dispatch, getState: () => RootState, { permissionService, userService }: ServiceRepository) => { const state = getState(); const { user } = state.auth; - const dialog = getDialog(state.dialog, SHARING_DIALOG_NAME); + const dialog = getDialog(state.dialog, SHARING_DIALOG_NAME); if (dialog && user) { const invitations = getFormValues(SHARING_INVITATION_FORM_NAME)(state) as SharingInvitationFormData; @@ -207,7 +222,7 @@ const sendInvitations = async (_: Dispatch, getState: () => RootState, { permiss const invitationDataUsers = getUsersFromForm .map(person => ({ ownerUuid: user.uuid, - headUuid: dialog.data, + headUuid: dialog.data.resourceUuid, tailUuid: person.uuid, name: invitations.permissions })); @@ -215,7 +230,7 @@ const sendInvitations = async (_: Dispatch, getState: () => RootState, { permiss const invitationsDataGroups = getGroupsFromForm.map( group => ({ ownerUuid: user.uuid, - headUuid: dialog.data, + headUuid: dialog.data.resourceUuid, tailUuid: group.uuid, name: invitations.permissions }) diff --git a/src/views-components/dialog-forms/add-group-member-dialog.tsx b/src/views-components/dialog-forms/add-group-member-dialog.tsx deleted file mode 100644 index 443191fe..00000000 --- a/src/views-components/dialog-forms/add-group-member-dialog.tsx +++ /dev/null @@ -1,49 +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, WrappedFieldArrayProps, FieldArray } from 'redux-form'; -import { withDialog, WithDialogProps } from "store/dialog/with-dialog"; -import { FormDialog } from 'components/form-dialog/form-dialog'; -import { ParticipantSelect, Participant } from 'views-components/sharing-dialog/participant-select'; -import { ADD_GROUP_MEMBERS_DIALOG, ADD_GROUP_MEMBERS_FORM, AddGroupMembersFormData, ADD_GROUP_MEMBERS_USERS_FIELD_NAME, addGroupMembers } from 'store/group-details-panel/group-details-panel-actions'; -import { minLength } from 'validators/min-length'; - -export const AddGroupMembersDialog = compose( - withDialog(ADD_GROUP_MEMBERS_DIALOG), - reduxForm({ - form: ADD_GROUP_MEMBERS_FORM, - onSubmit: (data, dispatch) => { - dispatch(addGroupMembers(data)); - }, - }) -)( - (props: AddGroupMembersDialogProps) => - -); - -type AddGroupMembersDialogProps = WithDialogProps<{}> & InjectedFormProps; - -const UsersField = () => - ; - -const UsersFieldValidation = [minLength(1, () => 'Select at least one user')]; - -const UsersSelect = ({ fields }: WrappedFieldArrayProps) => - ; diff --git a/src/views/workbench/workbench.tsx b/src/views/workbench/workbench.tsx index 9ce93bf2..c756a7d6 100644 --- a/src/views/workbench/workbench.tsx +++ b/src/views/workbench/workbench.tsx @@ -88,7 +88,6 @@ import { GroupAttributesDialog } from 'views-components/groups-dialog/attributes 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 { 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'; @@ -212,7 +211,6 @@ export const WorkbenchPanel = -