mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-18 21:19:44 +00:00
chore: add delete user button
This commit is contained in:
parent
ec2ec74e31
commit
e91050c803
@ -89,7 +89,7 @@ func (s *UserService) CreateUser(ctx context.Context, request *apiv2pb.CreateUse
|
|||||||
func (s *UserService) DeleteUser(ctx context.Context, request *apiv2pb.DeleteUserRequest) (*apiv2pb.DeleteUserResponse, error) {
|
func (s *UserService) DeleteUser(ctx context.Context, request *apiv2pb.DeleteUserRequest) (*apiv2pb.DeleteUserResponse, error) {
|
||||||
userID := ctx.Value(UserIDContextKey).(int32)
|
userID := ctx.Value(UserIDContextKey).(int32)
|
||||||
if userID == request.Id {
|
if userID == request.Id {
|
||||||
return nil, status.Errorf(codes.InvalidArgument, "cannot delete self")
|
return nil, status.Errorf(codes.InvalidArgument, "cannot delete yourself")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.Store.DeleteUser(ctx, &store.DeleteUser{
|
err := s.Store.DeleteUser(ctx, &store.DeleteUser{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Button } from "@mui/joy";
|
import { Button, IconButton } from "@mui/joy";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import copy from "copy-to-clipboard";
|
import copy from "copy-to-clipboard";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
@ -110,7 +110,7 @@ const AccessTokenSection = () => {
|
|||||||
{String(userAccessToken.expiresAt ?? "Never")}
|
{String(userAccessToken.expiresAt ?? "Never")}
|
||||||
</td>
|
</td>
|
||||||
<td className="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm">
|
<td className="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm">
|
||||||
<Button
|
<IconButton
|
||||||
color="danger"
|
color="danger"
|
||||||
variant="plain"
|
variant="plain"
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -119,7 +119,7 @@ const AccessTokenSection = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon.Trash className="w-4 h-auto" />
|
<Icon.Trash className="w-4 h-auto" />
|
||||||
</Button>
|
</IconButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { Button } from "@mui/joy";
|
import { Button, IconButton } from "@mui/joy";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
import useUserStore from "../../stores/v1/user";
|
import useUserStore from "../../stores/v1/user";
|
||||||
|
import { showCommonDialog } from "../Alert";
|
||||||
import CreateUserDialog from "../CreateUserDialog";
|
import CreateUserDialog from "../CreateUserDialog";
|
||||||
|
import Icon from "../Icon";
|
||||||
|
|
||||||
const MemberSection = () => {
|
const MemberSection = () => {
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
@ -18,6 +21,22 @@ const MemberSection = () => {
|
|||||||
setCurrentEditingUser(undefined);
|
setCurrentEditingUser(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteUser = async (user: User) => {
|
||||||
|
showCommonDialog({
|
||||||
|
title: "Delete User",
|
||||||
|
content: `Are you sure to delete user \`${user.nickname}\`? You cannot undo this action.`,
|
||||||
|
style: "danger",
|
||||||
|
onConfirm: async () => {
|
||||||
|
try {
|
||||||
|
await userStore.deleteUser(user.id);
|
||||||
|
toast.success(`User \`${user.nickname}\` deleted successfully`);
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error(`Failed to delete user \`${user.nickname}\`: ${error.response.data.message}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="w-full flex flex-col justify-start items-start space-y-4">
|
<div className="w-full flex flex-col justify-start items-start space-y-4">
|
||||||
@ -68,16 +87,20 @@ const MemberSection = () => {
|
|||||||
<td className="whitespace-nowrap py-4 pl-4 pr-3 text-sm text-gray-900">{user.nickname}</td>
|
<td className="whitespace-nowrap py-4 pl-4 pr-3 text-sm text-gray-900">{user.nickname}</td>
|
||||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{user.email}</td>
|
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{user.email}</td>
|
||||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{user.role}</td>
|
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{user.role}</td>
|
||||||
<td className="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium">
|
<td className="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm">
|
||||||
<button
|
<IconButton
|
||||||
className="text-indigo-600 hover:text-indigo-900"
|
size="sm"
|
||||||
|
variant="plain"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentEditingUser(user);
|
setCurrentEditingUser(user);
|
||||||
setShowCreateUserDialog(true);
|
setShowCreateUserDialog(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Edit
|
<Icon.PenBox className="w-4 h-auto" />
|
||||||
</button>
|
</IconButton>
|
||||||
|
<IconButton size="sm" color="danger" variant="plain" onClick={() => handleDeleteUser(user)}>
|
||||||
|
<Icon.Trash className="w-4 h-auto" />
|
||||||
|
</IconButton>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
@ -43,8 +43,8 @@ export function patchUser(userPatch: UserPatch) {
|
|||||||
return axios.patch<User>(`/api/v1/user/${userPatch.id}`, userPatch);
|
return axios.patch<User>(`/api/v1/user/${userPatch.id}`, userPatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteUser(userDelete: UserDelete) {
|
export function deleteUser(userId: UserId) {
|
||||||
return axios.delete(`/api/v1/user/${userDelete.id}`);
|
return axios.delete(`/api/v2/users/${userId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
||||||
|
@ -19,6 +19,7 @@ interface UserState {
|
|||||||
getCurrentUser: () => User;
|
getCurrentUser: () => User;
|
||||||
createUser: (userCreate: UserCreate) => Promise<User>;
|
createUser: (userCreate: UserCreate) => Promise<User>;
|
||||||
patchUser: (userPatch: UserPatch) => Promise<void>;
|
patchUser: (userPatch: UserPatch) => Promise<void>;
|
||||||
|
deleteUser: (id: UserId) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useUserStore = create<UserState>()((set, get) => ({
|
const useUserStore = create<UserState>()((set, get) => ({
|
||||||
@ -67,6 +68,12 @@ const useUserStore = create<UserState>()((set, get) => ({
|
|||||||
userMap[user.id] = user;
|
userMap[user.id] = user;
|
||||||
set(userMap);
|
set(userMap);
|
||||||
},
|
},
|
||||||
|
deleteUser: async (userId: UserId) => {
|
||||||
|
await api.deleteUser(userId);
|
||||||
|
const userMap = get().userMapById;
|
||||||
|
delete userMap[userId];
|
||||||
|
set(userMap);
|
||||||
|
},
|
||||||
getUserById: (id: UserId) => {
|
getUserById: (id: UserId) => {
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
return userMap[id] as User;
|
return userMap[id] as User;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user