From e91050c803063420a5e8ffcf9c93097291f521f1 Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 22 Aug 2023 23:02:14 +0800 Subject: [PATCH] chore: add delete user button --- api/v2/user_service.go | 2 +- .../components/setting/AccessTokenSection.tsx | 6 ++-- web/src/components/setting/MemberSection.tsx | 35 +++++++++++++++---- web/src/helpers/api.ts | 4 +-- web/src/stores/v1/user.ts | 7 ++++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/api/v2/user_service.go b/api/v2/user_service.go index 527ecf8..c413921 100644 --- a/api/v2/user_service.go +++ b/api/v2/user_service.go @@ -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) { userID := ctx.Value(UserIDContextKey).(int32) 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{ diff --git a/web/src/components/setting/AccessTokenSection.tsx b/web/src/components/setting/AccessTokenSection.tsx index 61578d4..b18422b 100644 --- a/web/src/components/setting/AccessTokenSection.tsx +++ b/web/src/components/setting/AccessTokenSection.tsx @@ -1,4 +1,4 @@ -import { Button } from "@mui/joy"; +import { Button, IconButton } from "@mui/joy"; import axios from "axios"; import copy from "copy-to-clipboard"; import { useEffect, useState } from "react"; @@ -110,7 +110,7 @@ const AccessTokenSection = () => { {String(userAccessToken.expiresAt ?? "Never")} - + ))} diff --git a/web/src/components/setting/MemberSection.tsx b/web/src/components/setting/MemberSection.tsx index 527f570..1032cda 100644 --- a/web/src/components/setting/MemberSection.tsx +++ b/web/src/components/setting/MemberSection.tsx @@ -1,7 +1,10 @@ -import { Button } from "@mui/joy"; +import { Button, IconButton } from "@mui/joy"; import { useEffect, useState } from "react"; +import toast from "react-hot-toast"; import useUserStore from "../../stores/v1/user"; +import { showCommonDialog } from "../Alert"; import CreateUserDialog from "../CreateUserDialog"; +import Icon from "../Icon"; const MemberSection = () => { const userStore = useUserStore(); @@ -18,6 +21,22 @@ const MemberSection = () => { 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 ( <>
@@ -68,16 +87,20 @@ const MemberSection = () => { {user.nickname} {user.email} {user.role} - - + + + handleDeleteUser(user)}> + + ))} diff --git a/web/src/helpers/api.ts b/web/src/helpers/api.ts index db5fae9..a25b4d7 100644 --- a/web/src/helpers/api.ts +++ b/web/src/helpers/api.ts @@ -43,8 +43,8 @@ export function patchUser(userPatch: UserPatch) { return axios.patch(`/api/v1/user/${userPatch.id}`, userPatch); } -export function deleteUser(userDelete: UserDelete) { - return axios.delete(`/api/v1/user/${userDelete.id}`); +export function deleteUser(userId: UserId) { + return axios.delete(`/api/v2/users/${userId}`); } export function getShortcutList(shortcutFind?: ShortcutFind) { diff --git a/web/src/stores/v1/user.ts b/web/src/stores/v1/user.ts index 7f17abd..2fbc2b6 100644 --- a/web/src/stores/v1/user.ts +++ b/web/src/stores/v1/user.ts @@ -19,6 +19,7 @@ interface UserState { getCurrentUser: () => User; createUser: (userCreate: UserCreate) => Promise; patchUser: (userPatch: UserPatch) => Promise; + deleteUser: (id: UserId) => Promise; } const useUserStore = create()((set, get) => ({ @@ -67,6 +68,12 @@ const useUserStore = create()((set, get) => ({ userMap[user.id] = user; set(userMap); }, + deleteUser: async (userId: UserId) => { + await api.deleteUser(userId); + const userMap = get().userMapById; + delete userMap[userId]; + set(userMap); + }, getUserById: (id: UserId) => { const userMap = get().userMapById; return userMap[id] as User;