mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-18 02:05:36 +00:00
feat: add options column on Domain table
This commit is contained in:
parent
e9c43b3b79
commit
bc9bef36bd
@ -10,7 +10,8 @@ import {regionNames} from '../../i18n'
|
||||
import {getCountryCode} from '../../utils/functions/getCountryCode'
|
||||
import {DomainLifecycleSteps} from './DomainLifecycleSteps'
|
||||
import {BankOutlined, KeyOutlined, SafetyCertificateOutlined} from '@ant-design/icons'
|
||||
import {statusToTag} from '../tracking/StatusToTag'
|
||||
import {statusToTag} from '../../utils/functions/StatusToTag'
|
||||
import {isDomainLocked} from "../../utils/functions/isDomainLocked"
|
||||
|
||||
export function DomainResult({domain}: { domain: Domain }) {
|
||||
const {tld, events} = domain
|
||||
@ -18,10 +19,6 @@ export function DomainResult({domain}: { domain: Domain }) {
|
||||
const clientStatus = domain.status.filter(s => s.startsWith('client'))
|
||||
const serverStatus = domain.status.filter(s => !clientStatus.includes(s))
|
||||
|
||||
const isDomainLocked = (type: 'client' | 'server'): boolean =>
|
||||
(domain.status.includes(type + ' update prohibited') && domain.status.includes(type + ' delete prohibited')) ||
|
||||
domain.status.includes(type + ' transfer prohibited')
|
||||
|
||||
return (
|
||||
<Space direction='vertical' size='middle' style={{width: '100%'}}>
|
||||
|
||||
@ -60,7 +57,7 @@ export function DomainResult({domain}: { domain: Domain }) {
|
||||
title={t`Registry-level protection, ensuring the highest level of security by preventing unauthorized, unwanted, or accidental changes to the domain name at the registry level`}
|
||||
>
|
||||
<Tag
|
||||
bordered={false} color={isDomainLocked('server') ? 'green' : 'default'}
|
||||
bordered={false} color={isDomainLocked(domain.status, 'server') ? 'green' : 'default'}
|
||||
icon={<SafetyCertificateOutlined
|
||||
style={{fontSize: '16px'}}
|
||||
/>}
|
||||
@ -71,7 +68,7 @@ export function DomainResult({domain}: { domain: Domain }) {
|
||||
title={t`Registrar-level protection, safeguarding the domain from unauthorized, unwanted, or accidental changes through registrar controls`}
|
||||
>
|
||||
<Tag
|
||||
bordered={false} color={isDomainLocked('client') ? 'green' : 'default'}
|
||||
bordered={false} color={isDomainLocked(domain.status, 'client') ? 'green' : 'default'}
|
||||
icon={<BankOutlined
|
||||
style={{fontSize: '16px'}}
|
||||
/>}
|
||||
|
||||
@ -1,15 +1,22 @@
|
||||
import type {ReactElement} from 'react'
|
||||
import React, { useEffect, useState} from 'react'
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import type {Domain} from '../../../utils/api'
|
||||
import { getTrackedDomainList} from '../../../utils/api'
|
||||
import {Button, Empty, Result, Skeleton, Table, Tag, Tooltip} from 'antd'
|
||||
import {getTrackedDomainList} from '../../../utils/api'
|
||||
import {Button, Empty, Flex, Result, Skeleton, Table, Tag, Tooltip} from 'antd'
|
||||
import {t} from 'ttag'
|
||||
import type {ColumnType} from 'antd/es/table'
|
||||
import {rdapStatusCodeDetailTranslation} from '../../../utils/functions/rdapTranslation'
|
||||
import {eppStatusCodeToColor} from '../../../utils/functions/eppStatusCodeToColor'
|
||||
import {Link} from 'react-router-dom'
|
||||
import {ExceptionOutlined, MonitorOutlined} from '@ant-design/icons'
|
||||
import {DomainToTag} from '../DomainToTag'
|
||||
import {
|
||||
BankOutlined,
|
||||
ExceptionOutlined,
|
||||
KeyOutlined,
|
||||
MonitorOutlined,
|
||||
SafetyCertificateOutlined
|
||||
} from '@ant-design/icons'
|
||||
import {DomainToTag} from '../../../utils/functions/DomainToTag'
|
||||
import {isDomainLocked} from "../../../utils/functions/isDomainLocked"
|
||||
|
||||
export function TrackedDomainTable() {
|
||||
const REDEMPTION_NOTICE = (
|
||||
@ -34,7 +41,7 @@ export function TrackedDomainTable() {
|
||||
expirationDate: string
|
||||
status: ReactElement[]
|
||||
updatedAt: string
|
||||
domain: Domain
|
||||
rawDomain: Domain
|
||||
}
|
||||
|
||||
const [dataTable, setDataTable] = useState<TableRow[]>([])
|
||||
@ -70,7 +77,27 @@ export function TrackedDomainTable() {
|
||||
</Tooltip>
|
||||
),
|
||||
updatedAt: new Date(d.updatedAt).toLocaleString(),
|
||||
domain: d
|
||||
rawDomain: d,
|
||||
options: <Flex gap='4px 0' wrap>
|
||||
<Tooltip title={t`Registry Lock`}>
|
||||
<Tag
|
||||
bordered={false} color={isDomainLocked(d.status, 'server') ? 'green' : 'default'}
|
||||
icon={<SafetyCertificateOutlined/>}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t`Registrar Lock`}>
|
||||
<Tag
|
||||
bordered={false} color={isDomainLocked(d.status, 'client') ? 'green' : 'default'}
|
||||
icon={<BankOutlined/>}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Tooltip title={t`DNSSEC`}>
|
||||
<Tag
|
||||
bordered={false} color={d.delegationSigned ? 'green' : 'default'}
|
||||
icon={<KeyOutlined/>}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
}
|
||||
}))
|
||||
setSpecialNotice(notices)
|
||||
@ -82,36 +109,47 @@ export function TrackedDomainTable() {
|
||||
}, [])
|
||||
|
||||
interface RecordType {
|
||||
domain: Domain
|
||||
rawDomain: Domain
|
||||
}
|
||||
|
||||
const columns: Array<ColumnType<RecordType>> = [
|
||||
{
|
||||
title: t`Domain`,
|
||||
dataIndex: 'ldhName'
|
||||
dataIndex: 'ldhName',
|
||||
width: '30%',
|
||||
align: 'left'
|
||||
},
|
||||
{
|
||||
title: t`Options`,
|
||||
dataIndex: 'options',
|
||||
width: '10%',
|
||||
},
|
||||
{
|
||||
title: t`Expiration date`,
|
||||
dataIndex: 'expirationDate',
|
||||
sorter: (a: RecordType, b: RecordType) => {
|
||||
const expirationDate1 = a.domain.events.find(e => e.action === 'expiration' && !e.deleted)?.date
|
||||
const expirationDate2 = b.domain.events.find(e => e.action === 'expiration' && !e.deleted)?.date
|
||||
const expirationDate1 = a.rawDomain.events.find(e => e.action === 'expiration' && !e.deleted)?.date
|
||||
const expirationDate2 = b.rawDomain.events.find(e => e.action === 'expiration' && !e.deleted)?.date
|
||||
|
||||
if (expirationDate1 === undefined || expirationDate2 === undefined) return 0
|
||||
return new Date(expirationDate1).getTime() - new Date(expirationDate2).getTime()
|
||||
}
|
||||
},
|
||||
width: '15%'
|
||||
},
|
||||
|
||||
{
|
||||
title: t`Updated at`,
|
||||
dataIndex: 'updatedAt',
|
||||
sorter: (a: RecordType, b: RecordType) => new Date(a.domain.updatedAt).getTime() - new Date(b.domain.updatedAt).getTime()
|
||||
responsive: ['md'],
|
||||
sorter: (a: RecordType, b: RecordType) => new Date(a.rawDomain.updatedAt).getTime() - new Date(b.rawDomain.updatedAt).getTime(),
|
||||
width: '15%'
|
||||
},
|
||||
{
|
||||
title: t`Status`,
|
||||
dataIndex: 'status',
|
||||
responsive: ['md'],
|
||||
showSorterTooltip: {target: 'full-header'},
|
||||
filters: [...new Set(dataTable.map((d: RecordType) => d.domain.status).flat())].map(s => ({
|
||||
filters: [...new Set(dataTable.map((d: RecordType) => d.rawDomain.status).flat())].map(s => ({
|
||||
text: <Tooltip
|
||||
placement='bottomLeft'
|
||||
title={rdapStatusCodeDetailTranslated[s as keyof typeof rdapStatusCodeDetailTranslated] || undefined}
|
||||
@ -120,55 +158,50 @@ export function TrackedDomainTable() {
|
||||
</Tooltip>,
|
||||
value: s
|
||||
})),
|
||||
onFilter: (value, record: RecordType) => record.domain.status.includes(value as string)
|
||||
onFilter: (value, record: RecordType) => record.rawDomain.status.includes(value as string),
|
||||
width: '30%'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<>
|
||||
{
|
||||
total === 0
|
||||
? <Empty
|
||||
description={t`No tracked domain names were found, please create your first Watchlist`}
|
||||
>
|
||||
<Link to='/tracking/watchlist'>
|
||||
<Button type='primary'>Create Now</Button>
|
||||
</Link>
|
||||
</Empty>
|
||||
: <Skeleton loading={total === undefined}>
|
||||
<Result
|
||||
style={{paddingTop: 0}}
|
||||
subTitle={t`Please note that this table does not include domain names marked as expired or those with an unknown expiration date`}
|
||||
{...(specialNotice.length > 0
|
||||
? {
|
||||
icon: <ExceptionOutlined/>,
|
||||
status: 'warning',
|
||||
title: t`At least one domain name you are tracking requires special attention`,
|
||||
extra: specialNotice
|
||||
}
|
||||
: {
|
||||
icon: <MonitorOutlined/>,
|
||||
status: 'info',
|
||||
title: t`The domain names below are subject to special monitoring`
|
||||
})}
|
||||
/>
|
||||
return total === 0
|
||||
? <Empty
|
||||
description={t`No tracked domain names were found, please create your first Watchlist`}
|
||||
>
|
||||
<Link to='/tracking/watchlist'>
|
||||
<Button type='primary'>Create Now</Button>
|
||||
</Link>
|
||||
</Empty>
|
||||
: <Skeleton loading={total === undefined}>
|
||||
<Result
|
||||
style={{paddingTop: 0}}
|
||||
subTitle={t`Please note that this table does not include domain names marked as expired or those with an unknown expiration date`}
|
||||
{...(specialNotice.length > 0
|
||||
? {
|
||||
icon: <ExceptionOutlined/>,
|
||||
status: 'warning',
|
||||
title: t`At least one domain name you are tracking requires special attention`,
|
||||
extra: specialNotice
|
||||
}
|
||||
: {
|
||||
icon: <MonitorOutlined/>,
|
||||
status: 'info',
|
||||
title: t`The domain names below are subject to special monitoring`
|
||||
})}
|
||||
/>
|
||||
|
||||
<Table
|
||||
loading={total === undefined}
|
||||
columns={columns}
|
||||
dataSource={dataTable}
|
||||
pagination={{
|
||||
total,
|
||||
hideOnSinglePage: true,
|
||||
defaultPageSize: 30,
|
||||
onChange: (page, itemsPerPage) => {
|
||||
fetchData({page, itemsPerPage})
|
||||
}
|
||||
}}
|
||||
scroll={{y: '50vh'}}
|
||||
/>
|
||||
</Skeleton>
|
||||
}
|
||||
</>
|
||||
)
|
||||
<Table
|
||||
loading={total === undefined}
|
||||
columns={columns}
|
||||
dataSource={dataTable}
|
||||
pagination={{
|
||||
total,
|
||||
hideOnSinglePage: true,
|
||||
defaultPageSize: 30,
|
||||
onChange: (page, itemsPerPage) => {
|
||||
fetchData({page, itemsPerPage})
|
||||
}
|
||||
}}
|
||||
scroll={{y: '50vh'}}
|
||||
/>
|
||||
</Skeleton>
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import {CalendarWatchlistButton} from './CalendarWatchlistButton'
|
||||
import {rdapEventDetailTranslation, rdapEventNameTranslation} from '../../../utils/functions/rdapTranslation'
|
||||
|
||||
import {actionToColor} from '../../../utils/functions/actionToColor'
|
||||
import {DomainToTag} from '../DomainToTag'
|
||||
import {DomainToTag} from '../../../utils/functions/DomainToTag'
|
||||
import type {Watchlist} from '../../../utils/api'
|
||||
|
||||
export function WatchlistCard({watchlist, onUpdateWatchlist, connectors, onDelete}: {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {Tag, Tooltip} from 'antd'
|
||||
import {eppStatusCodeToColor} from '../../utils/functions/eppStatusCodeToColor'
|
||||
import {eppStatusCodeToColor} from './eppStatusCodeToColor'
|
||||
import React from 'react'
|
||||
import {rdapStatusCodeDetailTranslation} from '../../utils/functions/rdapTranslation'
|
||||
import {rdapStatusCodeDetailTranslation} from './rdapTranslation'
|
||||
|
||||
export function statusToTag(s: string) {
|
||||
const rdapStatusCodeDetailTranslated = rdapStatusCodeDetailTranslation()
|
||||
3
assets/utils/functions/isDomainLocked.ts
Normal file
3
assets/utils/functions/isDomainLocked.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const isDomainLocked = (status: string[], type: 'client' | 'server'): boolean =>
|
||||
(status.includes(type + ' update prohibited') && status.includes(type + ' delete prohibited')) ||
|
||||
status.includes(type + ' transfer prohibited')
|
||||
@ -118,7 +118,7 @@ class Domain
|
||||
private Collection $domainStatuses;
|
||||
|
||||
#[ORM\Column(nullable: false)]
|
||||
#[Groups(['domain:item'])]
|
||||
#[Groups(['domain:item', 'domain:list'])]
|
||||
private ?bool $delegationSigned = null;
|
||||
|
||||
private const IMPORTANT_EVENTS = [EventAction::Deletion->value, EventAction::Expiration->value];
|
||||
|
||||
@ -101,46 +101,49 @@ msgstr ""
|
||||
msgid "Pending Delete"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:60
|
||||
#: assets/components/search/DomainResult.tsx:57
|
||||
msgid ""
|
||||
"Registry-level protection, ensuring the highest level of security by "
|
||||
"preventing unauthorized, unwanted, or accidental changes to the domain name "
|
||||
"at the registry level"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:67
|
||||
#: assets/components/search/DomainResult.tsx:64
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:82
|
||||
msgid "Registry Lock"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:71
|
||||
#: assets/components/search/DomainResult.tsx:68
|
||||
msgid ""
|
||||
"Registrar-level protection, safeguarding the domain from unauthorized, "
|
||||
"unwanted, or accidental changes through registrar controls"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:78
|
||||
#: assets/components/search/DomainResult.tsx:75
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:88
|
||||
msgid "Registrar Lock"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:82
|
||||
#: assets/components/search/DomainResult.tsx:79
|
||||
msgid ""
|
||||
"DNSSEC secures DNS by adding cryptographic signatures to DNS records, "
|
||||
"ensuring authenticity and integrity of responses"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:87
|
||||
#: assets/components/search/DomainResult.tsx:84
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:94
|
||||
msgid "DNSSEC"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:93
|
||||
#: assets/components/search/DomainResult.tsx:90
|
||||
msgid "EPP Status Codes"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:101
|
||||
#: assets/components/search/DomainResult.tsx:98
|
||||
msgid "Timeline"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/search/DomainResult.tsx:108
|
||||
#: assets/components/search/DomainResult.tsx:105
|
||||
msgid "Entities"
|
||||
msgstr ""
|
||||
|
||||
@ -158,7 +161,7 @@ msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/Sider.tsx:41
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:90
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:117
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
@ -410,45 +413,49 @@ msgstr ""
|
||||
msgid ".${ tld.tld } Registry"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:17
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:24
|
||||
msgid ""
|
||||
"At least one domain name is in redemption period and will potentially be "
|
||||
"deleted soon"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:25
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:32
|
||||
msgid ""
|
||||
"At least one domain name is pending deletion and will soon become available "
|
||||
"for registration again"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:94
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:123
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:128
|
||||
msgid "Expiration date"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:106
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:141
|
||||
msgid "Updated at"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:111
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:148
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:132
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:168
|
||||
msgid "No tracked domain names were found, please create your first Watchlist"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:141
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:177
|
||||
msgid ""
|
||||
"Please note that this table does not include domain names marked as expired "
|
||||
"or those with an unknown expiration date"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:146
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:182
|
||||
msgid "At least one domain name you are tracking requires special attention"
|
||||
msgstr ""
|
||||
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:152
|
||||
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:188
|
||||
msgid "The domain names below are subject to special monitoring"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user