From bc2859933b347a9652c24bc053d653cdfd89b853 Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Mon, 16 Sep 2024 19:47:25 +0000 Subject: [PATCH] feat: add warning dialog when removing member from organization --- .../CustomRolesPage/CustomRolesPage.tsx | 4 +- .../OrganizationMembersPage.tsx | 120 ++++++++++++------ .../OrganizationMembersPageView.tsx | 16 +-- 3 files changed, 88 insertions(+), 52 deletions(-) diff --git a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx index beff71098fbac..5a6b33f170f58 100644 --- a/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx +++ b/site/src/pages/ManagementSettingsPage/CustomRolesPage/CustomRolesPage.tsx @@ -90,7 +90,9 @@ export const CustomRolesPage: FC = () => { onCancel={() => setRoleToDelete(undefined)} onConfirm={async () => { try { - await deleteRoleMutation.mutateAsync(roleToDelete!.name); + if (roleToDelete) { + await deleteRoleMutation.mutateAsync(roleToDelete.name); + } setRoleToDelete(undefined); await organizationRolesQuery.refetch(); displaySuccess("Custom role deleted successfully!"); diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx index 9edd091ec6dac..e4b5b67b94637 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx @@ -1,7 +1,5 @@ -import { - groupsByUserId, - groupsByUserIdInOrganization, -} from "api/queries/groups"; +import { getErrorMessage } from "api/errors"; +import { groupsByUserIdInOrganization } from "api/queries/groups"; import { addOrganizationMember, organizationMembers, @@ -11,9 +9,12 @@ import { } from "api/queries/organizations"; import { organizationRoles } from "api/queries/roles"; import type { OrganizationMemberWithUserData, User } from "api/typesGenerated"; +import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; +import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; import { Loader } from "components/Loader/Loader"; +import { Stack } from "components/Stack/Stack"; import { useAuthenticated } from "contexts/auth/RequireAuth"; -import type { FC } from "react"; +import { type FC, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { useParams } from "react-router-dom"; import { useOrganizationSettings } from "./ManagementSettingsLayout"; @@ -52,44 +53,89 @@ const OrganizationMembersPage: FC = () => { const organization = organizations?.find((o) => o.name === organizationName); const permissionsQuery = useQuery(organizationPermissions(organization?.id)); + const [memberToDelete, setMemberToDelete] = + useState(); + const permissions = permissionsQuery.data; if (!permissions) { return ; } return ( - { - await addMemberMutation.mutateAsync(user.id); - void membersQuery.refetch(); - }} - removeMember={async (member: OrganizationMemberWithUserData) => { - await removeMemberMutation.mutateAsync(member.user_id); - void membersQuery.refetch(); - }} - updateMemberRoles={async ( - member: OrganizationMemberWithUserData, - newRoles: string[], - ) => { - await updateMemberRolesMutation.mutateAsync({ - userId: member.user_id, - roles: newRoles, - }); - }} - /> + <> + { + await addMemberMutation.mutateAsync(user.id); + void membersQuery.refetch(); + }} + removeMember={setMemberToDelete} + updateMemberRoles={async ( + member: OrganizationMemberWithUserData, + newRoles: string[], + ) => { + await updateMemberRolesMutation.mutateAsync({ + userId: member.user_id, + roles: newRoles, + }); + }} + /> + + setMemberToDelete(undefined)} + title="Remove member" + confirmText="Remove" + onConfirm={async () => { + try { + if (memberToDelete) { + await removeMemberMutation.mutateAsync(memberToDelete?.user_id); + } + setMemberToDelete(undefined); + await membersQuery.refetch(); + displaySuccess("User removed from organization successfully!"); + } catch (error) { + setMemberToDelete(undefined); + displayError( + getErrorMessage(error, "Failed to remove user from organization"), + ); + } + }} + description={ + +

+ Removing this member will also: +

    +
  • Remove them from all groups in this organization
  • +
  • Remove all user role assignments
  • +
  • + Irreversibly orphan all their workspaces associated with this + organization +
  • +
+

+ +

+ Are you sure you want to remove{" "} + {memberToDelete?.username}? +

+
+ } + /> + ); }; diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx index a714d480cc702..98aef769f64cb 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx @@ -44,7 +44,7 @@ interface OrganizationMembersPageViewProps { members: Array | undefined; groupsByUserId: GroupsByUserId | undefined; addMember: (user: User) => Promise; - removeMember: (member: OrganizationMemberWithUserData) => Promise; + removeMember: (member: OrganizationMemberWithUserData) => void; updateMemberRoles: ( member: OrganizationMemberWithUserData, newRoles: string[], @@ -135,19 +135,7 @@ export const OrganizationMembersPageView: FC< { - try { - await props.removeMember(member); - displaySuccess("Member removed successfully."); - } catch (error) { - displayError( - getErrorMessage( - error, - "Failed to remove member.", - ), - ); - } - }} + onClick={() => props.removeMember(member)} > Remove