feat: add dark theme support

This commit is contained in:
Maël Gangloff
2024-12-20 20:21:05 +01:00
parent 425071bc23
commit ad8a99c291
3 changed files with 74 additions and 57 deletions

View File

@@ -1,4 +1,4 @@
import {Button, Layout, Space, theme, Typography} from "antd"; import {Button, ConfigProvider, Layout, Space, theme, Typography} from "antd";
import {Link, Navigate, Route, Routes, useLocation, useNavigate} from "react-router-dom"; import {Link, Navigate, Route, Routes, useLocation, useNavigate} from "react-router-dom";
import TextPage from "./pages/TextPage"; import TextPage from "./pages/TextPage";
import DomainSearchPage from "./pages/search/DomainSearchPage"; import DomainSearchPage from "./pages/search/DomainSearchPage";
@@ -21,9 +21,6 @@ const ProjectLink = <Link to='https://github.com/maelgangloff/domain-watchdog'>D
const LicenseLink = <Link to='https://www.gnu.org/licenses/agpl-3.0.txt'>AGPL-3.0-or-later</Link> const LicenseLink = <Link to='https://www.gnu.org/licenses/agpl-3.0.txt'>AGPL-3.0-or-later</Link>
export default function App() { export default function App() {
const {
token: {colorBgContainer, borderRadiusLG},
} = theme.useToken()
const navigate = useNavigate() const navigate = useNavigate()
const location = useLocation() const location = useLocation()
@@ -32,7 +29,6 @@ export default function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false) const [isAuthenticated, setIsAuthenticated] = useState(false)
const authenticated = useCallback((authenticated: boolean) => { const authenticated = useCallback((authenticated: boolean) => {
setIsAuthenticated(authenticated) setIsAuthenticated(authenticated)
}, []); }, []);
@@ -42,6 +38,23 @@ export default function App() {
setIsAuthenticated setIsAuthenticated
}), [authenticated, setIsAuthenticated]) }), [authenticated, setIsAuthenticated])
const [darkMode, setDarkMode] = useState(false);
const windowQuery = window.matchMedia("(prefers-color-scheme:dark)");
const darkModeChange = useCallback((event: MediaQueryListEvent) => {
setDarkMode(event.matches)
}, [])
useEffect(() => {
windowQuery.addEventListener("change", darkModeChange)
return () => {
windowQuery.removeEventListener("change", darkModeChange)
}
}, [windowQuery, darkModeChange])
useEffect(() => {
setDarkMode(windowQuery.matches)
}, [])
useEffect(() => { useEffect(() => {
getUser().then(() => { getUser().then(() => {
@@ -52,63 +65,66 @@ export default function App() {
const pathname = location.pathname const pathname = location.pathname
if (!['/login', '/tos', '/faq', '/privacy'].includes(pathname)) navigate('/home') if (!['/login', '/tos', '/faq', '/privacy'].includes(pathname)) navigate('/home')
}) })
}, []); }, [])
return <AuthenticatedContext.Provider value={contextValue}> return <ConfigProvider
<Layout hasSider style={{minHeight: '100vh'}}> theme={{
{/* Ant will use a break-off tab to toggle the collapse of the sider when collapseWidth = 0*/} algorithm: darkMode ? theme.darkAlgorithm : theme.compactAlgorithm
<Layout.Sider collapsible breakpoint="sm" {...(sm ? {collapsedWidth: 0} : {})}> }}
<Sider isAuthenticated={isAuthenticated}/> >
</Layout.Sider> <AuthenticatedContext.Provider value={contextValue}>
<Layout> <Layout hasSider style={{minHeight: '100vh'}}>
<Layout.Header style={{padding: 0, background: colorBgContainer}}/> {/* Ant will use a break-off tab to toggle the collapse of the sider when collapseWidth = 0*/}
<Layout.Content style={sm ? {margin: '24px 0'} : {margin: '24px 16px 0'}}> <Layout.Sider collapsible breakpoint="sm" {...(sm ? {collapsedWidth: 0} : {})}>
<div style={{ <Sider isAuthenticated={isAuthenticated}/>
padding: 24, </Layout.Sider>
minHeight: 360, <Layout>
background: colorBgContainer, <Layout.Header style={{padding: 0}}/>
borderRadius: borderRadiusLG, <Layout.Content style={sm ? {margin: '24px 0'} : {margin: '24px 16px 0'}}>
}}> <div style={{
padding: 24,
minHeight: 360,
}}>
<Routes>
<Route path="/" element={<Navigate to="/login"/>}/>
<Route path="/home" element={<TextPage resource='home.md'/>}/>
<Routes> <Route path="/search/domain" element={<DomainSearchPage/>}/>
<Route path="/" element={<Navigate to="/login"/>}/> <Route path="/search/entity" element={<EntitySearchPage/>}/>
<Route path="/home" element={<TextPage resource='home.md'/>}/> <Route path="/search/nameserver" element={<NameserverSearchPage/>}/>
<Route path="/search/tld" element={<TldPage/>}/>
<Route path="/search/domain" element={<DomainSearchPage/>}/> <Route path="/tracking/watchlist" element={<WatchlistPage/>}/>
<Route path="/search/entity" element={<EntitySearchPage/>}/> <Route path="/tracking/connectors" element={<ConnectorsPage/>}/>
<Route path="/search/nameserver" element={<NameserverSearchPage/>}/>
<Route path="/search/tld" element={<TldPage/>}/>
<Route path="/tracking/watchlist" element={<WatchlistPage/>}/> <Route path="/stats" element={<StatisticsPage/>}/>
<Route path="/tracking/connectors" element={<ConnectorsPage/>}/> <Route path="/user" element={<UserPage/>}/>
<Route path="/stats" element={<StatisticsPage/>}/> <Route path="/faq" element={<TextPage resource='faq.md'/>}/>
<Route path="/user" element={<UserPage/>}/> <Route path="/tos" element={<TextPage resource='tos.md'/>}/>
<Route path="/privacy" element={<TextPage resource='privacy.md'/>}/>
<Route path="/faq" element={<TextPage resource='faq.md'/>}/> <Route path="/login" element={<LoginPage/>}/>
<Route path="/tos" element={<TextPage resource='tos.md'/>}/>
<Route path="/privacy" element={<TextPage resource='privacy.md'/>}/>
<Route path="/login" element={<LoginPage/>}/> <Route path="*" element={<NotFoundPage/>}/>
</Routes>
<Route path="*" element={<NotFoundPage/>}/> </div>
</Routes> </Layout.Content>
</div> <Layout.Footer style={{textAlign: 'center'}}>
</Layout.Content> <Space size='middle' wrap align='center'>
<Layout.Footer style={{textAlign: 'center'}}> <Link to='/tos'><Button type='text'>{t`TOS`}</Button></Link>
<Space size='middle' wrap align='center'> <Link to='/privacy'><Button type='text'>{t`Privacy Policy`}</Button></Link>
<Link to='/tos'><Button type='text'>{t`TOS`}</Button></Link> <Link to='/faq'><Button type='text'>{t`FAQ`}</Button></Link>
<Link to='/privacy'><Button type='text'>{t`Privacy Policy`}</Button></Link> <Typography.Link href='https://github.com/maelgangloff/domain-watchdog/wiki'><Button
<Link to='/faq'><Button type='text'>{t`FAQ`}</Button></Link> type='text'>{t`Documentation`}</Button></Typography.Link>
<Typography.Link href='https://github.com/maelgangloff/domain-watchdog/wiki'><Button </Space>
type='text'>{t`Documentation`}</Button></Typography.Link> <Typography.Paragraph style={{marginTop: '1em'}}>
</Space> {jt`${ProjectLink} is an open source project distributed under the ${LicenseLink} license.`}
<Typography.Paragraph style={{marginTop: '1em'}}> </Typography.Paragraph>
{jt`${ProjectLink} is an open source project distributed under the ${LicenseLink} license.`} </Layout.Footer>
</Typography.Paragraph> </Layout>
</Layout.Footer>
</Layout> </Layout>
</Layout> </AuthenticatedContext.Provider>
</AuthenticatedContext.Provider> </ConfigProvider>
} }

