mirror of
https://github.com/aykhans/slash-e.git
synced 2025-07-07 13:42:34 +00:00
chore: update router config
This commit is contained in:
@ -1,59 +1,8 @@
|
||||
import { useEffect } from "react";
|
||||
import { Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
||||
import { userService, workspaceService } from "./services";
|
||||
import useLoading from "./hooks/useLoading";
|
||||
import Only from "./components/common/OnlyWhen";
|
||||
import Auth from "./pages/Auth";
|
||||
import Home from "./pages/Home";
|
||||
import WorkspaceDetail from "./pages/WorkspaceDetail";
|
||||
import UserDetail from "./pages/UserDetail";
|
||||
import ShortcutRedirector from "./pages/ShortcutRedirector";
|
||||
|
||||
const pathnameWhitelist = [/\/.+?\/go\/.+/];
|
||||
import { RouterProvider } from "react-router-dom";
|
||||
import router from "./router";
|
||||
|
||||
function App() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const pageLoadingStatus = useLoading();
|
||||
|
||||
useEffect(() => {
|
||||
let needAuth = true;
|
||||
|
||||
for (const regexp of pathnameWhitelist) {
|
||||
if (regexp.test(location.pathname)) {
|
||||
needAuth = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!needAuth) {
|
||||
pageLoadingStatus.setFinish();
|
||||
return;
|
||||
}
|
||||
|
||||
userService.initialState().finally(() => {
|
||||
if (!userService.getState().user) {
|
||||
pageLoadingStatus.setFinish();
|
||||
navigate("/user/auth");
|
||||
return;
|
||||
}
|
||||
|
||||
Promise.all([workspaceService.fetchWorkspaceList()]).finally(() => {
|
||||
pageLoadingStatus.setFinish();
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Only when={!pageLoadingStatus.isLoading}>
|
||||
<Routes>
|
||||
<Route index element={<Home />} />
|
||||
<Route path="/user/auth" element={<Auth />} />
|
||||
<Route path="/account/" element={<UserDetail />} />
|
||||
<Route path="/:workspaceName" element={<WorkspaceDetail />} />
|
||||
<Route path="/:workspaceName/go/:shortcutName" element={<ShortcutRedirector />} />
|
||||
</Routes>
|
||||
</Only>
|
||||
);
|
||||
return <RouterProvider router={router} />;
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
@ -3,7 +3,6 @@ import { useAppSelector } from "../store";
|
||||
import { userService } from "../services";
|
||||
import Icon from "./Icon";
|
||||
import Dropdown from "./common/Dropdown";
|
||||
import Only from "./common/OnlyWhen";
|
||||
import showCreateWorkspaceDialog from "./CreateWorkspaceDialog";
|
||||
|
||||
const Header: React.FC = () => {
|
||||
@ -25,7 +24,7 @@ const Header: React.FC = () => {
|
||||
<Link to={"/"} className="text-base font-mono font-medium cursor-pointer">
|
||||
Corgi
|
||||
</Link>
|
||||
<Only when={workspaceList.length > 0 && activedWorkspace !== undefined}>
|
||||
{workspaceList.length > 0 && activedWorkspace !== undefined && (
|
||||
<>
|
||||
<span className="font-mono mx-2 text-gray-200">/</span>
|
||||
<Dropdown
|
||||
@ -45,9 +44,7 @@ const Header: React.FC = () => {
|
||||
className="w-full px-3 leading-10 flex flex-row justify-between items-center text-left cursor-pointer rounded whitespace-nowrap hover:bg-gray-100"
|
||||
>
|
||||
<span className="truncate">{workspace.name}</span>
|
||||
<Only when={workspace.name === activedWorkspace?.name}>
|
||||
<Icon.Check className="w-4 h-auto ml-1 shrink-0" />
|
||||
</Only>
|
||||
{workspace.name === activedWorkspace?.name && <Icon.Check className="w-4 h-auto ml-1 shrink-0" />}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
@ -63,7 +60,7 @@ const Header: React.FC = () => {
|
||||
actionsClassName="!w-48 !-left-4"
|
||||
></Dropdown>
|
||||
</>
|
||||
</Only>
|
||||
)}
|
||||
</div>
|
||||
<div className="relative">
|
||||
{user ? (
|
||||
|
@ -1,15 +0,0 @@
|
||||
import { ReactNode } from "react";
|
||||
|
||||
interface OnlyWhenProps {
|
||||
children: ReactNode;
|
||||
when: boolean;
|
||||
}
|
||||
|
||||
const OnlyWhen: React.FC<OnlyWhenProps> = (props: OnlyWhenProps) => {
|
||||
const { children, when } = props;
|
||||
return when ? <>{children}</> : null;
|
||||
};
|
||||
|
||||
const Only = OnlyWhen;
|
||||
|
||||
export default Only;
|
@ -1,6 +1,5 @@
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { Provider } from "react-redux";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
import store from "./store";
|
||||
import App from "./App";
|
||||
import "./helpers/polyfill";
|
||||
@ -9,9 +8,7 @@ import "./css/index.css";
|
||||
const container = document.getElementById("root");
|
||||
const root = createRoot(container as HTMLElement);
|
||||
root.render(
|
||||
<BrowserRouter>
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
</BrowserRouter>
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
);
|
||||
|
@ -5,7 +5,6 @@ import { validate, ValidatorConfig } from "../helpers/validator";
|
||||
import { userService } from "../services";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
import Icon from "../components/Icon";
|
||||
import Only from "../components/common/OnlyWhen";
|
||||
import toastHelper from "../components/Toast";
|
||||
|
||||
const validateConfig: ValidatorConfig = {
|
||||
@ -123,9 +122,7 @@ const Auth: React.FC = () => {
|
||||
<div className="flex flex-col justify-start items-start w-full mb-4">
|
||||
<div className="text-3xl font-medium font-mono flex flex-row justify-start items-center">
|
||||
Corgi
|
||||
<Only when={actionBtnLoadingState.isLoading}>
|
||||
<Icon.Loader className="ml-2 w-5 h-auto animate-spin" />
|
||||
</Only>
|
||||
{actionBtnLoadingState.isLoading && <Icon.Loader className="ml-2 w-5 h-auto animate-spin" />}
|
||||
</div>
|
||||
</div>
|
||||
<div className={`flex flex-col justify-start items-start w-full ${actionBtnLoadingState.isLoading ? "opacity-80" : ""}`}>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useEffect } from "react";
|
||||
import { workspaceService } from "../services";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { userService, workspaceService } from "../services";
|
||||
import { useAppSelector } from "../store";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
import Icon from "../components/Icon";
|
||||
@ -8,10 +9,16 @@ import WorkspaceListView from "../components/WorkspaceListView";
|
||||
import showCreateWorkspaceDialog from "../components/CreateWorkspaceDialog";
|
||||
|
||||
const Home: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const { workspaceList } = useAppSelector((state) => state.workspace);
|
||||
const loadingState = useLoading();
|
||||
|
||||
useEffect(() => {
|
||||
if (!userService.getState().user) {
|
||||
navigate("/user/auth");
|
||||
return;
|
||||
}
|
||||
|
||||
Promise.all([workspaceService.fetchWorkspaceList()]).finally(() => {
|
||||
loadingState.setFinish();
|
||||
});
|
||||
|
@ -1,19 +1,26 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import Header from "../components/Header";
|
||||
import { getShortcutWithNameAndWorkspaceName } from "../helpers/api";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
import { userService } from "../services";
|
||||
|
||||
interface State {
|
||||
errMessage?: string;
|
||||
}
|
||||
|
||||
const ShortcutRedirector: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const [state, setState] = useState<State>();
|
||||
const loadingState = useLoading();
|
||||
|
||||
useEffect(() => {
|
||||
if (!userService.getState().user) {
|
||||
navigate("/user/auth");
|
||||
return;
|
||||
}
|
||||
|
||||
const workspaceName = params.workspaceName || "";
|
||||
const shortcutName = params.shortcutName || "";
|
||||
getShortcutWithNameAndWorkspaceName(workspaceName, shortcutName)
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAppSelector } from "../store";
|
||||
import Header from "../components/Header";
|
||||
import { showCommonDialog } from "../components/Dialog/CommonDialog";
|
||||
@ -8,8 +10,16 @@ import toastHelper from "../components/Toast";
|
||||
import showChangePasswordDialog from "../components/ChangePasswordDialog";
|
||||
|
||||
const UserDetail: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAppSelector((state) => state.user);
|
||||
|
||||
useEffect(() => {
|
||||
if (!userService.getState().user) {
|
||||
navigate("/user/auth");
|
||||
return;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleChangePasswordBtnClick = async () => {
|
||||
showChangePasswordDialog();
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { shortcutService, workspaceService } from "../services";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { shortcutService, userService, workspaceService } from "../services";
|
||||
import { useAppSelector } from "../store";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
import Icon from "../components/Icon";
|
||||
@ -15,6 +15,7 @@ interface State {
|
||||
}
|
||||
|
||||
const WorkspaceDetail: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const { shortcutList } = useAppSelector((state) => state.shortcut);
|
||||
const [state, setState] = useState<State>({
|
||||
@ -23,6 +24,11 @@ const WorkspaceDetail: React.FC = () => {
|
||||
const loadingState = useLoading();
|
||||
|
||||
useEffect(() => {
|
||||
if (!userService.getState().user) {
|
||||
navigate("/user/auth");
|
||||
return;
|
||||
}
|
||||
|
||||
const workspace = workspaceService.getWorkspaceByName(params.workspaceName ?? "");
|
||||
if (!workspace) {
|
||||
toastHelper.error("workspace not found");
|
||||
|
62
web/src/router/index.tsx
Normal file
62
web/src/router/index.tsx
Normal file
@ -0,0 +1,62 @@
|
||||
import { createBrowserRouter } from "react-router-dom";
|
||||
import { userService, workspaceService } from "../services";
|
||||
import Auth from "../pages/Auth";
|
||||
import Home from "../pages/Home";
|
||||
import UserDetail from "../pages/UserDetail";
|
||||
import WorkspaceDetail from "../pages/WorkspaceDetail";
|
||||
import ShortcutRedirector from "../pages/ShortcutRedirector";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: "/",
|
||||
element: <Home />,
|
||||
loader: async () => {
|
||||
try {
|
||||
await userService.initialState();
|
||||
} catch (error) {
|
||||
// do nth
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/user/auth",
|
||||
element: <Auth />,
|
||||
},
|
||||
{
|
||||
path: "/account",
|
||||
element: <UserDetail />,
|
||||
loader: async () => {
|
||||
try {
|
||||
await userService.initialState();
|
||||
} catch (error) {
|
||||
// do nth
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/:workspaceName",
|
||||
element: <WorkspaceDetail />,
|
||||
loader: async () => {
|
||||
try {
|
||||
await userService.initialState();
|
||||
await workspaceService.fetchWorkspaceList();
|
||||
} catch (error) {
|
||||
// do nth
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/:workspaceName/go/:shortcutName",
|
||||
element: <ShortcutRedirector />,
|
||||
loader: async () => {
|
||||
try {
|
||||
await userService.initialState();
|
||||
await workspaceService.fetchWorkspaceList();
|
||||
} catch (error) {
|
||||
// do nth
|
||||
}
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
export default router;
|
Reference in New Issue
Block a user