feat: update pages

This commit is contained in:
Steven 2023-06-22 22:30:07 +08:00
parent 89740fa160
commit 407a8cc7fb
8 changed files with 55 additions and 103 deletions

View File

@ -28,7 +28,7 @@ const Header: React.FC = () => {
<Dropdown <Dropdown
trigger={ trigger={
<button className="flex flex-row justify-end items-center cursor-pointer"> <button className="flex flex-row justify-end items-center cursor-pointer">
<span>{user?.displayName}</span> <span>{user.nickname}</span>
<Icon.ChevronDown className="ml-1 w-5 h-auto text-gray-600" /> <Icon.ChevronDown className="ml-1 w-5 h-auto text-gray-600" />
</button> </button>
} }

View File

@ -64,7 +64,7 @@ const ShortcutListView: React.FC<Props> = (props: Props) => {
<span className="text-gray-400 text-sm ml-2">({shortcut.description})</span> <span className="text-gray-400 text-sm ml-2">({shortcut.description})</span>
</div> </div>
<div className="flex flex-row justify-end items-center"> <div className="flex flex-row justify-end items-center">
<span className="w-16 truncate mr-2 text-gray-600">{shortcut.creator.displayName}</span> <span className="w-16 truncate mr-2 text-gray-600">{shortcut.creator.nickname}</span>
<Tooltip title="Copy link" variant="solid" placement="top"> <Tooltip title="Copy link" variant="solid" placement="top">
<button <button
className="cursor-pointer mr-4 hover:opacity-80" className="cursor-pointer mr-4 hover:opacity-80"

View File

@ -1,7 +1,7 @@
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
import Header from "../components/Header"; import Header from "../components/Header";
const UserDetail: React.FC = () => { const Root: React.FC = () => {
return ( return (
<div className="w-full h-full flex flex-col justify-start items-start"> <div className="w-full h-full flex flex-col justify-start items-start">
<Header /> <Header />
@ -10,4 +10,4 @@ const UserDetail: React.FC = () => {
); );
}; };
export default UserDetail; export default Root;

View File

@ -1,15 +1,24 @@
import { useEffect } from "react"; import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { userService, shortcutService } from "../services"; import { userService, shortcutService } from "../services";
import { useAppSelector } from "../store"; import { useAppSelector } from "../store";
import useLoading from "../hooks/useLoading"; import useLoading from "../hooks/useLoading";
import Icon from "../components/Icon"; import Icon from "../components/Icon";
import Dropdown from "../components/common/Dropdown";
import ShortcutListView from "../components/ShortcutListView"; import ShortcutListView from "../components/ShortcutListView";
import CreateShortcutDialog from "../components/CreateShortcutDialog";
interface State {
showCreateShortcutDialog: boolean;
}
const Home: React.FC = () => { const Home: React.FC = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const loadingState = useLoading(); const loadingState = useLoading();
const { shortcutList } = useAppSelector((state) => state.shortcut); const { shortcutList } = useAppSelector((state) => state.shortcut);
const [state, setState] = useState<State>({
showCreateShortcutDialog: false,
});
useEffect(() => { useEffect(() => {
if (!userService.getState().user) { if (!userService.getState().user) {
@ -22,11 +31,38 @@ const Home: React.FC = () => {
}); });
}, []); }, []);
const setShowCreateShortcutDialog = (show: boolean) => {
setState({
...state,
showCreateShortcutDialog: show,
});
};
return ( return (
<> <>
<div className="mx-auto max-w-4xl w-full px-3 py-6 flex flex-col justify-start items-start"> <div className="mx-auto max-w-4xl w-full px-3 py-6 flex flex-col justify-start items-start">
<div className="mb-4 w-full flex flex-row justify-between items-center"> <div className="w-full flex flex-row justify-between items-center mb-4">
<span className="font-mono text-gray-400">Workspace List</span> <span className="font-mono text-gray-400">Shortcuts</span>
<div>
<Dropdown
trigger={
<button className="w-32 flex flex-row justify-start items-center border px-3 leading-10 rounded-lg cursor-pointer hover:shadow">
<Icon.Plus className="w-4 h-auto mr-1" /> Add new...
</button>
}
actions={
<>
<button
className="w-full flex flex-row justify-start items-center px-3 leading-10 rounded cursor-pointer hover:bg-gray-100"
onClick={() => setShowCreateShortcutDialog(true)}
>
Shortcut
</button>
</>
}
actionsClassName="!w-32"
/>
</div>
</div> </div>
{loadingState.isLoading ? ( {loadingState.isLoading ? (
<div className="py-4 w-full flex flex-row justify-center items-center"> <div className="py-4 w-full flex flex-row justify-center items-center">
@ -37,6 +73,10 @@ const Home: React.FC = () => {
<ShortcutListView shortcutList={shortcutList} /> <ShortcutListView shortcutList={shortcutList} />
)} )}
</div> </div>
{state.showCreateShortcutDialog && (
<CreateShortcutDialog onClose={() => setShowCreateShortcutDialog(false)} onConfirm={() => setShowCreateShortcutDialog(false)} />
)}
</> </>
); );
}; };

View File

@ -1,44 +0,0 @@
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { getShortcutWithNameAndWorkspaceName } from "../helpers/api";
import useLoading from "../hooks/useLoading";
interface State {
errMessage?: string;
}
const ShortcutRedirector: React.FC = () => {
const params = useParams();
const [state, setState] = useState<State>();
const loadingState = useLoading();
useEffect(() => {
const workspaceName = params.workspaceName || "";
const shortcutName = params.shortcutName || "";
getShortcutWithNameAndWorkspaceName(workspaceName, shortcutName)
.then(({ data: shortcut }) => {
if (shortcut) {
window.location.href = shortcut.link;
} else {
setState({
errMessage: "Not found",
});
loadingState.setFinish();
}
})
.catch((error) => {
setState({
errMessage: error.response.data.error || "Error occurred",
});
loadingState.setFinish();
});
}, []);
return loadingState.isLoading ? null : (
<div className="w-full pt-24 text-center font-mono text-xl">
<p>{state?.errMessage}</p>
</div>
);
};
export default ShortcutRedirector;

View File

@ -1,12 +1,8 @@
import { Button, Input, Tooltip } from "@mui/joy"; import { Button } from "@mui/joy";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import toast from "react-hot-toast";
import { useAppSelector } from "../store"; import { useAppSelector } from "../store";
import { showCommonDialog } from "../components/Alert";
import { userService } from "../services"; import { userService } from "../services";
import Icon from "../components/Icon";
import copy from "copy-to-clipboard";
import ChangePasswordDialog from "../components/ChangePasswordDialog"; import ChangePasswordDialog from "../components/ChangePasswordDialog";
interface State { interface State {
@ -20,11 +16,13 @@ const UserDetail: React.FC = () => {
showChangePasswordDialog: false, showChangePasswordDialog: false,
}); });
console.log("here");
useEffect(() => { useEffect(() => {
if (!userService.getState().user) { if (!userService.getState().user) {
navigate("/user/auth"); navigate("/user/auth");
return; return;
} }
console.log("here");
}, []); }, []);
const handleChangePasswordBtnClick = async () => { const handleChangePasswordBtnClick = async () => {
@ -34,34 +32,10 @@ const UserDetail: React.FC = () => {
}); });
}; };
const handleCopyOpenIdBtnClick = async () => {
if (!user?.openId) {
toast.error("OpenID not found");
return;
}
copy(user.openId);
toast.success("OpenID copied");
};
const handleResetOpenIdBtnClick = async () => {
showCommonDialog({
title: "Reset Open API",
content: "❗The existing API will be invalidated and a new one will be generated, are you sure you want to reset?",
style: "warning",
onConfirm: async () => {
await userService.patchUser({
id: user?.id as UserId,
resetOpenId: true,
});
},
});
};
return ( return (
<> <>
<div className="mx-auto max-w-4xl w-full px-3 py-6 flex flex-col justify-start items-start space-y-4"> <div className="mx-auto max-w-4xl w-full px-3 py-6 flex flex-col justify-start items-start space-y-4">
<p className="text-3xl mt-2 mb-4">{user?.displayName}</p> <p className="text-3xl mt-2 mb-4">{user?.nickname}</p>
<p className="leading-8 flex flex-row justify-start items-center"> <p className="leading-8 flex flex-row justify-start items-center">
<span className="mr-3 text-gray-500 font-mono">Email: </span> <span className="mr-3 text-gray-500 font-mono">Email: </span>
{user?.email} {user?.email}
@ -72,21 +46,6 @@ const UserDetail: React.FC = () => {
Change Change
</Button> </Button>
</div> </div>
{/* Do not display open api related field right now. */}
{false && (
<div className="leading-8 flex flex-row justify-start items-center">
<span className="mr-3 text-gray-500 font-mono">OpenID:</span>
<Input type="text" className="w-48" value={user?.openId} readOnly />
<Tooltip title="Copy OpenID" variant="solid" placement="top">
<button className="-ml-6 z-1 bg-white text-gray-600 hover:text-black" onClick={handleCopyOpenIdBtnClick}>
<Icon.Clipboard className="w-4 h-auto" />
</button>
</Tooltip>
<Button className="!ml-6" variant="soft" color="warning" onClick={handleResetOpenIdBtnClick}>
Reset
</Button>
</div>
)}
</div> </div>
{state.showChangePasswordDialog && ( {state.showChangePasswordDialog && (

View File

@ -5,7 +5,6 @@ import Root from "../layout/Root";
import Auth from "../pages/Auth"; import Auth from "../pages/Auth";
import Home from "../pages/Home"; import Home from "../pages/Home";
import UserDetail from "../pages/UserDetail"; import UserDetail from "../pages/UserDetail";
import ShortcutRedirector from "../pages/ShortcutRedirector";
const router = createBrowserRouter([ const router = createBrowserRouter([
{ {
@ -30,6 +29,7 @@ const router = createBrowserRouter([
if (isNullorUndefined(user)) { if (isNullorUndefined(user)) {
return redirect("/user/auth"); return redirect("/user/auth");
} }
return null;
}, },
}, },
{ {
@ -46,14 +46,11 @@ const router = createBrowserRouter([
if (isNullorUndefined(user)) { if (isNullorUndefined(user)) {
return redirect("/user/auth"); return redirect("/user/auth");
} }
return null;
}, },
}, },
], ],
}, },
{
path: "/:shortcutName",
element: <ShortcutRedirector />,
},
]); ]);
export default router; export default router;

View File

@ -9,9 +9,9 @@ interface User {
updatedTs: TimeStamp; updatedTs: TimeStamp;
rowStatus: RowStatus; rowStatus: RowStatus;
username: string;
nickname: string;
email: string; email: string;
displayName: string;
openId: string;
role: Role; role: Role;
} }