mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-20 14:01:24 +00:00
chore(frontend): update user module
This commit is contained in:
parent
832eb7cbf1
commit
35785a1a28
@ -3,6 +3,7 @@ import { isUndefined } from "lodash-es";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Role, User } from "@/types/proto/api/v2/user_service";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
@ -14,11 +15,9 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
userCreate: UserCreate;
|
userCreate: Pick<User, "email" | "nickname" | "password" | "role">;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roles: Role[] = ["USER", "ADMIN"];
|
|
||||||
|
|
||||||
const CreateUserDialog: React.FC<Props> = (props: Props) => {
|
const CreateUserDialog: React.FC<Props> = (props: Props) => {
|
||||||
const { onClose, onConfirm, user } = props;
|
const { onClose, onConfirm, user } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -28,7 +27,7 @@ const CreateUserDialog: React.FC<Props> = (props: Props) => {
|
|||||||
email: "",
|
email: "",
|
||||||
nickname: "",
|
nickname: "",
|
||||||
password: "",
|
password: "",
|
||||||
role: "USER",
|
role: Role.USER,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const requestState = useLoading(false);
|
const requestState = useLoading(false);
|
||||||
@ -95,7 +94,7 @@ const CreateUserDialog: React.FC<Props> = (props: Props) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (user) {
|
if (user) {
|
||||||
const userPatch: UserPatch = {
|
const userPatch: Partial<User> = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
};
|
};
|
||||||
if (user.email !== state.userCreate.email) {
|
if (user.email !== state.userCreate.email) {
|
||||||
@ -179,9 +178,8 @@ const CreateUserDialog: React.FC<Props> = (props: Props) => {
|
|||||||
</span>
|
</span>
|
||||||
<div className="w-full flex flex-row justify-start items-center text-base">
|
<div className="w-full flex flex-row justify-start items-center text-base">
|
||||||
<RadioGroup orientation="horizontal" value={state.userCreate.role} onChange={handleRoleInputChange}>
|
<RadioGroup orientation="horizontal" value={state.userCreate.role} onChange={handleRoleInputChange}>
|
||||||
{roles.map((role) => (
|
<Radio value={Role.USER} label={"User"} />
|
||||||
<Radio key={role} value={role} label={role} />
|
<Radio value={Role.ADMIN} label={"Admin"} />
|
||||||
))}
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Link, useLocation } from "react-router-dom";
|
import { Link, useLocation } from "react-router-dom";
|
||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
import { PlanType } from "@/types/proto/api/v2/subscription_service";
|
import { PlanType } from "@/types/proto/api/v2/subscription_service";
|
||||||
|
import { Role } from "@/types/proto/api/v2/user_service";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
import AboutDialog from "./AboutDialog";
|
import AboutDialog from "./AboutDialog";
|
||||||
@ -17,11 +18,12 @@ const Header: React.FC = () => {
|
|||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
const [showAboutDialog, setShowAboutDialog] = useState<boolean>(false);
|
const [showAboutDialog, setShowAboutDialog] = useState<boolean>(false);
|
||||||
const profile = workspaceStore.profile;
|
const profile = workspaceStore.profile;
|
||||||
const isAdmin = currentUser.role === "ADMIN";
|
const isAdmin = currentUser.role === Role.ADMIN;
|
||||||
const shouldShowRouterSwitch = location.pathname === "/" || location.pathname === "/collections";
|
const shouldShowRouterSwitch = location.pathname === "/" || location.pathname === "/collections";
|
||||||
|
|
||||||
const handleSignOutButtonClick = async () => {
|
const handleSignOutButtonClick = async () => {
|
||||||
await api.signout();
|
await api.signout();
|
||||||
|
localStorage.removeItem("userId");
|
||||||
window.location.href = "/auth";
|
window.location.href = "/auth";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
|
import { Role } from "@/types/proto/api/v2/user_service";
|
||||||
import { shortcutService } from "../services";
|
import { shortcutService } from "../services";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
import { showCommonDialog } from "./Alert";
|
import { showCommonDialog } from "./Alert";
|
||||||
@ -20,7 +21,7 @@ const ShortcutActionsDropdown = (props: Props) => {
|
|||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
const [showEditDrawer, setShowEditDrawer] = useState<boolean>(false);
|
const [showEditDrawer, setShowEditDrawer] = useState<boolean>(false);
|
||||||
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
|
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
|
||||||
const havePermission = currentUser.role === "ADMIN" || shortcut.creatorId === currentUser.id;
|
const havePermission = currentUser.role === Role.ADMIN || shortcut.creatorId === currentUser.id;
|
||||||
|
|
||||||
const handleDeleteShortcutButtonClick = (shortcut: Shortcut) => {
|
const handleDeleteShortcutButtonClick = (shortcut: Shortcut) => {
|
||||||
showCommonDialog({
|
showCommonDialog({
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Button } from "@mui/joy";
|
import { Button } from "@mui/joy";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Role } from "@/types/proto/api/v2/user_service";
|
||||||
import useUserStore from "../../stores/v1/user";
|
import useUserStore from "../../stores/v1/user";
|
||||||
import ChangePasswordDialog from "../ChangePasswordDialog";
|
import ChangePasswordDialog from "../ChangePasswordDialog";
|
||||||
import EditUserinfoDialog from "../EditUserinfoDialog";
|
import EditUserinfoDialog from "../EditUserinfoDialog";
|
||||||
@ -10,7 +11,7 @@ const AccountSection: React.FC = () => {
|
|||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
const [showEditUserinfoDialog, setShowEditUserinfoDialog] = useState<boolean>(false);
|
const [showEditUserinfoDialog, setShowEditUserinfoDialog] = useState<boolean>(false);
|
||||||
const [showChangePasswordDialog, setShowChangePasswordDialog] = useState<boolean>(false);
|
const [showChangePasswordDialog, setShowChangePasswordDialog] = useState<boolean>(false);
|
||||||
const isAdmin = currentUser.role === "ADMIN";
|
const isAdmin = currentUser.role === Role.ADMIN;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -2,6 +2,7 @@ import { Button, IconButton } from "@mui/joy";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { User } from "@/types/proto/api/v2/user_service";
|
||||||
import useUserStore from "../../stores/v1/user";
|
import useUserStore from "../../stores/v1/user";
|
||||||
import { showCommonDialog } from "../Alert";
|
import { showCommonDialog } from "../Alert";
|
||||||
import CreateUserDialog from "../CreateUserDialog";
|
import CreateUserDialog from "../CreateUserDialog";
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { userServiceClient } from "@/grpcweb";
|
|
||||||
|
|
||||||
export function signin(email: string, password: string) {
|
export function signin(email: string, password: string) {
|
||||||
return axios.post<User>("/api/v1/auth/signin", {
|
return axios.post<User>("/api/v1/auth/signin", {
|
||||||
@ -20,30 +19,6 @@ export function signout() {
|
|||||||
return axios.post("/api/v1/auth/logout");
|
return axios.post("/api/v1/auth/logout");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMyselfUser() {
|
|
||||||
return axios.get<User>("/api/v1/user/me");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getUserList() {
|
|
||||||
return axios.get<User[]>("/api/v1/user");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getUserById(id: number) {
|
|
||||||
return axios.get<User>(`/api/v1/user/${id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createUser(userCreate: UserCreate) {
|
|
||||||
return axios.post<User>("/api/v1/user", userCreate);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function patchUser(userPatch: UserPatch) {
|
|
||||||
return axios.patch<User>(`/api/v1/user/${userPatch.id}`, userPatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteUser(userId: UserId) {
|
|
||||||
return userServiceClient.deleteUser({ id: userId });
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
||||||
const queryList = [];
|
const queryList = [];
|
||||||
if (shortcutFind?.tag) {
|
if (shortcutFind?.tag) {
|
||||||
|
@ -6,6 +6,7 @@ import toast from "react-hot-toast";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useLoaderData } from "react-router-dom";
|
import { useLoaderData } from "react-router-dom";
|
||||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
import useNavigateTo from "@/hooks/useNavigateTo";
|
||||||
|
import { Role } from "@/types/proto/api/v2/user_service";
|
||||||
import { showCommonDialog } from "../components/Alert";
|
import { showCommonDialog } from "../components/Alert";
|
||||||
import AnalyticsView from "../components/AnalyticsView";
|
import AnalyticsView from "../components/AnalyticsView";
|
||||||
import CreateShortcutDrawer from "../components/CreateShortcutDrawer";
|
import CreateShortcutDrawer from "../components/CreateShortcutDrawer";
|
||||||
@ -31,7 +32,7 @@ const ShortcutDetail = () => {
|
|||||||
showEditDrawer: false,
|
showEditDrawer: false,
|
||||||
});
|
});
|
||||||
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
|
const [showQRCodeDialog, setShowQRCodeDialog] = useState<boolean>(false);
|
||||||
const havePermission = currentUser.role === "ADMIN" || shortcut.creatorId === currentUser.id;
|
const havePermission = currentUser.role === Role.ADMIN || shortcut.creatorId === currentUser.id;
|
||||||
const shortcutLink = absolutifyLink(`/s/${shortcut.name}`);
|
const shortcutLink = absolutifyLink(`/s/${shortcut.name}`);
|
||||||
const favicon = getFaviconWithGoogleS2(shortcut.link);
|
const favicon = getFaviconWithGoogleS2(shortcut.link);
|
||||||
|
|
||||||
|
@ -3,16 +3,12 @@ import React, { FormEvent, useEffect, useState } from "react";
|
|||||||
import { toast } from "react-hot-toast";
|
import { toast } from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import useNavigateTo from "@/hooks/useNavigateTo";
|
|
||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
import useUserStore from "../stores/v1/user";
|
|
||||||
|
|
||||||
const SignIn: React.FC = () => {
|
const SignIn: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigateTo = useNavigateTo();
|
|
||||||
const userStore = useUserStore();
|
|
||||||
const workspaceStore = useWorkspaceStore();
|
const workspaceStore = useWorkspaceStore();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
@ -20,11 +16,7 @@ const SignIn: React.FC = () => {
|
|||||||
const allowConfirm = email.length > 0 && password.length > 0;
|
const allowConfirm = email.length > 0 && password.length > 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userStore.getCurrentUser()) {
|
localStorage.removeItem("userId");
|
||||||
return navigateTo("/", {
|
|
||||||
replace: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workspaceStore.profile.mode === "demo") {
|
if (workspaceStore.profile.mode === "demo") {
|
||||||
setEmail("steven@yourselfhosted.com");
|
setEmail("steven@yourselfhosted.com");
|
||||||
@ -50,12 +42,10 @@ const SignIn: React.FC = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
actionBtnLoadingState.setLoading();
|
actionBtnLoadingState.setLoading();
|
||||||
await api.signin(email, password);
|
const { data: user } = await api.signin(email, password);
|
||||||
const user = await userStore.fetchCurrentUser();
|
|
||||||
if (user) {
|
if (user) {
|
||||||
navigateTo("/", {
|
localStorage.setItem("userId", `${user.id}`);
|
||||||
replace: true,
|
window.location.href = "/";
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
toast.error("Signin failed");
|
toast.error("Signin failed");
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,10 @@ import useNavigateTo from "@/hooks/useNavigateTo";
|
|||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import useLoading from "../hooks/useLoading";
|
import useLoading from "../hooks/useLoading";
|
||||||
import useUserStore from "../stores/v1/user";
|
|
||||||
|
|
||||||
const SignUp: React.FC = () => {
|
const SignUp: React.FC = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigateTo = useNavigateTo();
|
const navigateTo = useNavigateTo();
|
||||||
const userStore = useUserStore();
|
|
||||||
const workspaceStore = useWorkspaceStore();
|
const workspaceStore = useWorkspaceStore();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [nickname, setNickname] = useState("");
|
const [nickname, setNickname] = useState("");
|
||||||
@ -21,11 +19,7 @@ const SignUp: React.FC = () => {
|
|||||||
const allowConfirm = email.length > 0 && nickname.length > 0 && password.length > 0;
|
const allowConfirm = email.length > 0 && nickname.length > 0 && password.length > 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userStore.getCurrentUser()) {
|
localStorage.removeItem("userId");
|
||||||
return navigateTo("/", {
|
|
||||||
replace: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!workspaceStore.profile.enableSignup) {
|
if (!workspaceStore.profile.enableSignup) {
|
||||||
return navigateTo("/auth", {
|
return navigateTo("/auth", {
|
||||||
@ -57,12 +51,10 @@ const SignUp: React.FC = () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
actionBtnLoadingState.setLoading();
|
actionBtnLoadingState.setLoading();
|
||||||
await api.signup(email, nickname, password);
|
const { data: user } = await api.signup(email, nickname, password);
|
||||||
const user = await userStore.fetchCurrentUser();
|
|
||||||
if (user) {
|
if (user) {
|
||||||
navigateTo("/", {
|
localStorage.setItem("userId", `${user.id}`);
|
||||||
replace: true,
|
window.location.href = "/";
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
toast.error("Signup failed");
|
toast.error("Signup failed");
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,14 @@ import { subscriptionServiceClient } from "@/grpcweb";
|
|||||||
import { stringifyPlanType } from "@/stores/v1/subscription";
|
import { stringifyPlanType } from "@/stores/v1/subscription";
|
||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
import { PlanType } from "@/types/proto/api/v2/subscription_service";
|
import { PlanType } from "@/types/proto/api/v2/subscription_service";
|
||||||
|
import { Role } from "@/types/proto/api/v2/user_service";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
|
|
||||||
const SubscriptionSetting: React.FC = () => {
|
const SubscriptionSetting: React.FC = () => {
|
||||||
const workspaceStore = useWorkspaceStore();
|
const workspaceStore = useWorkspaceStore();
|
||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
const [licenseKey, setLicenseKey] = useState<string>("");
|
const [licenseKey, setLicenseKey] = useState<string>("");
|
||||||
const isAdmin = currentUser.role === "ADMIN";
|
const isAdmin = currentUser.role === Role.ADMIN;
|
||||||
const profile = workspaceStore.profile;
|
const profile = workspaceStore.profile;
|
||||||
|
|
||||||
const handleUpdateLicenseKey = async () => {
|
const handleUpdateLicenseKey = async () => {
|
||||||
|
@ -4,6 +4,7 @@ import { Link } from "react-router-dom";
|
|||||||
import Icon from "@/components/Icon";
|
import Icon from "@/components/Icon";
|
||||||
import { stringifyPlanType } from "@/stores/v1/subscription";
|
import { stringifyPlanType } from "@/stores/v1/subscription";
|
||||||
import useWorkspaceStore from "@/stores/v1/workspace";
|
import useWorkspaceStore from "@/stores/v1/workspace";
|
||||||
|
import { Role } from "@/types/proto/api/v2/user_service";
|
||||||
import MemberSection from "../components/setting/MemberSection";
|
import MemberSection from "../components/setting/MemberSection";
|
||||||
import WorkspaceSection from "../components/setting/WorkspaceSection";
|
import WorkspaceSection from "../components/setting/WorkspaceSection";
|
||||||
import useUserStore from "../stores/v1/user";
|
import useUserStore from "../stores/v1/user";
|
||||||
@ -11,7 +12,7 @@ import useUserStore from "../stores/v1/user";
|
|||||||
const WorkspaceSetting: React.FC = () => {
|
const WorkspaceSetting: React.FC = () => {
|
||||||
const workspaceStore = useWorkspaceStore();
|
const workspaceStore = useWorkspaceStore();
|
||||||
const currentUser = useUserStore().getCurrentUser();
|
const currentUser = useUserStore().getCurrentUser();
|
||||||
const isAdmin = currentUser.role === "ADMIN";
|
const isAdmin = currentUser.role === Role.ADMIN;
|
||||||
const profile = workspaceStore.profile;
|
const profile = workspaceStore.profile;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,33 +1,25 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { userSettingServiceClient } from "@/grpcweb";
|
import { userServiceClient, userSettingServiceClient } from "@/grpcweb";
|
||||||
|
import { User } from "@/types/proto/api/v2/user_service";
|
||||||
import { UserSetting } from "@/types/proto/api/v2/user_setting_service";
|
import { UserSetting } from "@/types/proto/api/v2/user_setting_service";
|
||||||
import * as api from "../../helpers/api";
|
|
||||||
|
|
||||||
const convertResponseModelUser = (user: User): User => {
|
|
||||||
return {
|
|
||||||
...user,
|
|
||||||
createdTs: user.createdTs * 1000,
|
|
||||||
updatedTs: user.updatedTs * 1000,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
interface UserState {
|
interface UserState {
|
||||||
userMapById: Record<UserId, User>;
|
userMapById: Record<number, User>;
|
||||||
userSettingMapById: Record<UserId, UserSetting>;
|
userSettingMapById: Record<number, UserSetting>;
|
||||||
currentUserId?: UserId;
|
currentUserId?: number;
|
||||||
|
|
||||||
// User related actions.
|
// User related actions.
|
||||||
fetchUserList: () => Promise<User[]>;
|
fetchUserList: () => Promise<User[]>;
|
||||||
fetchCurrentUser: () => Promise<User>;
|
fetchCurrentUser: () => Promise<User>;
|
||||||
getOrFetchUserById: (id: UserId) => Promise<User>;
|
getOrFetchUserById: (id: number) => Promise<User>;
|
||||||
getUserById: (id: UserId) => User;
|
getUserById: (id: number) => User;
|
||||||
getCurrentUser: () => User;
|
getCurrentUser: () => User;
|
||||||
createUser: (userCreate: UserCreate) => Promise<User>;
|
createUser: (create: Partial<User>) => Promise<User>;
|
||||||
patchUser: (userPatch: UserPatch) => Promise<void>;
|
patchUser: (userPatch: Partial<User>) => Promise<void>;
|
||||||
deleteUser: (id: UserId) => Promise<void>;
|
deleteUser: (id: number) => Promise<void>;
|
||||||
|
|
||||||
// User setting related actions.
|
// User setting related actions.
|
||||||
fetchUserSetting: (userId: UserId) => Promise<UserSetting>;
|
fetchUserSetting: (userId: number) => Promise<UserSetting>;
|
||||||
updateUserSetting: (userSetting: UserSetting, updateMask: string[]) => Promise<UserSetting>;
|
updateUserSetting: (userSetting: UserSetting, updateMask: string[]) => Promise<UserSetting>;
|
||||||
getCurrentUserSetting: () => UserSetting;
|
getCurrentUserSetting: () => UserSetting;
|
||||||
}
|
}
|
||||||
@ -36,65 +28,88 @@ const useUserStore = create<UserState>()((set, get) => ({
|
|||||||
userMapById: {},
|
userMapById: {},
|
||||||
userSettingMapById: {},
|
userSettingMapById: {},
|
||||||
fetchUserList: async () => {
|
fetchUserList: async () => {
|
||||||
const { data: userList } = await api.getUserList();
|
const { users } = await userServiceClient.listUsers({});
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
userList.forEach((user) => {
|
users.forEach((user) => {
|
||||||
userMap[user.id] = convertResponseModelUser(user);
|
userMap[user.id] = user;
|
||||||
});
|
});
|
||||||
set(userMap);
|
set(userMap);
|
||||||
return userList;
|
return users;
|
||||||
},
|
},
|
||||||
fetchCurrentUser: async () => {
|
fetchCurrentUser: async () => {
|
||||||
const { data } = await api.getMyselfUser();
|
const userId = localStorage.getItem("userId");
|
||||||
const user = convertResponseModelUser(data);
|
if (!userId) {
|
||||||
|
throw new Error("User id not found in localStorage");
|
||||||
|
}
|
||||||
|
const { user } = await userServiceClient.getUser({
|
||||||
|
id: Number(userId),
|
||||||
|
});
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("User not found");
|
||||||
|
}
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
userMap[user.id] = user;
|
userMap[user.id] = user;
|
||||||
set({ userMapById: userMap, currentUserId: user.id });
|
set({ userMapById: userMap, currentUserId: user.id });
|
||||||
return user;
|
return user;
|
||||||
},
|
},
|
||||||
getOrFetchUserById: async (id: UserId) => {
|
getOrFetchUserById: async (id: number) => {
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
if (userMap[id]) {
|
if (userMap[id]) {
|
||||||
return userMap[id] as User;
|
return userMap[id] as User;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await api.getUserById(id);
|
const { user } = await userServiceClient.getUser({
|
||||||
const user = convertResponseModelUser(data);
|
id: Number(id),
|
||||||
|
});
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("User not found");
|
||||||
|
}
|
||||||
userMap[id] = user;
|
userMap[id] = user;
|
||||||
set(userMap);
|
set(userMap);
|
||||||
return user;
|
return user;
|
||||||
},
|
},
|
||||||
createUser: async (userCreate: UserCreate) => {
|
createUser: async (userCreate: Partial<User>) => {
|
||||||
const { data } = await api.createUser(userCreate);
|
const { user } = await userServiceClient.createUser({
|
||||||
const user = convertResponseModelUser(data);
|
user: userCreate,
|
||||||
|
});
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("User not found");
|
||||||
|
}
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
userMap[user.id] = user;
|
userMap[user.id] = user;
|
||||||
set(userMap);
|
set(userMap);
|
||||||
return user;
|
return user;
|
||||||
},
|
},
|
||||||
patchUser: async (userPatch: UserPatch) => {
|
patchUser: async (userPatch: Partial<User>) => {
|
||||||
const { data } = await api.patchUser(userPatch);
|
const { user } = await userServiceClient.updateUser({
|
||||||
const user = convertResponseModelUser(data);
|
user: userPatch,
|
||||||
|
updateMask: ["email", "nickname"],
|
||||||
|
});
|
||||||
|
if (!user) {
|
||||||
|
throw new Error("User not found");
|
||||||
|
}
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
userMap[user.id] = user;
|
userMap[user.id] = user;
|
||||||
set(userMap);
|
set(userMap);
|
||||||
},
|
},
|
||||||
deleteUser: async (userId: UserId) => {
|
deleteUser: async (userId: number) => {
|
||||||
await api.deleteUser(userId);
|
await userServiceClient.deleteUser({
|
||||||
|
id: userId,
|
||||||
|
});
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
delete userMap[userId];
|
delete userMap[userId];
|
||||||
set(userMap);
|
set(userMap);
|
||||||
},
|
},
|
||||||
getUserById: (id: UserId) => {
|
getUserById: (id: number) => {
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
return userMap[id] as User;
|
return userMap[id] as User;
|
||||||
},
|
},
|
||||||
getCurrentUser: () => {
|
getCurrentUser: () => {
|
||||||
const userMap = get().userMapById;
|
const userMap = get().userMapById;
|
||||||
const currentUserId = get().currentUserId;
|
const currentUserId = get().currentUserId;
|
||||||
return userMap[currentUserId as UserId];
|
return userMap[currentUserId as number];
|
||||||
},
|
},
|
||||||
fetchUserSetting: async (userId: UserId) => {
|
fetchUserSetting: async (userId: number) => {
|
||||||
const userSetting = (
|
const userSetting = (
|
||||||
await userSettingServiceClient.getUserSetting({
|
await userSettingServiceClient.getUserSetting({
|
||||||
id: userId,
|
id: userId,
|
||||||
@ -122,7 +137,7 @@ const useUserStore = create<UserState>()((set, get) => ({
|
|||||||
getCurrentUserSetting: () => {
|
getCurrentUserSetting: () => {
|
||||||
const userSettingMap = get().userSettingMapById;
|
const userSettingMap = get().userSettingMapById;
|
||||||
const currentUserId = get().currentUserId;
|
const currentUserId = get().currentUserId;
|
||||||
return userSettingMap[currentUserId as UserId];
|
return userSettingMap[currentUserId as number];
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { persist } from "zustand/middleware";
|
import { persist } from "zustand/middleware";
|
||||||
|
import { User } from "@/types/proto/api/v2/user_service";
|
||||||
|
|
||||||
export interface Filter {
|
export interface Filter {
|
||||||
tab?: string;
|
tab?: string;
|
||||||
|
2
frontend/web/src/types/modules/shortcut.d.ts
vendored
2
frontend/web/src/types/modules/shortcut.d.ts
vendored
@ -11,7 +11,7 @@ interface OpenGraphMetadata {
|
|||||||
interface Shortcut {
|
interface Shortcut {
|
||||||
id: ShortcutId;
|
id: ShortcutId;
|
||||||
|
|
||||||
creatorId: UserId;
|
creatorId: number;
|
||||||
creator: User;
|
creator: User;
|
||||||
createdTs: TimeStamp;
|
createdTs: TimeStamp;
|
||||||
updatedTs: TimeStamp;
|
updatedTs: TimeStamp;
|
||||||
|
34
frontend/web/src/types/modules/user.d.ts
vendored
34
frontend/web/src/types/modules/user.d.ts
vendored
@ -1,36 +1,6 @@
|
|||||||
type UserId = number;
|
|
||||||
|
|
||||||
type Role = "ADMIN" | "USER";
|
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
id: UserId;
|
id: number;
|
||||||
|
|
||||||
createdTs: TimeStamp;
|
|
||||||
updatedTs: TimeStamp;
|
|
||||||
rowStatus: RowStatus;
|
|
||||||
|
|
||||||
email: string;
|
email: string;
|
||||||
nickname: string;
|
nickname: string;
|
||||||
role: Role;
|
role: "ADMIN" | "USER";
|
||||||
}
|
|
||||||
|
|
||||||
interface UserCreate {
|
|
||||||
email: string;
|
|
||||||
nickname: string;
|
|
||||||
password: string;
|
|
||||||
role: Role;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UserPatch {
|
|
||||||
id: UserId;
|
|
||||||
|
|
||||||
rowStatus?: RowStatus;
|
|
||||||
email?: string;
|
|
||||||
nickname?: string;
|
|
||||||
password?: string;
|
|
||||||
role?: Role;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UserDelete {
|
|
||||||
id: UserId;
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user