chore: auf Wiedersehen MUI, hallo Ant Design

This commit is contained in:
Maël Gangloff
2024-07-26 16:45:10 +02:00
parent a384140aa7
commit a15c1b2c2f
32 changed files with 923 additions and 1230 deletions

View File

@@ -1,61 +0,0 @@
import React, {ChangeEvent, useState} from 'react';
import Container from "@mui/material/Container";
import {Grid, InputAdornment, Paper} from "@mui/material";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import {Explore} from "@mui/icons-material";
import Footer from "../components/Footer";
export default function DomainFinderPage() {
const [ldhName, setLdhName] = useState("")
const [error, setError] = useState(false)
const onChangeDomain = (e: ChangeEvent<HTMLInputElement>) => {
setLdhName(e.currentTarget.value);
const regex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/
setError(!regex.test(e.currentTarget.value))
}
return (
<>
<Container maxWidth="lg" sx={{mt: 20, mb: 4}}>
<Grid container spacing={3}>
<Grid item xs={12} md={8} lg={9}>
<Paper
sx={{
p: 2,
display: 'flex',
flexDirection: 'column',
height: 240,
}}
>
<TextField
sx={{mt: 5}} label="Domain name" variant="standard" value={ldhName}
onChange={onChangeDomain}
helperText={error && "This domain name does not appear to be valid"}
error={error}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Explore/>
</InputAdornment>
),
}}
/>
<Typography variant="subtitle2" sx={{mt: 3}}>
This tool allows you to search for a domain name in the database.
As a reminder, if a domain name is unknown to Domain Watchdog or if the data is
more
than a week old, an RDAP search will be performed. The RDAP search is an operation worth
a token.
</Typography>
</Paper>
</Grid>
</Grid>
<Footer/>
</Container>
</>
);
};

View File

@@ -1,20 +0,0 @@
import React from 'react';
import Container from "@mui/material/Container";
import {Grid} from "@mui/material";
import Footer from "../components/Footer";
export default function EntityFinderPage() {
return (
<>
<Container maxWidth="lg" sx={{mt: 20, mb: 4}}>
<Grid container spacing={3}>
<Grid item xs={12} md={8} lg={9}>
</Grid>
</Grid>
<Footer/>
</Container>
</>
);
};

View File

