refactor: move functions

This commit is contained in:
Maël Gangloff
2024-08-22 01:44:50 +02:00
parent 7ece681d73
commit 5ae0b836a5
25 changed files with 244 additions and 215 deletions

View File

@@ -4,7 +4,8 @@ import React, {useContext, useEffect} from "react";
import {getUser, login} from "../utils/api";
import {AuthenticatedContext} from "../pages/LoginPage";
import {useNavigate} from "react-router-dom";
import {showErrorAPI} from "../utils";
import {showErrorAPI} from "../utils/functions/showErrorAPI";
type FieldType = {

View File

@@ -3,7 +3,8 @@ import {t} from "ttag";
import React, {useState} from "react";
import {register} from "../utils/api";
import {useNavigate} from "react-router-dom";
import {showErrorAPI} from "../utils";
import {showErrorAPI} from "../utils/functions/showErrorAPI";
type FieldType = {

View File

@@ -6,19 +6,30 @@ import {DomainDiagram} from "./DomainDiagram";
import React from "react";
import {Domain} from "../../utils/api";
import {rdapStatusCodeDetailTranslation} from "./rdapTranslation";
import {regionNames} from "../../i18n";
import {getCountryCode} from "../../utils/functions/getCountryCode";
export function DomainResult({domain}: { domain: Domain }) {
const rdapStatusCodeDetailTranslated = rdapStatusCodeDetailTranslation()
const {tld} = domain
return <Space direction="vertical" size="middle" style={{width: '100%'}}>
<Badge.Ribbon text={`.${domain.tld.tld.toUpperCase()} (${domain.tld.type})`}
<Badge.Ribbon text={
<Tooltip
title={tld.type === 'ccTLD' ? regionNames.of(getCountryCode(tld.tld)) : tld.type === 'gTLD' ? tld?.registryOperator : undefined}>
{`.${domain.tld.tld.toUpperCase()} (${tld.type})`}
</Tooltip>
}
color={
domain.tld.type === 'ccTLD' ? 'purple' :
(domain.tld.type === 'gTLD' && domain.tld.specification13) ? "volcano" :
domain.tld.type === 'gTLD' ? "green"
tld.type === 'ccTLD' ? 'purple' :
(tld.type === 'gTLD' && tld.specification13) ? "volcano" :
tld.type === 'gTLD' ? "green"
: "cyan"
}>
<Card title={<Space>
{domain.ldhName}{domain.handle && <Typography.Text code>{domain.handle}</Typography.Text>}
</Space>}

View File

@@ -2,7 +2,10 @@ import {List, Tag, Tooltip} from "antd";
import React from "react";
import {Domain} from "../../utils/api";
import {rdapRoleDetailTranslation, rdapRoleTranslation} from "./rdapTranslation";
import {entityToName, rolesToColor, roleToAvatar, sortDomainEntities} from "../../utils";
import {roleToAvatar} from "../../utils/functions/roleToAvatar";
import {rolesToColor} from "../../utils/functions/rolesToColor";
import {entityToName} from "../../utils/functions/entityToName";
import {sortDomainEntities} from "../../utils/functions/sortDomainEntities";
export function EntitiesList({domain}: { domain: Domain }) {

View File

@@ -3,7 +3,8 @@ import React from "react";
import {Domain} from "../../utils/api";
import useBreakpoint from "../../hooks/useBreakpoint";
import {rdapEventDetailTranslation, rdapEventNameTranslation} from "./rdapTranslation";
import {actionToColor, actionToIcon} from "../../utils";
import {actionToColor} from "../../utils/functions/actionToColor";
import {actionToIcon} from "../../utils/functions/actionToIcon";
export function EventTimeline({domain}: { domain: Domain }) {
const sm = useBreakpoint('sm')

View File

@@ -11,7 +11,8 @@ import {Connector} from "../../../utils/api/connectors";
import useBreakpoint from "../../../hooks/useBreakpoint";
import {CalendarWatchlistButton} from "./CalendarWatchlistButton";
import {rdapEventDetailTranslation, rdapEventNameTranslation} from "../../search/rdapTranslation";
import {actionToColor} from "../../../utils";
import {actionToColor} from "../../../utils/functions/actionToColor";
export function WatchlistCard({watchlist, onUpdateWatchlist, connectors, onDelete}: {
watchlist: Watchlist,

View File

@@ -4,7 +4,8 @@ import {ApiOutlined, MinusCircleOutlined, PlusOutlined} from "@ant-design/icons"
import React from "react";
import {Connector} from "../../../utils/api/connectors";
import {rdapEventDetailTranslation, rdapEventNameTranslation} from "../../search/rdapTranslation";
import {actionToColor, actionToIcon} from "../../../utils";
import {actionToColor} from "../../../utils/functions/actionToColor";
import {actionToIcon} from "../../../utils/functions/actionToIcon";
type TagRender = SelectProps['tagRender'];

View File

@@ -26,7 +26,7 @@ export function ViewDiagramWatchlistButton({token}: { token: string }) {
if (!open) return
setLoading(true)
getWatchlist(token).then(w => {
const e = getLayoutedElements(watchlistToNodes(w), watchlistToEdges(w))
const e = getLayoutedElements(watchlistToNodes(w, true), watchlistToEdges(w, true))
setNodes(e.nodes)
setEdges(e.edges)
}).catch(() => setOpen(false)).finally(() => setLoading(false))

View File

@@ -1,7 +1,8 @@
import {Domain, Watchlist} from "../../../../utils/api";
import {rdapRoleTranslation} from "../../../search/rdapTranslation";
import {t} from "ttag";
import {rolesToColor} from "../../../../utils";
import {rolesToColor} from "../../../../utils/functions/rolesToColor";
export function domainEntitiesToEdges(d: Domain, withRegistrar = false) {
const rdapRoleTranslated = rdapRoleTranslation()

View File

@@ -1,7 +1,8 @@
import {Domain, Nameserver, Tld, Watchlist} from "../../../../utils/api";
import React from "react";
import {t} from 'ttag'
import {entityToName} from "../../../../utils";
import {entityToName} from "../../../../utils/functions/entityToName";
export const domainToNode = (d: Domain) => ({
id: d.ldhName,

View File

@@ -6,28 +6,14 @@ 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 }
const toEmoji = (tld: string) => {
if (tld.startsWith('xn--')) return '-'
return 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.toUpperCase()
}
function TldTable(filters: FiltersType) {
const sm = useBreakpoint('sm')
@@ -55,7 +41,7 @@ function TldTable(filters: FiltersType) {
return {
...rowData,
Flag: toEmoji(tld.tld),
Flag: tldToEmoji(tld.tld),
Country: countryName
}
case 'gTLD':

View File

@@ -4,8 +4,8 @@ import {Domain, getDomain} from "../../utils/api";
import {AxiosError} from "axios"
import {t} from 'ttag'
import {DomainSearchBar, FieldType} from "../../components/search/DomainSearchBar";
import {showErrorAPI} from "../../utils";
import {DomainResult} from "../../components/search/DomainResult";
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
export default function DomainSearchPage() {
const [domain, setDomain] = useState<Domain | null>()

View File

@@ -5,7 +5,8 @@ import {Connector, getConnectors, postConnector} from "../../utils/api/connector
import {ConnectorForm} from "../../components/tracking/connector/ConnectorForm";
import {AxiosError} from "axios";
import {ConnectorElement, ConnectorsList} from "../../components/tracking/connector/ConnectorsList";
import {showErrorAPI} from "../../utils";
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
export default function ConnectorsPage() {
const [form] = Form.useForm()

View File

@@ -6,7 +6,8 @@ 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 {showErrorAPI} from "../../utils";
import {showErrorAPI} from "../../utils/functions/showErrorAPI";
export type Watchlist = {

View File

@@ -0,0 +1,11 @@
import {EventAction} from "../api";
export const actionToColor = (a: EventAction) => a === 'registration' ? 'green' :
a === 'reregistration' ? 'cyan' :
a === 'expiration' ? 'red' :
a === 'deletion' ? 'magenta' :
a === 'transfer' ? 'orange' :
a === 'last changed' ? 'blue' :
a === 'registrar expiration' ? 'red' :
a === 'reinstantiation' ? 'purple' :
a === 'enum validation expiration' ? 'red' : 'default'

View File

@@ -0,0 +1,26 @@
import {EventAction} from "../api";
import {
ClockCircleOutlined,
DeleteOutlined,
LockOutlined,
ReloadOutlined,
ShareAltOutlined,
SignatureOutlined,
SyncOutlined,
UnlockOutlined
} from "@ant-design/icons";
import React from "react";
export const actionToIcon = (a: EventAction) => a === 'registration' ?
<SignatureOutlined style={{fontSize: '16px'}}/> : a === 'expiration' ?
<ClockCircleOutlined style={{fontSize: '16px'}}/> : a === 'transfer' ?
<ShareAltOutlined style={{fontSize: '16px'}}/> : a === 'last changed' ?
<SyncOutlined style={{fontSize: '16px'}}/> : a === 'deletion' ?
<DeleteOutlined style={{fontSize: '16px'}}/> : a === 'reregistration' ?
<ReloadOutlined style={{fontSize: '16px'}}/> : a === 'locked' ?
<LockOutlined style={{fontSize: '16px'}}/> : a === 'unlocked' ?
<UnlockOutlined style={{fontSize: '16px'}}/> : a === 'registrar expiration' ?
<ClockCircleOutlined
style={{fontSize: '16px'}}/> : a === 'enum validation expiration' ?
<ClockCircleOutlined style={{fontSize: '16px'}}/> : a === 'reinstantiation' ?
<ReloadOutlined style={{fontSize: '16px'}}/> : undefined

View File

@@ -0,0 +1,11 @@
import {Entity} from "../api";
import vCard from "vcf";
export const entityToName = (e: { entity: Entity }): string => {
if (e.entity.jCard.length === 0) return e.entity.handle
const jCard = vCard.fromJSON(e.entity.jCard)
let name = e.entity.handle
if (jCard.data.fn && !Array.isArray(jCard.data.fn) && jCard.data.fn.valueOf() !== '') name = jCard.data.fn.valueOf()
return name
}

View File

@@ -0,0 +1,5 @@
export 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.toUpperCase()
}

View File

@@ -0,0 +1,24 @@
import {Avatar} from "antd";
import {
BankOutlined,
DollarOutlined,
IdcardOutlined,
SignatureOutlined,
ToolOutlined,
UserOutlined
} from "@ant-design/icons";
import React from "react";
import {rolesToColor} from "./rolesToColor";
export const roleToAvatar = (e: { roles: string[] }) => <Avatar style={{backgroundColor: rolesToColor(e.roles)}}
icon={e.roles.includes('registrant') ?
<SignatureOutlined/> : e.roles.includes('registrar') ?
<BankOutlined/> :
e.roles.includes('technical') ?
<ToolOutlined/> :
e.roles.includes('administrative') ?
<IdcardOutlined/> :
e.roles.includes('billing') ?
<DollarOutlined/> :
<UserOutlined/>}/>

View File

@@ -0,0 +1,6 @@
export const rolesToColor = (roles: string[]) => roles.includes('registrant') ? 'green' :
roles.includes('administrative') ? 'blue' :
roles.includes('technical') ? 'orange' :
roles.includes('registrar') ? 'purple' :
roles.includes('sponsor') ? 'magenta' :
roles.includes('billing') ? 'cyan' : 'default'

View File

@@ -0,0 +1,27 @@
import {AxiosError, AxiosResponse} from "axios";
import {MessageInstance, MessageType} from "antd/lib/message/interface";
import {t} from "ttag";
export function showErrorAPI(e: AxiosError, messageApi: MessageInstance): MessageType | undefined {
const response = e.response as AxiosResponse
const data = response.data
if ('message' in data) {
return messageApi.error(data.message as string)
}
if (!('detail' in data)) return
const detail = data.detail as string
if (response.status === 429) {
const duration = response.headers['retry-after']
return messageApi.error(t`Please retry after ${duration} seconds`)
}
if (response.status.toString()[0] === '4') {
return messageApi.warning(detail !== '' ? detail : t`An error occurred`)
}
return messageApi.error(detail !== '' ? detail : t`An error occurred`)
}

View File

@@ -0,0 +1,9 @@
import {Domain} from "../api";
export const sortDomainEntities = (domain: Domain) => domain.entities.sort((e1, e2) => {
const p = (r: string[]) => r.includes('registrant') ? 5 :
r.includes('administrative') ? 4 :
r.includes('billing') ? 3 :
r.includes('registrar') ? 2 : 1
return p(e2.roles) - p(e1.roles)
})

View File

@@ -0,0 +1,12 @@
import {getCountryCode} from "./getCountryCode";
export const tldToEmoji = (tld: string) => {
if (tld.startsWith('xn--')) return '-'
return String.fromCodePoint(
...getCountryCode(tld)
.toUpperCase()
.split('')
.map((char) => 127397 + char.charCodeAt(0))
)
}

View File

@@ -1,111 +0,0 @@
import {MessageInstance, MessageType} from "antd/lib/message/interface";
import {AxiosError, AxiosResponse} from "axios";
import {t} from "ttag";
import {Avatar} from "antd";
import {
BankOutlined,
ClockCircleOutlined,
DeleteOutlined,
DollarOutlined,
IdcardOutlined,
LockOutlined,
ReloadOutlined,
ShareAltOutlined,
SignatureOutlined,
SyncOutlined,
ToolOutlined,
UnlockOutlined,
UserOutlined
} from "@ant-design/icons";
import {Domain, Entity, EventAction} from "./api";
import vCard from "vcf";
import React from "react";
export const roleToAvatar = (e: { roles: string[] }) => <Avatar style={{backgroundColor: rolesToColor(e.roles)}}
icon={e.roles.includes('registrant') ?
<SignatureOutlined/> : e.roles.includes('registrar') ?
<BankOutlined/> :
e.roles.includes('technical') ?
<ToolOutlined/> :
e.roles.includes('administrative') ?
<IdcardOutlined/> :
e.roles.includes('billing') ?
<DollarOutlined/> :
<UserOutlined/>}/>
export const rolesToColor = (roles: string[]) => roles.includes('registrant') ? 'green' :
roles.includes('administrative') ? 'blue' :
roles.includes('technical') ? 'orange' :
roles.includes('registrar') ? 'purple' :
roles.includes('sponsor') ? 'magenta' :
roles.includes('billing') ? 'cyan' : 'default'
export const actionToColor = (a: EventAction) => a === 'registration' ? 'green' :
a === 'reregistration' ? 'cyan' :
a === 'expiration' ? 'red' :
a === 'deletion' ? 'magenta' :
a === 'transfer' ? 'orange' :
a === 'last changed' ? 'blue' :
a === 'registrar expiration' ? 'red' :
a === 'reinstantiation' ? 'purple' :
a === 'enum validation expiration' ? 'red' : 'default'
export const actionToIcon = (a: EventAction) => a === 'registration' ?
<SignatureOutlined style={{fontSize: '16px'}}/> : a === 'expiration' ?
<ClockCircleOutlined style={{fontSize: '16px'}}/> : a === 'transfer' ?
<ShareAltOutlined style={{fontSize: '16px'}}/> : a === 'last changed' ?
<SyncOutlined style={{fontSize: '16px'}}/> : a === 'deletion' ?
<DeleteOutlined style={{fontSize: '16px'}}/> : a === 'reregistration' ?
<ReloadOutlined style={{fontSize: '16px'}}/> : a === 'locked' ?
<LockOutlined style={{fontSize: '16px'}}/> : a === 'unlocked' ?
<UnlockOutlined style={{fontSize: '16px'}}/> : a === 'registrar expiration' ?
<ClockCircleOutlined
style={{fontSize: '16px'}}/> : a === 'enum validation expiration' ?
<ClockCircleOutlined style={{fontSize: '16px'}}/> : a === 'reinstantiation' ?
<ReloadOutlined style={{fontSize: '16px'}}/> : undefined
export const entityToName = (e: { entity: Entity }): string => {
if (e.entity.jCard.length === 0) return e.entity.handle
const jCard = vCard.fromJSON(e.entity.jCard)
let name = e.entity.handle
if (jCard.data.fn && !Array.isArray(jCard.data.fn) && jCard.data.fn.valueOf() !== '') name = jCard.data.fn.valueOf()
return name
}
export const sortDomainEntities = (domain: Domain) => domain.entities.sort((e1, e2) => {
const p = (r: string[]) => r.includes('registrant') ? 5 :
r.includes('administrative') ? 4 :
r.includes('billing') ? 3 :
r.includes('registrar') ? 2 : 1
return p(e2.roles) - p(e1.roles)
})
export function showErrorAPI(e: AxiosError, messageApi: MessageInstance): MessageType | undefined {
const response = e.response as AxiosResponse
const data = response.data
if ('message' in data) {
return messageApi.error(data.message as string)
}
if (!('detail' in data)) return
const detail = data.detail as string
if (response.status === 429) {
const duration = response.headers['retry-after']
return messageApi.error(t`Please retry after ${duration} seconds`)
}
if (response.status.toString()[0] === '4') {
return messageApi.warning(detail !== '' ? detail : t`An error occurred`)
}
return messageApi.error(detail !== '' ? detail : t`An error occurred`)
}