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