@@ -1,110 +1,7 @@
import * as React from 'react';
import {useState} from 'react';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Box from '@mui/material/Box';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import Typography from '@mui/material/Typography';
import Link from "@mui/material/Link";
import {login} from "../utils/api";
import {useNavigate} from "react-router-dom";
import {Alert} from "@mui/material";
import Container from "@mui/material/Container";
import Footer from "../components/Footer";
import React from "react";
interface Props {
setIsAuthenticated: (val: boolean) => void
}
export default function LoginPage({setIsAuthenticated}: Props) {
const navigate = useNavigate()
const [error, setError] = useState<string>('')
const [credentials, setCredentials] = useState({email: "", password: ""})
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
try {
await login(credentials.email, credentials.password);
setIsAuthenticated(true)
navigate('/');
} catch (e: any) {
setCredentials({...credentials, password: ""})
setError(e.response.data.message)
}
};
return (
<>
<Container component="main" maxWidth="xs">
<Box
sx={{
marginTop: 20,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{m: 1, bgcolor: 'secondary.main'}}>
<LockOutlinedIcon/>
</Avatar>
<Typography component="h1" variant="h5">
Sign in
</Typography>
<Box component="form" onSubmit={handleSubmit} noValidate sx={{mt: 1}}>
{
error !== "" && <Alert variant="outlined" severity="error">{error}</Alert>
}
<TextField
margin="normal"
required
fullWidth
id="email"
label="Email Address"
name="email"
autoComplete="email"
autoFocus
value={credentials.email}
onChange={(e) => setCredentials({...credentials, email: e.currentTarget.value})}
/>
<TextField
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
value={credentials.password}
autoComplete="current-password"
onChange={(e) => setCredentials({...credentials, password: e.currentTarget.value})}
/>
<Button
type="submit"
fullWidth
variant="contained"
sx={{mt: 3}}
>
Sign In
</Button>
</Box>
</Box>
<Link href="/login/oauth">
<Button
type="button"
fullWidth
color='secondary'
variant="contained"
sx={{mt: 3, mb: 2}}
>
Single Sign-On
</Button>
</Link>
<Footer/>
</Container>
</>
);
export default function Page() {
return <p>
Login Page
</p>
}

View File

@@ -1,20 +0,0 @@
import React from 'react';
import Container from "@mui/material/Container";
import {Grid} from "@mui/material";
import Footer from "../components/Footer";
export default function NameserverFinderPage() {
return (
<>
<Container maxWidth="lg" sx={{mt: 20, mb: 4}}>
<Grid container spacing={3}>
<Grid item xs={12} md={8} lg={9}>
</Grid>
</Grid>
<Footer/>
</Container>
</>
);
};

View File

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

View File

@@ -1,20 +0,0 @@
import React from 'react';
import Container from "@mui/material/Container";
import {Grid} from "@mui/material";
import Footer from "../components/Footer";
export default function ReverseDirectoryPage() {
return (
<>
<Container maxWidth="lg" sx={{mt: 20, mb: 4}}>
<Grid container spacing={3}>
<Grid item xs={12} md={8} lg={9}>
</Grid>
</Grid>
<Footer/>
</Container>
</>
);
};

View File

@@ -1,38 +1,6 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import Container from "@mui/material/Container";
import Footer from "../components/Footer";
import React from "react";
import snarkdown from "snarkdown"
interface Props {
content: string
}
export default function Index({content}: Props) {
return (
<Container
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: {xs: 4, sm: 8},
py: {xs: 8, sm: 10},
textAlign: {sm: 'center', md: 'left'},
}}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
pt: {xs: 4, sm: 8},
width: '100%',
borderTop: '1px solid',
borderColor: 'divider',
}}
>
<div dangerouslySetInnerHTML={{__html: content}}></div>
</Box>
<Footer/>
</Container>
)
}
export default function TextPage({markdown}: { markdown: string }) {
return <div dangerouslySetInnerHTML={{__html: snarkdown(markdown)}}></div>
}

View File

