feat: update front layout

This commit is contained in:
Maël Gangloff 2024-07-26 18:31:47 +02:00
parent a15c1b2c2f
commit 467d0efa1c
No known key found for this signature in database
GPG Key ID: 11FDC81C24A7F629
13 changed files with 272 additions and 177 deletions

View File

@ -7,12 +7,14 @@ import {
FileSearchOutlined,
InfoCircleOutlined,
LineChartOutlined,
LoginOutlined,
LogoutOutlined,
QuestionCircleOutlined,
SearchOutlined,
TeamOutlined,
UserOutlined
} from "@ant-design/icons";
import {Navigate, Route, Routes, useNavigate} from "react-router-dom";
import {Navigate, Route, Routes, useLocation, useNavigate} from "react-router-dom";
import TextPage from "./pages/TextPage";
import tos from "./content/tos.md";
import privacy from "./content/privacy.md";
@ -23,32 +25,43 @@ import TldPage from "./pages/info/TldPage";
import StatisticsPage from "./pages/info/StatisticsPage";
import WatchlistsPage from "./pages/tracking/WatchlistsPage";
import UserPage from "./pages/UserPage";
import LoginPage from "./pages/LoginPage";
import React, {useEffect, useState} from "react";
import React, {useCallback, useEffect, useMemo, useState} from "react";
import {getUser} from "./utils/api";
import FAQPage from "./pages/FAQPage";
import LoginPage, {AuthenticatedContext} from "./pages/LoginPage";
import ConnectorsPage from "./pages/tracking/ConnectorsPage";
import NotFoundPage from "./pages/NotFoundPage";
export default function App() {
const {
token: {colorBgContainer, borderRadiusLG},
} = theme.useToken()
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
const navigate = useNavigate()
const navigate = useNavigate()
const [isAuthenticated, setIsAuthenticated] = useState(false)
const location = useLocation()
const authenticated = useCallback((authenticated: boolean) => {
setIsAuthenticated(authenticated)
}, []);
const contextValue = useMemo(() => ({
authenticated,
setIsAuthenticated
}), [authenticated, setIsAuthenticated]);
useEffect(() => {
getUser().then(() => setIsAuthenticated(true)).catch(() => setIsAuthenticated(false))
getUser().then(() => {
setIsAuthenticated(true)
if (location.pathname === '/login') navigate('/search/domain')
}).catch(() => {
setIsAuthenticated(false)
if (location.pathname !== '/login') navigate('/login')
})
}, []);
return <Layout hasSider style={{minHeight: '100vh'}}>
<Layout.Sider>
<Menu
defaultSelectedKeys={['1-1']}
defaultOpenKeys={['1', '2', '3']}
mode="inline"
theme="dark"
items={[
const menuItems = [
{
key: '1',
label: 'Search',
@ -145,7 +158,29 @@ export default function App() {
label: 'Privacy Policy',
onClick: () => navigate('/privacy')
}
]}
]
return <AuthenticatedContext.Provider value={contextValue}>
<Layout hasSider style={{minHeight: '100vh'}}>
<Layout.Sider>
<Menu
defaultSelectedKeys={['1-1']}
defaultOpenKeys={['1', '2', '3']}
mode="inline"
theme="dark"
items={[...menuItems, isAuthenticated ? {
key: '8',
icon: <LogoutOutlined/>,
label: 'Log out',
danger: true,
onClick: () => window.location.replace("/logout")
} : {
key: '8',
icon: <LoginOutlined/>,
label: 'Log in',
onClick: () => navigate('/login')
}]}
/>
<div className="demo-logo-vertical"></div>
</Layout.Sider>
@ -160,11 +195,6 @@ export default function App() {
}}>
<Routes>
<Route path="/tos" element={<TextPage markdown={tos}/>}/>
<Route path="/privacy" element={<TextPage markdown={privacy}/>}/>
{isAuthenticated ?
<>
<Route path="/" element={<Navigate to="/search/domain"/>}/>
<Route path="/search/domain" element={<DomainSearchPage/>}/>
@ -175,13 +205,17 @@ export default function App() {
<Route path="/info/stats" element={<StatisticsPage/>}/>
<Route path="/tracking/watchlist" element={<WatchlistsPage/>}/>
<Route path="/tracking/connectors" element={<ConnectorsPage/>}/>
<Route path="/user" element={<UserPage/>}/>
</>
:
<Route path="*" element={<LoginPage/>}/>
}
<Route path="/faq" element={<FAQPage/>}/>
<Route path="/tos" element={<TextPage markdown={tos}/>}/>
<Route path="/privacy" element={<TextPage markdown={privacy}/>}/>
<Route path="/login" element={<LoginPage/>}/>
<Route path="*" element={<NotFoundPage/>}/>
</Routes>
</div>
</Layout.Content>
@ -190,4 +224,5 @@ export default function App() {
</Layout.Footer>
</Layout>
</Layout>
</AuthenticatedContext.Provider>
}

View File

@ -14,7 +14,6 @@ function Index() {
<HashRouter>
<App/>
</HashRouter>
);
}

8
assets/pages/FAQPage.tsx Normal file
View File

@ -0,0 +1,8 @@
import React from "react";
export default function FAQPage() {
return <p>
FAQ Page
</p>
}

View File

@ -1,7 +1,74 @@
import React from "react";
import React, {createContext, useContext, useEffect, useState} from "react";
import {Alert, Button, Card, Flex, Form, Input} from "antd";
import {login} from "../utils/api";
import {useNavigate} from "react-router-dom";
type FieldType = {
username: string;
password: string;
};
export const AuthenticatedContext = createContext<any>(null)
export default function Page() {
return <p>
Login Page
</p>
const [error, setError] = useState()
const navigate = useNavigate()
const {isAuthenticated, setIsAuthenticated} = useContext(AuthenticatedContext)
const onFinish = (data: FieldType) => {
login(data.username, data.password).then(() => {
setIsAuthenticated(true)
navigate('/search/domain')
}).catch((e) => {
setIsAuthenticated(false)
setError(e.response.data.message)
})
}
return <Flex gap="middle" align="center" justify="center" vertical><Card
title="Log in"
style={{width: 500}}
>
{error &&
<Alert
type='error'
message='Error'
banner={true}
role='role'
description={error}
style={{marginBottom: '1em'}}
/>}
<Form
name="basic"
labelCol={{span: 8}}
wrapperCol={{span: 16}}
style={{maxWidth: 600}}
onFinish={onFinish}
autoComplete="off"
>
<Form.Item
label="Username"
name="username"
rules={[{required: true, message: 'Required'}]}
>
<Input/>
</Form.Item>
<Form.Item<FieldType>
label="Password"
name="password"
rules={[{required: true, message: 'Required'}]}
>
<Input.Password/>
</Form.Item>
<Form.Item wrapperCol={{offset: 8, span: 16}}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</Card>
</Flex>
}

View File

@ -1,4 +1,4 @@
import {Button, Result} from "antd";
import {Result} from "antd";
import React from "react";
@ -7,6 +7,5 @@ export default function NotFoundPage() {
status="404"
title="404"
subTitle="Sorry, the page you visited does not exist."
extra={<Button type="primary">Back Home</Button>}
/>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function StatisticsPage() {
return <p>
Tld
Statistics Page
</p>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function TldPage() {
return <p>
Tld
Tld Page
</p>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function DomainSearchPage() {
return <p>
Domain Search Page
</p>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function EntitySearchPage() {
return <p>
Entity Search Page
</p>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function NameserverSearchPage() {
return <p>
NS Finder
NS Search Page
</p>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function ConnectorsPage() {
return <p>
Connectors Page
</p>
}

View File

@ -2,6 +2,6 @@ import React from "react";
export default function WatchlistsPage() {
return <p>
Watchlists Page
</p>
}

View File

@ -8,21 +8,8 @@ interface Tld {
}
export async function getTldList(params: object): Promise<Tld[]> {
let page = 1
let response = (await request<Tld[]>({
return (await request<Tld[]>({
url: 'tld',
params: {...params, page},
params,
})).data
const tldList: Tld[] = response;
while (response.length !== 0) {
page++
response = (await request<Tld[]>({
url: 'tld',
params: {...params, page},
})).data
tldList.push(...response)
}
return tldList
}