mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-17 17:55:42 +00:00
feat: add link on domain name tags
This commit is contained in:
parent
8d43290f0e
commit
d3adc4b4ef
@ -96,6 +96,7 @@ export default function App() {
|
|||||||
<Route path="/home" element={<TextPage resource='home.md'/>}/>
|
<Route path="/home" element={<TextPage resource='home.md'/>}/>
|
||||||
|
|
||||||
<Route path="/search/domain" element={<DomainSearchPage/>}/>
|
<Route path="/search/domain" element={<DomainSearchPage/>}/>
|
||||||
|
<Route path="/search/domain/:query" element={<DomainSearchPage/>}/>
|
||||||
<Route path="/search/entity" element={<EntitySearchPage/>}/>
|
<Route path="/search/entity" element={<EntitySearchPage/>}/>
|
||||||
<Route path="/search/nameserver" element={<NameserverSearchPage/>}/>
|
<Route path="/search/nameserver" element={<NameserverSearchPage/>}/>
|
||||||
<Route path="/search/tld" element={<TldPage/>}/>
|
<Route path="/search/tld" element={<TldPage/>}/>
|
||||||
|
|||||||
21
assets/components/tracking/DomainToTag.tsx
Normal file
21
assets/components/tracking/DomainToTag.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import {Tag} from "antd";
|
||||||
|
import {DeleteOutlined, ExclamationCircleOutlined} from "@ant-design/icons";
|
||||||
|
import punycode from "punycode/punycode";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export function DomainToTag({domain}: { domain: { ldhName: string, deleted: boolean, status: string[] } }) {
|
||||||
|
return <Link to={'/search/domain/' + domain.ldhName}>
|
||||||
|
<Tag
|
||||||
|
color={
|
||||||
|
domain.deleted ? 'magenta' :
|
||||||
|
domain.status.includes('redemption period') ? 'yellow' :
|
||||||
|
domain.status.includes('pending delete') ? 'volcano' : 'default'
|
||||||
|
}
|
||||||
|
icon={
|
||||||
|
domain.deleted ? <DeleteOutlined/> :
|
||||||
|
domain.status.includes('redemption period') ? <ExclamationCircleOutlined/> :
|
||||||
|
domain.status.includes('pending delete') ? <DeleteOutlined/> : null
|
||||||
|
}>{punycode.toUnicode(domain.ldhName)}</Tag>
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import {rdapStatusCodeDetailTranslation} from "../../../utils/functions/rdapTran
|
|||||||
import {eppStatusCodeToColor} from "../../../utils/functions/eppStatusCodeToColor";
|
import {eppStatusCodeToColor} from "../../../utils/functions/eppStatusCodeToColor";
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
import {ExceptionOutlined, MonitorOutlined} from '@ant-design/icons'
|
import {ExceptionOutlined, MonitorOutlined} from '@ant-design/icons'
|
||||||
|
import {DomainToTag} from "../DomainToTag";
|
||||||
|
|
||||||
|
|
||||||
export function TrackedDomainTable() {
|
export function TrackedDomainTable() {
|
||||||
@ -42,7 +43,7 @@ export function TrackedDomainTable() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
key: d.ldhName,
|
key: d.ldhName,
|
||||||
ldhName: d.ldhName,
|
ldhName: <DomainToTag domain={d}/>,
|
||||||
expirationDate: expirationDate ? new Date(expirationDate).toLocaleString() : '-',
|
expirationDate: expirationDate ? new Date(expirationDate).toLocaleString() : '-',
|
||||||
status: d.status.map(s => <Tooltip
|
status: d.status.map(s => <Tooltip
|
||||||
placement='bottomLeft'
|
placement='bottomLeft'
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import {Card, Divider, Space, Table, Tag, Tooltip} from "antd";
|
import {Card, Divider, Space, Table, Tag, Tooltip} from "antd";
|
||||||
import {DeleteOutlined, DisconnectOutlined, ExclamationCircleOutlined, LinkOutlined} from "@ant-design/icons";
|
import {DisconnectOutlined, LinkOutlined} from "@ant-design/icons";
|
||||||
import {t} from "ttag";
|
import {t} from "ttag";
|
||||||
import {ViewDiagramWatchlistButton} from "./diagram/ViewDiagramWatchlistButton";
|
import {ViewDiagramWatchlistButton} from "./diagram/ViewDiagramWatchlistButton";
|
||||||
import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
|
import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
|
||||||
import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
|
import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
|
||||||
import punycode from "punycode/punycode";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Watchlist} from "../../../pages/tracking/WatchlistPage";
|
import {Watchlist} from "../../../pages/tracking/WatchlistPage";
|
||||||
import {Connector} from "../../../utils/api/connectors";
|
import {Connector} from "../../../utils/api/connectors";
|
||||||
@ -13,6 +12,7 @@ import {CalendarWatchlistButton} from "./CalendarWatchlistButton";
|
|||||||
import {rdapEventDetailTranslation, rdapEventNameTranslation} from "../../../utils/functions/rdapTranslation";
|
import {rdapEventDetailTranslation, rdapEventNameTranslation} from "../../../utils/functions/rdapTranslation";
|
||||||
|
|
||||||
import {actionToColor} from "../../../utils/functions/actionToColor";
|
import {actionToColor} from "../../../utils/functions/actionToColor";
|
||||||
|
import {DomainToTag} from "../DomainToTag";
|
||||||
|
|
||||||
export function WatchlistCard({watchlist, onUpdateWatchlist, connectors, onDelete}: {
|
export function WatchlistCard({watchlist, onUpdateWatchlist, connectors, onDelete}: {
|
||||||
watchlist: Watchlist,
|
watchlist: Watchlist,
|
||||||
@ -78,17 +78,7 @@ export function WatchlistCard({watchlist, onUpdateWatchlist, connectors, onDelet
|
|||||||
pagination={false}
|
pagination={false}
|
||||||
style={{width: '100%'}}
|
style={{width: '100%'}}
|
||||||
dataSource={[{
|
dataSource={[{
|
||||||
domains: watchlist.domains.map(d => <Tag
|
domains: watchlist.domains.map(d => <DomainToTag domain={d}/>),
|
||||||
color={
|
|
||||||
d.deleted ? 'magenta' :
|
|
||||||
d.status.includes('redemption period') ? 'yellow' :
|
|
||||||
d.status.includes('pending delete') ? 'volcano' : 'default'
|
|
||||||
}
|
|
||||||
icon={
|
|
||||||
d.deleted ? <DeleteOutlined/> :
|
|
||||||
d.status.includes('redemption period') ? <ExclamationCircleOutlined/> :
|
|
||||||
d.status.includes('pending delete') ? <DeleteOutlined/> : null
|
|
||||||
}>{punycode.toUnicode(d.ldhName)}</Tag>),
|
|
||||||
events: watchlist.triggers?.filter(t => t.action === 'email')
|
events: watchlist.triggers?.filter(t => t.action === 'email')
|
||||||
.map(t => <Tooltip
|
.map(t => <Tooltip
|
||||||
title={t.event in rdapEventDetailTranslated ? rdapEventDetailTranslated[t.event as keyof typeof rdapEventDetailTranslated] : undefined}>
|
title={t.event in rdapEventDetailTranslated ? rdapEventDetailTranslated[t.event as keyof typeof rdapEventDetailTranslated] : undefined}>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, {useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import {Empty, Flex, FormProps, message, Skeleton} from "antd";
|
import {Empty, Flex, FormProps, message, Skeleton} from "antd";
|
||||||
import {Domain, getDomain} from "../../utils/api";
|
import {Domain, getDomain} from "../../utils/api";
|
||||||
import {AxiosError} from "axios"
|
import {AxiosError} from "axios"
|
||||||
@ -6,11 +6,14 @@ import {t} from 'ttag'
|
|||||||
import {DomainSearchBar, FieldType} from "../../components/search/DomainSearchBar";
|
import {DomainSearchBar, FieldType} from "../../components/search/DomainSearchBar";
|
||||||
import {DomainResult} from "../../components/search/DomainResult";
|
import {DomainResult} from "../../components/search/DomainResult";
|
||||||
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
|
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
|
||||||
|
import {useParams} from "react-router-dom";
|
||||||
|
|
||||||
export default function DomainSearchPage() {
|
export default function DomainSearchPage() {
|
||||||
const [domain, setDomain] = useState<Domain | null>()
|
const [domain, setDomain] = useState<Domain | null>()
|
||||||
const [messageApi, contextHolder] = message.useMessage()
|
const [messageApi, contextHolder] = message.useMessage()
|
||||||
|
|
||||||
|
const {query} = useParams()
|
||||||
|
|
||||||
const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
|
const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
|
||||||
setDomain(null)
|
setDomain(null)
|
||||||
getDomain(values.ldhName).then(d => {
|
getDomain(values.ldhName).then(d => {
|
||||||
@ -22,6 +25,10 @@ export default function DomainSearchPage() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (query) onFinish({ldhName: query})
|
||||||
|
}, [query])
|
||||||
|
|
||||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
<DomainSearchBar onFinish={onFinish}/>
|
<DomainSearchBar onFinish={onFinish}/>
|
||||||
|
|||||||
@ -83,7 +83,7 @@ readonly class RDAPService
|
|||||||
];
|
];
|
||||||
|
|
||||||
/* @see https://www.iana.org/assignments/registrar-ids/registrar-ids.xhtml */
|
/* @see https://www.iana.org/assignments/registrar-ids/registrar-ids.xhtml */
|
||||||
public const ENTITY_IANA_RESERVED_IDS = [
|
public const IANA_RESERVED_IDS = [
|
||||||
1, 3, 8, 119, 365, 376, 9994, 9995, 9996, 9997, 9998, 9999, 10009, 4000001, 8888888,
|
1, 3, 8, 119, 365, 376, 9994, 9995, 9996, 9997, 9998, 9999, 10009, 4000001, 8888888,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -509,7 +509,7 @@ readonly class RDAPService
|
|||||||
|
|
||||||
$entity->setHandle($rdapEntity['handle']);
|
$entity->setHandle($rdapEntity['handle']);
|
||||||
|
|
||||||
if (array_key_exists('vcardArray', $rdapEntity) && !in_array($rdapEntity['handle'], self::ENTITY_IANA_RESERVED_IDS)) {
|
if (array_key_exists('vcardArray', $rdapEntity) && !in_array($rdapEntity['handle'], self::IANA_RESERVED_IDS)) {
|
||||||
if (empty($entity->getJCard())) {
|
if (empty($entity->getJCard())) {
|
||||||
$entity->setJCard($rdapEntity['vcardArray']);
|
$entity->setJCard($rdapEntity['vcardArray']);
|
||||||
} else {
|
} else {
|
||||||
@ -524,7 +524,7 @@ readonly class RDAPService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isIANAid || !array_key_exists('events', $rdapEntity) || in_array($rdapEntity['handle'], self::ENTITY_IANA_RESERVED_IDS)) {
|
if ($isIANAid || !array_key_exists('events', $rdapEntity) || in_array($rdapEntity['handle'], self::IANA_RESERVED_IDS)) {
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,34 +3,34 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
||||||
|
|
||||||
#: assets/App.tsx:122
|
#: assets/App.tsx:123
|
||||||
msgid "TOS"
|
msgid "TOS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/App.tsx:123
|
#: assets/App.tsx:124
|
||||||
msgid "Privacy Policy"
|
msgid "Privacy Policy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/App.tsx:124
|
#: assets/App.tsx:125
|
||||||
msgid "FAQ"
|
msgid "FAQ"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/App.tsx:127
|
#: assets/App.tsx:128
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/App.tsx:130
|
#: assets/App.tsx:131
|
||||||
#, javascript-format
|
#, javascript-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"${ ProjectLink } is an open source project distributed under the ${ "
|
"${ ProjectLink } is an open source project distributed under the ${ "
|
||||||
"LicenseLink } license."
|
"LicenseLink } license."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/App.tsx:143
|
#: assets/App.tsx:144
|
||||||
msgid "Official git repository"
|
msgid "Official git repository"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/App.tsx:146
|
#: assets/App.tsx:147
|
||||||
msgid "Submit an issue"
|
msgid "Submit an issue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ msgid "Search"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/Sider.tsx:39
|
#: assets/components/Sider.tsx:39
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:68
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:69
|
||||||
msgid "Domain"
|
msgid "Domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -367,54 +367,54 @@ msgstr ""
|
|||||||
msgid "Watchlist Entity Diagram"
|
msgid "Watchlist Entity Diagram"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:37
|
#: assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx:42
|
||||||
msgid "Registry"
|
msgid "Registry"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:30
|
#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:37
|
||||||
#, javascript-format
|
#, javascript-format
|
||||||
msgid ".${ tld.tld } Registry"
|
msgid ".${ tld.tld } Registry"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:14
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:15
|
||||||
msgid ""
|
msgid ""
|
||||||
"At least one domain name is in redemption period and will potentially be "
|
"At least one domain name is in redemption period and will potentially be "
|
||||||
"deleted soon"
|
"deleted soon"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:19
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:20
|
||||||
msgid ""
|
msgid ""
|
||||||
"At least one domain name is pending deletion and will soon become available "
|
"At least one domain name is pending deletion and will soon become available "
|
||||||
"for registration again"
|
"for registration again"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:72
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:73
|
||||||
msgid "Expiration date"
|
msgid "Expiration date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:85
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:86
|
||||||
msgid "Updated at"
|
msgid "Updated at"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:92
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:93
|
||||||
msgid "Status"
|
msgid "Status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:110
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:111
|
||||||
msgid "No tracked domain names were found, please create your first Watchlist"
|
msgid "No tracked domain names were found, please create your first Watchlist"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:118
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:119
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please note that this table does not include domain names marked as expired "
|
"Please note that this table does not include domain names marked as expired "
|
||||||
"or those with an unknown expiration date"
|
"or those with an unknown expiration date"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:122
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:123
|
||||||
msgid "At least one domain name you are tracking requires special attention"
|
msgid "At least one domain name you are tracking requires special attention"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:127
|
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:128
|
||||||
msgid "The domain names below are subject to special monitoring"
|
msgid "The domain names below are subject to special monitoring"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -515,11 +515,11 @@ msgstr ""
|
|||||||
msgid "Sorry, the page you visited does not exist."
|
msgid "Sorry, the page you visited does not exist."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:18
|
#: assets/pages/search/DomainSearchPage.tsx:21
|
||||||
msgid "Found !"
|
msgid "Found !"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:34
|
#: assets/pages/search/DomainSearchPage.tsx:41
|
||||||
msgid ""
|
msgid ""
|
||||||
"Although the domain exists in my database, it has been deleted from the "
|
"Although the domain exists in my database, it has been deleted from the "
|
||||||
"WHOIS by its registrar."
|
"WHOIS by its registrar."
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user