@@ -1,110 +0,0 @@
import React, {useEffect, useState} from 'react';
import Container from "@mui/material/Container";
import {Accordion, AccordionDetails, AccordionSummary, Grid, Typography} from "@mui/material";
import {ExpandMore} from "@mui/icons-material";
import HeadTable from "../components/HeadTable";
import {getTldList} from "../utils/api";
import Footer from "../components/Footer";
const gTldColumns = [
{id: 'tld', label: 'TLD'},
{id: 'registryOperator', label: 'Operator'}
]
const sTldColumns = [
{id: 'tld', label: 'TLD'}
]
const toEmoji = (tld: string) => String.fromCodePoint(
...getCountryCode(tld)
.toUpperCase()
.split('')
.map((char) => 127397 + char.charCodeAt(0)
)
)
const getCountryCode = (tld: string): string => {
const exceptions = {uk: 'gb', su: 'ru', tp: 'tl'}
if (tld in exceptions) return exceptions[tld as keyof typeof exceptions]
return tld
}
const regionNames = new Intl.DisplayNames(['en'], {type: 'region'})
const ccTldColumns = [
{id: 'tld', label: 'TLD'},
{
id: 'tld',
label: 'Flag',
format: (tld: string) => toEmoji(tld)
},
{id: 'tld', label: 'Country name', format: (tld: string) => regionNames.of(getCountryCode(tld)) ?? '-'},
]
export default function TldPage() {
const [sTld, setSTld] = useState<any>([])
const [gTld, setGTld] = useState<any>([])
const [ccTld, setCcTld] = useState<any>([])
const [brandGTld, setBrandGTld] = useState<any>([])
useEffect(() => {
getTldList({type: 'sTLD'}).then(setSTld)
getTldList({type: 'gTLD', contractTerminated: 0, specification13: 0}).then(setGTld)
getTldList({type: 'gTLD', contractTerminated: 0, specification13: 1}).then(setBrandGTld)
getTldList({type: 'ccTLD'}).then(setCcTld)
}, [])
return (
<Container maxWidth="lg" sx={{mt: 20, mb: 4}}>
<Grid container spacing={3}>
<Grid item xs={12} md={8} lg={9}>
<Accordion>
<AccordionSummary expandIcon={<ExpandMore/>}>
<Typography sx={{width: '33%', flexShrink: 0}}>
sTLD
</Typography>
<Typography sx={{color: 'text.secondary'}}>Sponsored Top-Level Domains</Typography>
</AccordionSummary>
<AccordionDetails>
<HeadTable rows={sTld} columns={sTldColumns}/>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary expandIcon={<ExpandMore/>}>
<Typography sx={{width: '33%', flexShrink: 0}}>
gTLD
</Typography>
<Typography sx={{color: 'text.secondary'}}>Generic Top-Level Domains</Typography>
</AccordionSummary>
<AccordionDetails>
<HeadTable rows={gTld} columns={gTldColumns}/>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary expandIcon={<ExpandMore/>}>
<Typography sx={{width: '33%', flexShrink: 0}}>
Brand gTLD
</Typography>
<Typography sx={{color: 'text.secondary'}}>Brand Generic Top-Level Domains</Typography>
</AccordionSummary>
<AccordionDetails>
<HeadTable rows={brandGTld} columns={gTldColumns}/>
</AccordionDetails>
</Accordion>
<Accordion>
<AccordionSummary expandIcon={<ExpandMore/>}>
<Typography sx={{width: '33%', flexShrink: 0}}>
ccTLD
</Typography>
<Typography sx={{color: 'text.secondary'}}>Country-Code Top-Level Domains</Typography>
</AccordionSummary>
<AccordionDetails>
<HeadTable rows={ccTld} columns={ccTldColumns}/>
</AccordionDetails>
</Accordion>
</Grid>
</Grid>
<Footer/>
</Container>
);
};

View File

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

View File

@@ -1,41 +0,0 @@
import React, {useEffect, useState} from 'react';
import Container from "@mui/material/Container";
import {Grid, List, ListItem, ListItemText} from "@mui/material";
import Footer from "../components/Footer";
import {deleteWatchlist, getWatchlists, Watchlist} from "../utils/api";
import IconButton from "@mui/material/IconButton";
import {DeleteForever} from '@mui/icons-material'
export default function WatchlistsPage() {
const [watchlists, setWatchlists] = useState<(Partial<Watchlist> & { token: string })[]>([])
const [refreshKey, setRefreshKey] = useState(0)
useEffect(() => {
getWatchlists().then(setWatchlists)
}, [refreshKey])
return (
<Container maxWidth="lg" sx={{mt: 20, mb: 4}}>
<Grid container spacing={3}>
<Grid item xs={12} md={8} lg={9}>
<List sx={{width: '100%', bgcolor: 'background.paper'}}>
{watchlists.map((w) => (
<ListItem
key={w.token}
secondaryAction={
<IconButton aria-label="delete"
onClick={(e) => deleteWatchlist(w.token).then(() => setRefreshKey(refreshKey + 1))}>
<DeleteForever/>
</IconButton>
}
>
<ListItemText primary={`Token ${w.token}`}/>
</ListItem>
))}
</List>
</Grid>
</Grid>
<Footer/>
</Container>
);
};

View File

@@ -0,0 +1,7 @@
import React from "react";
export default function StatisticsPage() {
return <p>
Tld
</p>
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
import React from "react";
export default function NameserverSearchPage() {
return <p>
NS Finder
</p>
}

View File

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

View File

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