mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
feat: add eslint linter
This commit is contained in:
@@ -1,16 +1,24 @@
|
||||
import React, {createContext, useEffect, useState} from "react";
|
||||
import {Button, Card} from "antd";
|
||||
import React, {createContext, useEffect, useState} from 'react'
|
||||
import {Button, Card} from 'antd'
|
||||
import {t} from 'ttag'
|
||||
import TextPage from "./TextPage";
|
||||
import {LoginForm} from "../components/LoginForm";
|
||||
import {getConfiguration, InstanceConfig} from "../utils/api";
|
||||
import {RegisterForm} from "../components/RegisterForm";
|
||||
import TextPage from './TextPage'
|
||||
import {LoginForm} from '../components/LoginForm'
|
||||
import {getConfiguration, InstanceConfig} from '../utils/api'
|
||||
import {RegisterForm} from '../components/RegisterForm'
|
||||
|
||||
|
||||
export const AuthenticatedContext = createContext<any>(null)
|
||||
export const AuthenticatedContext = createContext<
|
||||
{
|
||||
authenticated: (authenticated: boolean) => void
|
||||
setIsAuthenticated: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
>({
|
||||
authenticated: () => {
|
||||
},
|
||||
setIsAuthenticated: () => {
|
||||
}
|
||||
})
|
||||
|
||||
export default function LoginPage() {
|
||||
|
||||
const [wantRegister, setWantRegister] = useState<boolean>(false)
|
||||
const [configuration, setConfiguration] = useState<InstanceConfig>()
|
||||
|
||||
@@ -22,19 +30,24 @@ export default function LoginPage() {
|
||||
getConfiguration().then(setConfiguration)
|
||||
}, [])
|
||||
|
||||
return <Card title={wantRegister ? t`Register` : t`Log in`} style={{width: '100%'}}>
|
||||
<Card.Grid style={{width: '50%', textAlign: 'center'}} hoverable={false}>
|
||||
{wantRegister ? <RegisterForm/> : <LoginForm ssoLogin={configuration?.ssoLogin}/>}
|
||||
{
|
||||
configuration?.registerEnabled &&
|
||||
<Button type='link'
|
||||
return (
|
||||
<Card title={wantRegister ? t`Register` : t`Log in`} style={{width: '100%'}}>
|
||||
<Card.Grid style={{width: '50%', textAlign: 'center'}} hoverable={false}>
|
||||
{wantRegister ? <RegisterForm/> : <LoginForm ssoLogin={configuration?.ssoLogin}/>}
|
||||
{
|
||||
configuration?.registerEnabled &&
|
||||
<Button
|
||||
type='link'
|
||||
block
|
||||
style={{marginTop: '1em'}}
|
||||
onClick={toggleWantRegister}>{wantRegister ? t`Log in` : t`Create an account`}</Button>
|
||||
}
|
||||
</Card.Grid>
|
||||
<Card.Grid style={{width: '50%'}} hoverable={false}>
|
||||
<TextPage resource='ads.md'/>
|
||||
</Card.Grid>
|
||||
</Card>
|
||||
}
|
||||
onClick={toggleWantRegister}
|
||||
>{wantRegister ? t`Log in` : t`Create an account`}
|
||||
</Button>
|
||||
}
|
||||
</Card.Grid>
|
||||
<Card.Grid style={{width: '50%'}} hoverable={false}>
|
||||
<TextPage resource='ads.md'/>
|
||||
</Card.Grid>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import {Result} from "antd";
|
||||
import React from "react";
|
||||
import {Result} from 'antd'
|
||||
import React from 'react'
|
||||
import {t} from 'ttag'
|
||||
|
||||
|
||||
export default function NotFoundPage() {
|
||||
return <Result
|
||||
status="404"
|
||||
title="404"
|
||||
subTitle={t`Sorry, the page you visited does not exist.`}
|
||||
/>
|
||||
}
|
||||
return (
|
||||
<Result
|
||||
status='404'
|
||||
title='404'
|
||||
subTitle={t`Sorry, the page you visited does not exist.`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {getStatistics, Statistics} from "../utils/api";
|
||||
import {Card, Col, Divider, Row, Statistic, Tooltip} from "antd";
|
||||
import {t} from "ttag";
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {getStatistics, Statistics} from '../utils/api'
|
||||
import {Card, Col, Divider, Row, Statistic, Tooltip} from 'antd'
|
||||
import {t} from 'ttag'
|
||||
import {
|
||||
AimOutlined,
|
||||
CompassOutlined,
|
||||
DatabaseOutlined,
|
||||
FieldTimeOutlined,
|
||||
NotificationOutlined
|
||||
} from "@ant-design/icons";
|
||||
AimOutlined,
|
||||
CompassOutlined,
|
||||
DatabaseOutlined,
|
||||
FieldTimeOutlined,
|
||||
NotificationOutlined
|
||||
} from '@ant-design/icons'
|
||||
|
||||
export default function StatisticsPage() {
|
||||
|
||||
const [stats, setStats] = useState<Statistics>()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -20,101 +19,104 @@ export default function StatisticsPage() {
|
||||
|
||||
const totalDomainPurchase = (stats?.domainPurchased ?? 0) + (stats?.domainPurchaseFailed ?? 0)
|
||||
|
||||
const successRate = stats !== undefined ?
|
||||
(totalDomainPurchase === 0 ? undefined : stats.domainPurchased / totalDomainPurchase)
|
||||
const successRate = stats !== undefined
|
||||
? (totalDomainPurchase === 0 ? undefined : stats.domainPurchased / totalDomainPurchase)
|
||||
: undefined
|
||||
|
||||
return <>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
prefix={<CompassOutlined/>}
|
||||
title={t`RDAP queries`}
|
||||
value={stats?.rdapQueries}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Alerts sent`}
|
||||
prefix={<NotificationOutlined/>}
|
||||
value={stats?.alertSent}
|
||||
valueStyle={{color: 'violet'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Domain names in database`}
|
||||
prefix={<DatabaseOutlined/>}
|
||||
value={stats?.domainCountTotal}
|
||||
valueStyle={{color: 'orange'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Tracked domain names`}
|
||||
prefix={<AimOutlined/>}
|
||||
value={stats?.domainTracked}
|
||||
valueStyle={{color: 'violet'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Purchased domain names`}
|
||||
prefix={<FieldTimeOutlined/>}
|
||||
value={stats?.domainPurchased}
|
||||
valueStyle={{color: 'green'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Tooltip
|
||||
title={t`This value is based on the status code of the HTTP response from the providers following the domain order.`}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Success rate`}
|
||||
value={successRate === undefined ? '-' : successRate * 100}
|
||||
suffix='%'
|
||||
valueStyle={{color: successRate === undefined ? 'grey' : successRate >= 0.5 ? 'darkgreen' : 'orange'}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
<Row gutter={16} justify='center' align='middle'>
|
||||
{stats?.domainCount
|
||||
.sort((a, b) => b.domain - a.domain)
|
||||
.map(({domain, tld}) => <Col span={4}>
|
||||
return (
|
||||
<>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={`.${tld}`}
|
||||
value={domain}
|
||||
valueStyle={{color: 'darkorange'}}
|
||||
prefix={<CompassOutlined/>}
|
||||
title={t`RDAP queries`}
|
||||
value={stats?.rdapQueries}
|
||||
/>
|
||||
</Card>
|
||||
</Col>)}
|
||||
</Row>
|
||||
</>
|
||||
}
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Alerts sent`}
|
||||
prefix={<NotificationOutlined/>}
|
||||
value={stats?.alertSent}
|
||||
valueStyle={{color: 'violet'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Domain names in database`}
|
||||
prefix={<DatabaseOutlined/>}
|
||||
value={stats?.domainCountTotal}
|
||||
valueStyle={{color: 'orange'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Tracked domain names`}
|
||||
prefix={<AimOutlined/>}
|
||||
value={stats?.domainTracked}
|
||||
valueStyle={{color: 'violet'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Purchased domain names`}
|
||||
prefix={<FieldTimeOutlined/>}
|
||||
value={stats?.domainPurchased}
|
||||
valueStyle={{color: 'green'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card bordered={false}>
|
||||
<Tooltip
|
||||
title={t`This value is based on the status code of the HTTP response from the providers following the domain order.`}
|
||||
>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={t`Success rate`}
|
||||
value={successRate === undefined ? '-' : successRate * 100}
|
||||
suffix='%'
|
||||
valueStyle={{color: successRate === undefined ? 'grey' : successRate >= 0.5 ? 'darkgreen' : 'orange'}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
<Row gutter={16} justify='center' align='middle'>
|
||||
{stats?.domainCount
|
||||
.sort((a, b) => b.domain - a.domain)
|
||||
.map(({domain, tld}) => <Col key={tld} span={4}>
|
||||
<Card bordered={false}>
|
||||
<Statistic
|
||||
loading={stats === undefined}
|
||||
title={`.${tld}`}
|
||||
value={domain}
|
||||
valueStyle={{color: 'darkorange'}}
|
||||
/>
|
||||
</Card>
|
||||
</Col>)}
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import snarkdown from "snarkdown"
|
||||
import {Skeleton, Typography} from "antd";
|
||||
import axios from "axios";
|
||||
import {t} from "ttag";
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import snarkdown from 'snarkdown'
|
||||
import {Skeleton, Typography} from 'antd'
|
||||
import axios from 'axios'
|
||||
import {t} from 'ttag'
|
||||
|
||||
export default function TextPage({resource}: { resource: string }) {
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
@@ -12,18 +12,22 @@ export default function TextPage({resource}: { resource: string }) {
|
||||
setLoading(true)
|
||||
axios.get('/content/' + resource)
|
||||
.then(res => setMarkdown(res.data))
|
||||
.catch(err => {
|
||||
.catch(() => {
|
||||
console.error(`Please create the /public/content/${resource} file.`)
|
||||
setMarkdown(undefined)
|
||||
})
|
||||
.finally(() => setLoading(false))
|
||||
}, [resource])
|
||||
|
||||
return <Skeleton loading={loading} active>
|
||||
{markdown !== undefined ? <div
|
||||
dangerouslySetInnerHTML={{__html: snarkdown(markdown)}}></div> :
|
||||
<Typography.Text strong>
|
||||
{t`📝 Please create the /public/content/${resource} file.`}
|
||||
</Typography.Text>}
|
||||
</Skeleton>
|
||||
}
|
||||
return (
|
||||
<Skeleton loading={loading} active>
|
||||
{markdown !== undefined
|
||||
? <div
|
||||
dangerouslySetInnerHTML={{__html: snarkdown(markdown)}}
|
||||
/>
|
||||
: <Typography.Text strong>
|
||||
{t`📝 Please create the /public/content/${resource} file.`}
|
||||
</Typography.Text>}
|
||||
</Skeleton>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Card, Flex, Skeleton, Typography} from "antd";
|
||||
import {getUser, User} from "../utils/api";
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {Card, Flex, Skeleton, Typography} from 'antd'
|
||||
import {getUser, User} from '../utils/api'
|
||||
import {t} from 'ttag'
|
||||
|
||||
export default function UserPage() {
|
||||
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
getUser().then(setUser)
|
||||
}, [])
|
||||
|
||||
return <Skeleton loading={user === null} active>
|
||||
<Flex gap="middle" align="center" justify="center" vertical>
|
||||
<Card title={t`My Account`}>
|
||||
<Typography.Paragraph>
|
||||
{t`Username`} : {user?.email}
|
||||
</Typography.Paragraph>
|
||||
<Typography.Paragraph>
|
||||
{t`Roles`} : {user?.roles.join(',')}
|
||||
</Typography.Paragraph>
|
||||
</Card>
|
||||
</Flex>
|
||||
</Skeleton>
|
||||
}
|
||||
return (
|
||||
<Skeleton loading={user === null} active>
|
||||
<Flex gap='middle' align='center' justify='center' vertical>
|
||||
<Card title={t`My Account`}>
|
||||
<Typography.Paragraph>
|
||||
{t`Username`} : {user?.email}
|
||||
</Typography.Paragraph>
|
||||
<Typography.Paragraph>
|
||||
{t`Roles`} : {user?.roles.join(',')}
|
||||
</Typography.Paragraph>
|
||||
</Card>
|
||||
</Flex>
|
||||
</Skeleton>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Empty, Flex, FormProps, message, Skeleton} from "antd";
|
||||
import {Domain, getDomain} from "../../utils/api";
|
||||
import {AxiosError} from "axios"
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {Empty, Flex, FormProps, message, Skeleton} from 'antd'
|
||||
import {Domain, getDomain} from '../../utils/api'
|
||||
import {AxiosError} from 'axios'
|
||||
import {t} from 'ttag'
|
||||
import {DomainSearchBar, FieldType} from "../../components/search/DomainSearchBar";
|
||||
import {DomainResult} from "../../components/search/DomainResult";
|
||||
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
|
||||
import {useNavigate, useParams} from "react-router-dom";
|
||||
import {DomainSearchBar, FieldType} from '../../components/search/DomainSearchBar'
|
||||
import {DomainResult} from '../../components/search/DomainResult'
|
||||
import {showErrorAPI} from '../../utils/functions/showErrorAPI'
|
||||
import {useNavigate, useParams} from 'react-router-dom'
|
||||
|
||||
export default function DomainSearchPage() {
|
||||
const {query} = useParams()
|
||||
@@ -36,17 +36,21 @@ export default function DomainSearchPage() {
|
||||
onFinish({ldhName: query})
|
||||
}, [])
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
{contextHolder}
|
||||
<DomainSearchBar initialValue={query} onFinish={onFinish}/>
|
||||
return (
|
||||
<Flex gap='middle' align='center' justify='center' vertical>
|
||||
{contextHolder}
|
||||
<DomainSearchBar initialValue={query} onFinish={onFinish}/>
|
||||
|
||||
<Skeleton loading={domain === null} active>
|
||||
{
|
||||
domain &&
|
||||
(!domain.deleted ? <DomainResult domain={domain}/>
|
||||
: <Empty
|
||||
description={t`Although the domain exists in my database, it has been deleted from the WHOIS by its registrar.`}/>)
|
||||
}
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
}
|
||||
<Skeleton loading={domain === null} active>
|
||||
{
|
||||
(domain != null) &&
|
||||
(!domain.deleted
|
||||
? <DomainResult domain={domain}/>
|
||||
: <Empty
|
||||
description={t`Although the domain exists in my database, it has been deleted from the WHOIS by its registrar.`}
|
||||
/>)
|
||||
}
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from "react";
|
||||
import React from 'react'
|
||||
|
||||
export default function EntitySearchPage() {
|
||||
return <p>
|
||||
Not implemented
|
||||
</p>
|
||||
}
|
||||
return (
|
||||
<p>
|
||||
Not implemented
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import React from "react";
|
||||
import React from 'react'
|
||||
|
||||
export default function NameserverSearchPage() {
|
||||
return <p>
|
||||
Not implemented
|
||||
</p>
|
||||
}
|
||||
return (
|
||||
<p>
|
||||
Not implemented
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,41 +1,53 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Collapse, Divider, Table, Typography} from "antd";
|
||||
import {getTldList, Tld} from "../../utils/api";
|
||||
import React, {ReactElement, useEffect, useState} from 'react'
|
||||
import {Collapse, Divider, Table, Typography} from 'antd'
|
||||
import {getTldList, Tld} from '../../utils/api'
|
||||
import {t} from 'ttag'
|
||||
import {regionNames} from "../../i18n";
|
||||
import useBreakpoint from "../../hooks/useBreakpoint";
|
||||
import {ColumnType} from "antd/es/table";
|
||||
import punycode from "punycode/punycode";
|
||||
import {getCountryCode} from "../../utils/functions/getCountryCode";
|
||||
import {tldToEmoji} from "../../utils/functions/tldToEmoji";
|
||||
import {regionNames} from '../../i18n'
|
||||
import useBreakpoint from '../../hooks/useBreakpoint'
|
||||
import {ColumnType} from 'antd/es/table'
|
||||
import punycode from 'punycode/punycode'
|
||||
import {getCountryCode} from '../../utils/functions/getCountryCode'
|
||||
import {tldToEmoji} from '../../utils/functions/tldToEmoji'
|
||||
|
||||
const {Text, Paragraph} = Typography
|
||||
|
||||
type TldType = 'iTLD' | 'sTLD' | 'gTLD' | 'ccTLD'
|
||||
type FiltersType = { type: TldType, contractTerminated?: boolean, specification13?: boolean }
|
||||
|
||||
interface FiltersType {
|
||||
type: TldType,
|
||||
contractTerminated?: boolean,
|
||||
specification13?: boolean
|
||||
}
|
||||
|
||||
function TldTable(filters: FiltersType) {
|
||||
interface TableRow {
|
||||
key: string
|
||||
TLD: ReactElement
|
||||
Flag?: string
|
||||
Country?: string
|
||||
}
|
||||
|
||||
const sm = useBreakpoint('sm')
|
||||
const [dataTable, setDataTable] = useState<Tld[]>([])
|
||||
const [dataTable, setDataTable] = useState<TableRow[]>([])
|
||||
const [total, setTotal] = useState(0)
|
||||
|
||||
const fetchData = (params: FiltersType & { page: number, itemsPerPage: number }) => {
|
||||
getTldList(params).then((data) => {
|
||||
setTotal(data['hydra:totalItems'])
|
||||
setDataTable(data['hydra:member'].map((tld: Tld) => {
|
||||
|
||||
const rowData = {
|
||||
key: tld.tld,
|
||||
TLD: <Typography.Text code>{punycode.toUnicode(tld.tld)}</Typography.Text>
|
||||
}
|
||||
switch (filters.type) {
|
||||
const type = filters.type
|
||||
let countryName
|
||||
|
||||
switch (type) {
|
||||
case 'ccTLD':
|
||||
let countryName
|
||||
|
||||
try {
|
||||
countryName = regionNames.of(getCountryCode(tld.tld))
|
||||
} catch (e) {
|
||||
} catch {
|
||||
countryName = '-'
|
||||
}
|
||||
|
||||
@@ -60,98 +72,104 @@ function TldTable(filters: FiltersType) {
|
||||
fetchData({...filters, page: 1, itemsPerPage: 30})
|
||||
}, [])
|
||||
|
||||
let columns: ColumnType<any>[] = [
|
||||
let columns: Array<ColumnType<TableRow>> = [
|
||||
{
|
||||
title: t`TLD`,
|
||||
dataIndex: "TLD"
|
||||
dataIndex: 'TLD'
|
||||
}
|
||||
]
|
||||
|
||||
if (filters.type === 'ccTLD') columns = [...columns, {
|
||||
title: t`Flag`,
|
||||
dataIndex: "Flag",
|
||||
}, {
|
||||
title: t`Country`,
|
||||
dataIndex: "Country"
|
||||
}]
|
||||
if (filters.type === 'ccTLD') {
|
||||
columns = [...columns, {
|
||||
title: t`Flag`,
|
||||
dataIndex: 'Flag'
|
||||
}, {
|
||||
title: t`Country`,
|
||||
dataIndex: 'Country'
|
||||
}]
|
||||
}
|
||||
|
||||
if (filters.type === 'gTLD') columns = [...columns, {
|
||||
title: t`Registry Operator`,
|
||||
dataIndex: "Operator"
|
||||
}]
|
||||
if (filters.type === 'gTLD') {
|
||||
columns = [...columns, {
|
||||
title: t`Registry Operator`,
|
||||
dataIndex: 'Operator'
|
||||
}]
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={dataTable}
|
||||
pagination={{
|
||||
total,
|
||||
hideOnSinglePage: true,
|
||||
defaultPageSize: 30,
|
||||
onChange: (page, itemsPerPage) => {
|
||||
fetchData({...filters, page, itemsPerPage})
|
||||
}
|
||||
}}
|
||||
|
||||
return <Table
|
||||
columns={columns}
|
||||
dataSource={dataTable}
|
||||
pagination={{
|
||||
total,
|
||||
hideOnSinglePage: true,
|
||||
defaultPageSize: 30,
|
||||
onChange: (page, itemsPerPage) => {
|
||||
fetchData({...filters, page, itemsPerPage})
|
||||
}
|
||||
}}
|
||||
|
||||
{...(sm ? {scroll: {y: 'max-content'}} : {scroll: {y: 240}})}
|
||||
/>
|
||||
{...(sm ? {scroll: {y: 'max-content'}} : {scroll: {y: 240}})}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default function TldPage() {
|
||||
const sm = useBreakpoint('sm')
|
||||
|
||||
return <>
|
||||
<Paragraph>
|
||||
{t`This page presents all active TLDs in the root zone database.`}
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
{t`IANA provides the list of currently active TLDs, regardless of their type, and ICANN provides the list of gTLDs.
|
||||
return (
|
||||
<>
|
||||
<Paragraph>
|
||||
{t`This page presents all active TLDs in the root zone database.`}
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
{t`IANA provides the list of currently active TLDs, regardless of their type, and ICANN provides the list of gTLDs.
|
||||
In most cases, the two-letter ccTLD assigned to a country is made in accordance with the ISO 3166-1 standard.
|
||||
This data is updated every month. Three HTTP requests are needed for the complete update of TLDs in Domain Watchdog (two requests to IANA and one to ICANN).
|
||||
At the same time, the list of root RDAP servers is updated.`}
|
||||
</Paragraph>
|
||||
<Divider/>
|
||||
<Collapse
|
||||
accordion
|
||||
size={sm ? 'small' : 'large'}
|
||||
items={[
|
||||
{
|
||||
key: 'sTLD',
|
||||
label: t`Sponsored Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Top-level domains sponsored by specific organizations that set rules for registration and use, often related to particular interest groups or industries.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='sTLD'/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'gTLD',
|
||||
label: t`Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Generic top-level domains open to everyone, not restricted by specific criteria, representing various themes or industries.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='gTLD' contractTerminated={false} specification13={false}/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'ngTLD',
|
||||
label: t`Brand Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Generic top-level domains associated with specific brands, allowing companies to use their own brand names as domains.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='gTLD' contractTerminated={false} specification13={true}/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'ccTLD',
|
||||
label: t`Country-Code Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Top-level domains based on country codes, identifying websites according to their country of origin.`}</Text>
|
||||
<Divider/><TldTable type='ccTLD'/>
|
||||
</>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
</Paragraph>
|
||||
<Divider/>
|
||||
<Collapse
|
||||
accordion
|
||||
size={sm ? 'small' : 'large'}
|
||||
items={[
|
||||
{
|
||||
key: 'sTLD',
|
||||
label: t`Sponsored Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Top-level domains sponsored by specific organizations that set rules for registration and use, often related to particular interest groups or industries.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='sTLD'/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'gTLD',
|
||||
label: t`Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Generic top-level domains open to everyone, not restricted by specific criteria, representing various themes or industries.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='gTLD' contractTerminated={false} specification13={false}/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'ngTLD',
|
||||
label: t`Brand Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Generic top-level domains associated with specific brands, allowing companies to use their own brand names as domains.`}</Text>
|
||||
<Divider/>
|
||||
<TldTable type='gTLD' contractTerminated={false} specification13/>
|
||||
</>
|
||||
},
|
||||
{
|
||||
key: 'ccTLD',
|
||||
label: t`Country-Code Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>{t`Top-level domains based on country codes, identifying websites according to their country of origin.`}</Text>
|
||||
<Divider/><TldTable type='ccTLD'/>
|
||||
</>
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Card, Flex, Form, message, Skeleton} from "antd";
|
||||
import {t} from "ttag";
|
||||
import {Connector, getConnectors, postConnector} from "../../utils/api/connectors";
|
||||
import {ConnectorForm} from "../../components/tracking/connector/ConnectorForm";
|
||||
import {AxiosError} from "axios";
|
||||
import {ConnectorElement, ConnectorsList} from "../../components/tracking/connector/ConnectorsList";
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {Card, Flex, Form, message, Skeleton} from 'antd'
|
||||
import {t} from 'ttag'
|
||||
import {Connector, getConnectors, postConnector} from '../../utils/api/connectors'
|
||||
import {ConnectorForm} from '../../components/tracking/connector/ConnectorForm'
|
||||
import {AxiosError} from 'axios'
|
||||
import {ConnectorElement, ConnectorsList} from '../../components/tracking/connector/ConnectorsList'
|
||||
|
||||
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
|
||||
import {showErrorAPI} from '../../utils/functions/showErrorAPI'
|
||||
|
||||
export default function ConnectorPage() {
|
||||
const [form] = Form.useForm()
|
||||
@@ -14,7 +14,7 @@ export default function ConnectorPage() {
|
||||
const [connectors, setConnectors] = useState<ConnectorElement[] | null>()
|
||||
|
||||
const onCreateConnector = (values: Connector) => {
|
||||
postConnector(values).then((w) => {
|
||||
postConnector(values).then(() => {
|
||||
form.resetFields()
|
||||
refreshConnectors()
|
||||
messageApi.success(t`Connector created !`)
|
||||
@@ -23,7 +23,7 @@ export default function ConnectorPage() {
|
||||
})
|
||||
}
|
||||
|
||||
const refreshConnectors = () => getConnectors().then(c => {
|
||||
const refreshConnectors = async () => await getConnectors().then(c => {
|
||||
setConnectors(c['hydra:member'])
|
||||
}).catch((e: AxiosError) => {
|
||||
setConnectors(undefined)
|
||||
@@ -34,18 +34,17 @@ export default function ConnectorPage() {
|
||||
refreshConnectors()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Flex gap='middle' align='center' justify='center' vertical>
|
||||
<Card title={t`Create a Connector`} style={{width: '100%'}}>
|
||||
{contextHolder}
|
||||
<ConnectorForm form={form} onCreate={onCreateConnector}/>
|
||||
</Card>
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
<Card title={t`Create a Connector`} style={{width: '100%'}}>
|
||||
{contextHolder}
|
||||
<ConnectorForm form={form} onCreate={onCreateConnector}/>
|
||||
</Card>
|
||||
|
||||
|
||||
<Skeleton loading={connectors === undefined} active>
|
||||
{connectors && connectors.length > 0 &&
|
||||
<ConnectorsList connectors={connectors} onDelete={refreshConnectors}/>
|
||||
}
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
}
|
||||
<Skeleton loading={connectors === undefined} active>
|
||||
{(connectors != null) && connectors.length > 0 &&
|
||||
<ConnectorsList connectors={connectors} onDelete={refreshConnectors}/>}
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {TrackedDomainTable} from "../../components/tracking/watchlist/TrackedDomainTable";
|
||||
import React from "react";
|
||||
import {TrackedDomainTable} from '../../components/tracking/watchlist/TrackedDomainTable'
|
||||
import React from 'react'
|
||||
|
||||
export default function TrackedDomainPage() {
|
||||
return <TrackedDomainTable/>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,19 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Card, Divider, Flex, Form, message} from "antd";
|
||||
import {EventAction, getWatchlists, postWatchlist, putWatchlist} from "../../utils/api";
|
||||
import {AxiosError} from "axios";
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {Card, Divider, Flex, Form, message} from 'antd'
|
||||
import {getWatchlists, postWatchlist, putWatchlist, Watchlist} from '../../utils/api'
|
||||
import {AxiosError} from 'axios'
|
||||
import {t} from 'ttag'
|
||||
import {WatchlistForm} from "../../components/tracking/watchlist/WatchlistForm";
|
||||
import {WatchlistsList} from "../../components/tracking/watchlist/WatchlistsList";
|
||||
import {Connector, getConnectors} from "../../utils/api/connectors";
|
||||
import {WatchlistForm} from '../../components/tracking/watchlist/WatchlistForm'
|
||||
import {WatchlistsList} from '../../components/tracking/watchlist/WatchlistsList'
|
||||
import {Connector, getConnectors} from '../../utils/api/connectors'
|
||||
|
||||
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
|
||||
import {showErrorAPI} from '../../utils/functions/showErrorAPI'
|
||||
|
||||
|
||||
export type Watchlist = {
|
||||
interface FormValuesType {
|
||||
name?: string
|
||||
token: string,
|
||||
domains: { ldhName: string, deleted: boolean, status: string[] }[],
|
||||
triggers?: { event: EventAction, action: string }[],
|
||||
dsn?: string[]
|
||||
connector?: {
|
||||
id: string
|
||||
provider: string
|
||||
createdAt: string
|
||||
}
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
type FormValuesType = {
|
||||
name?: string
|
||||
domains: string[],
|
||||
domains: string[]
|
||||
triggers: string[]
|
||||
connector?: string,
|
||||
connector?: string
|
||||
dsn?: string[]
|
||||
}
|
||||
|
||||
@@ -52,14 +37,13 @@ const getRequestDataFromForm = (values: FormValuesType) => {
|
||||
}
|
||||
|
||||
export default function WatchlistPage() {
|
||||
|
||||
const [form] = Form.useForm()
|
||||
const [messageApi, contextHolder] = message.useMessage()
|
||||
const [watchlists, setWatchlists] = useState<Watchlist[]>()
|
||||
const [connectors, setConnectors] = useState<(Connector & { id: string })[]>()
|
||||
const [connectors, setConnectors] = useState<Array<Connector & { id: string }>>()
|
||||
|
||||
const onCreateWatchlist = (values: FormValuesType) => {
|
||||
postWatchlist(getRequestDataFromForm(values)).then((w) => {
|
||||
postWatchlist(getRequestDataFromForm(values)).then(() => {
|
||||
form.resetFields()
|
||||
refreshWatchlists()
|
||||
messageApi.success(t`Watchlist created !`)
|
||||
@@ -68,18 +52,18 @@ export default function WatchlistPage() {
|
||||
})
|
||||
}
|
||||
|
||||
const onUpdateWatchlist = async (values: FormValuesType & { token: string }) => putWatchlist({
|
||||
const onUpdateWatchlist = async (values: FormValuesType & { token: string }) => await putWatchlist({
|
||||
token: values.token,
|
||||
...getRequestDataFromForm(values)
|
||||
}
|
||||
).then((w) => {
|
||||
).then(() => {
|
||||
refreshWatchlists()
|
||||
messageApi.success(t`Watchlist updated !`)
|
||||
}).catch((e: AxiosError) => {
|
||||
throw showErrorAPI(e, messageApi)
|
||||
})
|
||||
|
||||
const refreshWatchlists = () => getWatchlists().then(w => {
|
||||
const refreshWatchlists = async () => await getWatchlists().then(w => {
|
||||
setWatchlists(w['hydra:member'])
|
||||
}).catch((e: AxiosError) => {
|
||||
setWatchlists(undefined)
|
||||
@@ -95,18 +79,20 @@ export default function WatchlistPage() {
|
||||
})
|
||||
}, [])
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
{contextHolder}
|
||||
<Card loading={connectors === undefined} title={t`Create a Watchlist`} style={{width: '100%'}}>
|
||||
{connectors &&
|
||||
<WatchlistForm form={form} onFinish={onCreateWatchlist} connectors={connectors} isCreation={true}/>
|
||||
}
|
||||
</Card>
|
||||
<Divider/>
|
||||
{connectors && watchlists && watchlists.length > 0 &&
|
||||
<WatchlistsList watchlists={watchlists} onDelete={refreshWatchlists}
|
||||
connectors={connectors}
|
||||
onUpdateWatchlist={onUpdateWatchlist}
|
||||
/>}
|
||||
</Flex>
|
||||
}
|
||||
return (
|
||||
<Flex gap='middle' align='center' justify='center' vertical>
|
||||
{contextHolder}
|
||||
<Card loading={connectors === undefined} title={t`Create a Watchlist`} style={{width: '100%'}}>
|
||||
{(connectors != null) &&
|
||||
<WatchlistForm form={form} onFinish={onCreateWatchlist} connectors={connectors} isCreation/>}
|
||||
</Card>
|
||||
<Divider/>
|
||||
{(connectors != null) && (watchlists != null) && watchlists.length > 0 &&
|
||||
<WatchlistsList
|
||||
watchlists={watchlists} onDelete={refreshWatchlists}
|
||||
connectors={connectors}
|
||||
onUpdateWatchlist={onUpdateWatchlist}
|
||||
/>}
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user