View File

@@ -36,7 +36,7 @@ export function DomainDiagram({domain}: { domain: Domain }) {
return <Flex style={{width: '100%', height: '100vh'}}> return <Flex style={{width: '100%', height: '100vh'}}>
<ReactFlow <ReactFlow
fitView fitView
colorMode='dark' colorMode='system'
nodesConnectable={false} nodesConnectable={false}
edgesReconnectable={false} edgesReconnectable={false}
nodes={nodes} nodes={nodes}

View File

@@ -256,6 +256,7 @@ readonly class RDAPService
continue; continue;
} }
$entity = $this->registerEntity($rdapEntity); $entity = $this->registerEntity($rdapEntity);
$this->em->flush();
$domainEntity = $this->domainEntityRepository->findOneBy([ $domainEntity = $this->domainEntityRepository->findOneBy([
'domain' => $domain, 'domain' => $domain,
@@ -327,6 +328,7 @@ readonly class RDAPService
continue; continue;
} }
$entity = $this->registerEntity($rdapEntity); $entity = $this->registerEntity($rdapEntity);
$this->em->flush();
$nameserverEntity = $this->nameserverEntityRepository->findOneBy([ $nameserverEntity = $this->nameserverEntityRepository->findOneBy([
'nameserver' => $nameserver, 'nameserver' => $nameserver,
@@ -477,7 +479,6 @@ readonly class RDAPService
} }
$this->em->persist($entity); $this->em->persist($entity);
$this->em->flush();
if (isset($domainEntities)) { if (isset($domainEntities)) {
/** @var DomainEntity[] $domainEntities */ /** @var DomainEntity[] $domainEntities */