feat: Add 'delete user' option for admins
This commit is contained in:
@@ -2,6 +2,7 @@ import { PlusIcon } from "outline-icons";
|
||||
import * as React from "react";
|
||||
import stores from "~/stores";
|
||||
import Invite from "~/scenes/Invite";
|
||||
import { UserDeleteDialog } from "~/components/UserDialogs";
|
||||
import { createAction } from "~/actions";
|
||||
import { UserSection } from "~/actions/sections";
|
||||
|
||||
@@ -21,4 +22,31 @@ export const inviteUser = createAction({
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteUserActionFactory = (userId: string) =>
|
||||
createAction({
|
||||
name: ({ t }) => `${t("Delete user")}…`,
|
||||
analyticsName: "Delete user",
|
||||
keywords: "leave",
|
||||
dangerous: true,
|
||||
section: UserSection,
|
||||
visible: ({ stores }) => stores.policies.abilities(userId).delete,
|
||||
perform: ({ t }) => {
|
||||
const user = stores.users.get(userId);
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
|
||||
stores.dialogs.openModal({
|
||||
title: t("Delete user"),
|
||||
isCentered: true,
|
||||
content: (
|
||||
<UserDeleteDialog
|
||||
user={user}
|
||||
onSubmit={stores.dialogs.closeAllModals}
|
||||
/>
|
||||
),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const rootUserActions = [inviteUser];
|
||||
|
||||
@@ -58,6 +58,31 @@ export function UserChangeToMemberDialog({ user, onSubmit }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
export function UserDeleteDialog({ user, onSubmit }: Props) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await user.delete();
|
||||
onSubmit();
|
||||
};
|
||||
|
||||
return (
|
||||
<ConfirmationDialog
|
||||
onSubmit={handleSubmit}
|
||||
submitText={t("I understand, delete")}
|
||||
savingText={`${t("Deleting")}…`}
|
||||
danger
|
||||
>
|
||||
{t(
|
||||
"Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable, consider suspending the user instead.",
|
||||
{
|
||||
userName: user.name,
|
||||
}
|
||||
)}
|
||||
</ConfirmationDialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserChangeToAdminDialog({ user, onSubmit }: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { users } = useStores();
|
||||
@@ -12,7 +12,10 @@ import {
|
||||
UserChangeToViewerDialog,
|
||||
UserSuspendDialog,
|
||||
UserChangeNameDialog,
|
||||
} from "~/components/UserRoleDialogs";
|
||||
} from "~/components/UserDialogs";
|
||||
import { actionToMenuItem } from "~/actions";
|
||||
import { deleteUserActionFactory } from "~/actions/definitions/users";
|
||||
import useActionContext from "~/hooks/useActionContext";
|
||||
import usePolicy from "~/hooks/usePolicy";
|
||||
import useStores from "~/hooks/useStores";
|
||||
import useToasts from "~/hooks/useToasts";
|
||||
@@ -29,6 +32,9 @@ function UserMenu({ user }: Props) {
|
||||
});
|
||||
const can = usePolicy(user.id);
|
||||
const { showToast } = useToasts();
|
||||
const context = useActionContext({
|
||||
isContextMenu: true,
|
||||
});
|
||||
|
||||
const handlePromote = React.useCallback(
|
||||
(ev: React.SyntheticEvent) => {
|
||||
@@ -99,7 +105,7 @@ function UserMenu({ user }: Props) {
|
||||
(ev: React.SyntheticEvent) => {
|
||||
ev.preventDefault();
|
||||
dialogs.openModal({
|
||||
title: t("Suspend account"),
|
||||
title: t("Suspend user"),
|
||||
isCentered: true,
|
||||
content: (
|
||||
<UserSuspendDialog user={user} onSubmit={dialogs.closeAllModals} />
|
||||
@@ -199,11 +205,14 @@ function UserMenu({ user }: Props) {
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Suspend account")}…`,
|
||||
dangerous: true,
|
||||
title: `${t("Suspend user")}…`,
|
||||
onClick: handleSuspend,
|
||||
visible: !user.isInvited && !user.isSuspended,
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
actionToMenuItem(deleteUserActionFactory(user.id), context),
|
||||
]}
|
||||
/>
|
||||
</ContextMenu>
|
||||
|
||||
Reference in New Issue
Block a user