diff --git a/web/src/components/ChangePasswordDialog.tsx b/web/src/components/ChangePasswordDialog.tsx index 6f42c75d..01641281 100644 --- a/web/src/components/ChangePasswordDialog.tsx +++ b/web/src/components/ChangePasswordDialog.tsx @@ -55,7 +55,9 @@ const ChangePasswordDialog: React.FC = ({ destroy }: Props) => { } try { + const user = userService.getState().user as User; await userService.patchUser({ + id: user.id, password: newPassword, }); toastHelper.info("Password changed."); diff --git a/web/src/components/ConfirmResetOpenIdDialog.tsx b/web/src/components/ConfirmResetOpenIdDialog.tsx index 617ecf08..f095ac79 100644 --- a/web/src/components/ConfirmResetOpenIdDialog.tsx +++ b/web/src/components/ConfirmResetOpenIdDialog.tsx @@ -25,7 +25,9 @@ const ConfirmResetOpenIdDialog: React.FC = ({ destroy }: Props) => { resetBtnClickLoadingState.setLoading(); try { + const user = userService.getState().user as User; await userService.patchUser({ + id: user.id, resetOpenId: true, }); } catch (error) { diff --git a/web/src/components/Settings/MemberSection.tsx b/web/src/components/Settings/MemberSection.tsx index a92b8931..995e7d8d 100644 --- a/web/src/components/Settings/MemberSection.tsx +++ b/web/src/components/Settings/MemberSection.tsx @@ -1,5 +1,7 @@ import React, { useEffect, useState } from "react"; import { isEmpty } from "lodash-es"; +import { userService } from "../../services"; +import { useAppSelector } from "../../store"; import * as api from "../../helpers/api"; import toastHelper from "../Toast"; import "../../less/settings/member-section.less"; @@ -12,6 +14,7 @@ interface State { } const PreferencesSection: React.FC = () => { + const currentUser = useAppSelector((state) => state.user.user); const [state, setState] = useState({ createUserEmail: "", createUserPassword: "", @@ -66,6 +69,30 @@ const PreferencesSection: React.FC = () => { }); }; + const handleArchiveUserClick = async (user: User) => { + await userService.patchUser({ + id: user.id, + rowStatus: "ARCHIVED", + }); + fetchUserList(); + }; + + const handleRestoreUserClick = async (user: User) => { + await userService.patchUser({ + id: user.id, + rowStatus: "NORMAL", + }); + fetchUserList(); + }; + + // TODO: show a dialog to confirm delete user. + const handleDeleteUserClick = async (user: User) => { + await userService.deleteUser({ + id: user.id, + }); + fetchUserList(); + }; + return (

Create a member

@@ -86,15 +113,31 @@ const PreferencesSection: React.FC = () => {
ID EMAIL +
{userList.map((user) => ( -
+
{user.id} {user.email} - {/* TODO */} - {/*
- delete -
*/} +
+ {currentUser?.id === user.id ? ( + Yourself + ) : user.rowStatus === "NORMAL" ? ( + handleArchiveUserClick(user)}> + archive + + ) : ( + <> + handleRestoreUserClick(user)}> + restore + + / + handleDeleteUserClick(user)}> + delete + + + )} +
))}
diff --git a/web/src/components/Settings/MyAccountSection.tsx b/web/src/components/Settings/MyAccountSection.tsx index efed1aeb..f0203446 100644 --- a/web/src/components/Settings/MyAccountSection.tsx +++ b/web/src/components/Settings/MyAccountSection.tsx @@ -39,6 +39,7 @@ const MyAccountSection: React.FC = () => { try { await userService.patchUser({ + id: user.id, name: username, }); toastHelper.info("Username changed"); diff --git a/web/src/helpers/api.ts b/web/src/helpers/api.ts index 26ac0a7e..51f9d134 100644 --- a/web/src/helpers/api.ts +++ b/web/src/helpers/api.ts @@ -34,7 +34,7 @@ export function createUser(userCreate: UserCreate) { return axios.post>("/api/user", userCreate); } -export function getUser() { +export function getMyselfUser() { return axios.get>("/api/user/me"); } @@ -47,7 +47,11 @@ export function getUserById(id: number) { } export function patchUser(userPatch: UserPatch) { - return axios.patch>("/api/user/me", userPatch); + return axios.patch>(`/api/user/${userPatch.id}`, userPatch); +} + +export function deleteUser(userDelete: UserDelete) { + return axios.delete(`/api/user/${userDelete.id}`); } export function getMemoList(memoFind?: MemoFind) { diff --git a/web/src/less/dialog.less b/web/src/less/dialog.less index 5b363d2d..75bed808 100644 --- a/web/src/less/dialog.less +++ b/web/src/less/dialog.less @@ -2,7 +2,7 @@ .dialog-wrapper { .flex(column, flex-start, center); - @apply fixed top-0 left-0 w-full h-full pt-16 z-1000 overflow-x-hidden overflow-y-scroll bg-transparent transition-all; + @apply fixed top-0 left-0 w-full h-full pt-16 z-100 overflow-x-hidden overflow-y-scroll bg-transparent transition-all; .hide-scroll-bar(); &.showup { diff --git a/web/src/less/settings/member-section.less b/web/src/less/settings/member-section.less index 0741f134..68c2c7dd 100644 --- a/web/src/less/settings/member-section.less +++ b/web/src/less/settings/member-section.less @@ -32,7 +32,7 @@ } > .member-container { - @apply w-full grid grid-cols-5 border-b py-2; + @apply w-full grid grid-cols-6 border-b py-2; > .field-text { @apply text-base pl-2 mr-4 w-16; @@ -47,7 +47,31 @@ } > .buttons-container { - @apply col-span-1; + @apply col-span-2; + + > .btn { + @apply px-2 py-1 border rounded shadow hover:opacity-80; + + &.archive { + @apply bg-yellow-100 text-yellow-600; + } + + &.restore { + @apply bg-green-100 text-green-600; + } + + &.delete { + @apply bg-red-100 text-red-600; + } + } + + > .tip-text { + @apply text-gray-400; + } + + > .split-line { + @apply font-mono text-gray-300 mx-1; + } } } } diff --git a/web/src/services/userService.ts b/web/src/services/userService.ts index fea35093..9a745d24 100644 --- a/web/src/services/userService.ts +++ b/web/src/services/userService.ts @@ -33,7 +33,7 @@ const userService = { } } - const { data: user } = (await api.getUser()).data; + const { data: user } = (await api.getMyselfUser()).data; if (user) { store.dispatch(setUser(convertResponseModelUser(user))); } @@ -53,7 +53,7 @@ const userService = { }, doSignIn: async () => { - const { data: user } = (await api.getUser()).data; + const { data: user } = (await api.getMyselfUser()).data; if (user) { store.dispatch(setUser(convertResponseModelUser(user))); } else { @@ -78,8 +78,14 @@ const userService = { patchUser: async (userPatch: UserPatch): Promise => { const { data } = (await api.patchUser(userPatch)).data; - const user = convertResponseModelUser(data); - store.dispatch(patchUser(user)); + if (userPatch.id === store.getState().user.user?.id) { + const user = convertResponseModelUser(data); + store.dispatch(patchUser(user)); + } + }, + + deleteUser: async (userDelete: UserDelete) => { + await api.deleteUser(userDelete); }, }; diff --git a/web/src/types/modules/user.d.ts b/web/src/types/modules/user.d.ts index 7403dabc..ef55bc4c 100644 --- a/web/src/types/modules/user.d.ts +++ b/web/src/types/modules/user.d.ts @@ -22,7 +22,15 @@ interface UserCreate { } interface UserPatch { + id: UserId; + + rowStatus?: RowStatus; + name?: string; password?: string; resetOpenId?: boolean; } + +interface UserDelete { + id: UserId; +}