mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
feat: add i18n with ttag
This commit is contained in:
@@ -31,6 +31,7 @@ import LoginPage, {AuthenticatedContext} from "./pages/LoginPage";
|
||||
import ConnectorsPage from "./pages/tracking/ConnectorsPage";
|
||||
import NotFoundPage from "./pages/NotFoundPage";
|
||||
import {ItemType, MenuItemType} from "antd/lib/menu/interface";
|
||||
import {t} from 'ttag'
|
||||
|
||||
export default function App() {
|
||||
const {
|
||||
@@ -67,36 +68,36 @@ export default function App() {
|
||||
const menuItems: ItemType<MenuItemType>[] = [
|
||||
{
|
||||
key: 'home',
|
||||
label: 'Home',
|
||||
label: t`Home`,
|
||||
icon: <HomeOutlined/>,
|
||||
onClick: () => navigate('/home')
|
||||
},
|
||||
{
|
||||
key: 'search',
|
||||
label: 'Search',
|
||||
label: t`Search`,
|
||||
icon: <SearchOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'domain-finder',
|
||||
icon: <CompassOutlined/>,
|
||||
label: 'Domain',
|
||||
title: 'Domain Finder',
|
||||
label: t`Domain`,
|
||||
title: t`Domain Finder`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/search/domain')
|
||||
},
|
||||
{
|
||||
key: 'entity-finder',
|
||||
icon: <TeamOutlined/>,
|
||||
label: 'Entity',
|
||||
title: 'Entity Finder',
|
||||
label: t`Entity`,
|
||||
title: t`Entity Finder`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/search/entity')
|
||||
},
|
||||
{
|
||||
key: 'ns-finder',
|
||||
icon: <CloudServerOutlined/>,
|
||||
label: 'Nameserver',
|
||||
title: 'Nameserver Finder',
|
||||
label: t`Nameserver`,
|
||||
title: t`Nameserver Finder`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/search/nameserver')
|
||||
}
|
||||
@@ -104,21 +105,21 @@ export default function App() {
|
||||
},
|
||||
{
|
||||
key: 'info',
|
||||
label: 'Information',
|
||||
label: t`Information`,
|
||||
icon: <InfoCircleOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'tld-list',
|
||||
icon: <BankOutlined/>,
|
||||
label: 'TLD',
|
||||
title: 'TLD list',
|
||||
label: t`TLD`,
|
||||
title: t`TLD list`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/info/tld')
|
||||
},
|
||||
{
|
||||
key: 'stats',
|
||||
icon: <LineChartOutlined/>,
|
||||
label: 'Statistics',
|
||||
label: t`Statistics`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/info/stats')
|
||||
}
|
||||
@@ -126,20 +127,20 @@ export default function App() {
|
||||
},
|
||||
{
|
||||
key: 'tracking',
|
||||
label: 'Tracking',
|
||||
label: t`Tracking`,
|
||||
icon: <FileSearchOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'watchlist',
|
||||
icon: <Badge count={0} size="small"><FileSearchOutlined/></Badge>,
|
||||
label: 'My Watchlists',
|
||||
label: t`My Watchlists`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/tracking/watchlist')
|
||||
},
|
||||
{
|
||||
key: 'connectors',
|
||||
icon: <ApiOutlined/>,
|
||||
label: 'My connectors',
|
||||
label: t`My connectors`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/tracking/connectors')
|
||||
}
|
||||
@@ -147,26 +148,26 @@ export default function App() {
|
||||
},
|
||||
{
|
||||
key: 'watchdog',
|
||||
label: 'My Watchdog',
|
||||
label: t`My Watchdog`,
|
||||
icon: <UserOutlined/>,
|
||||
children: [
|
||||
{
|
||||
key: 'account',
|
||||
icon: <UserOutlined/>,
|
||||
label: 'My Account',
|
||||
label: t`My Account`,
|
||||
disabled: !isAuthenticated,
|
||||
onClick: () => navigate('/user')
|
||||
},
|
||||
{
|
||||
key: 'tos',
|
||||
icon: <InfoCircleOutlined/>,
|
||||
label: 'TOS',
|
||||
label: t`TOS`,
|
||||
onClick: () => navigate('/tos')
|
||||
},
|
||||
{
|
||||
key: 'privacy',
|
||||
icon: <FileProtectOutlined/>,
|
||||
label: 'Privacy Policy',
|
||||
label: t`Privacy Policy`,
|
||||
onClick: () => navigate('/privacy')
|
||||
}
|
||||
]
|
||||
@@ -174,7 +175,7 @@ export default function App() {
|
||||
{
|
||||
key: '5',
|
||||
icon: <QuestionCircleOutlined/>,
|
||||
label: 'FAQ',
|
||||
label: t`FAQ`,
|
||||
onClick: () => navigate('/faq')
|
||||
},
|
||||
|
||||
@@ -192,13 +193,13 @@ export default function App() {
|
||||
items={[...menuItems, isAuthenticated ? {
|
||||
key: '8',
|
||||
icon: <LogoutOutlined/>,
|
||||
label: 'Log out',
|
||||
label: t`Log out`,
|
||||
danger: true,
|
||||
onClick: () => window.location.replace("/logout")
|
||||
} : {
|
||||
key: '8',
|
||||
icon: <LoginOutlined/>,
|
||||
label: 'Log in',
|
||||
label: t`Log in`,
|
||||
onClick: () => navigate('/login')
|
||||
}]}
|
||||
/>
|
||||
|
||||
13
assets/i18n/index.ts
Normal file
13
assets/i18n/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import {addLocale, useLocale} from 'ttag'
|
||||
|
||||
const locale = navigator.language.split('-')[0];
|
||||
|
||||
if (locale !== 'en') {
|
||||
fetch(`/locales/${locale}.po.json`).then(response => {
|
||||
if (!response.ok) throw new Error(`Failed to load translations for locale ${locale}`);
|
||||
response.json().then(translationsObj => {
|
||||
addLocale(locale, translationsObj);
|
||||
useLocale(locale);
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import App from "./App";
|
||||
import {HashRouter} from "react-router-dom";
|
||||
|
||||
import 'antd/dist/reset.css';
|
||||
import './i18n'
|
||||
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement)
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, {createContext, useContext, useState} from "react";
|
||||
import {Alert, Button, Card, Flex, Form, Input} from "antd";
|
||||
import {login} from "../utils/api";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {t} from 'ttag'
|
||||
|
||||
type FieldType = {
|
||||
username: string;
|
||||
@@ -14,7 +15,7 @@ export default function Page() {
|
||||
|
||||
const [error, setError] = useState()
|
||||
const navigate = useNavigate()
|
||||
const {isAuthenticated, setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||
|
||||
const onFinish = (data: FieldType) => {
|
||||
login(data.username, data.password).then(() => {
|
||||
@@ -27,12 +28,12 @@ export default function Page() {
|
||||
}
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical><Card
|
||||
title="Log in"
|
||||
title={t`Log in`}
|
||||
>
|
||||
{error &&
|
||||
<Alert
|
||||
type='error'
|
||||
message='Error'
|
||||
message={t`Error`}
|
||||
banner={true}
|
||||
role='role'
|
||||
description={error}
|
||||
@@ -47,29 +48,29 @@ export default function Page() {
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item
|
||||
label="Username"
|
||||
label={t`Username`}
|
||||
name="username"
|
||||
rules={[{required: true, message: 'Required'}]}
|
||||
rules={[{required: true, message: t`Required`}]}
|
||||
>
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<FieldType>
|
||||
label="Password"
|
||||
label={t`Password`}
|
||||
name="password"
|
||||
rules={[{required: true, message: 'Required'}]}
|
||||
rules={[{required: true, message: t`Required`}]}
|
||||
>
|
||||
<Input.Password/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
{t`Submit`}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||
<Button type="primary" htmlType="button" href="/login/oauth">
|
||||
Log in with SSO
|
||||
{t`Log in with SSO`}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {Result} from "antd";
|
||||
import React from "react";
|
||||
import { t } from 'ttag'
|
||||
|
||||
|
||||
export default function NotFoundPage() {
|
||||
return <Result
|
||||
status="404"
|
||||
title="404"
|
||||
subTitle="Sorry, the page you visited does not exist."
|
||||
subTitle={t`Sorry, the page you visited does not exist.`}
|
||||
/>
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {Collapse, Divider, Table, Typography} from "antd";
|
||||
import {getTldList, Tld} from "../../utils/api";
|
||||
import {t} from 'ttag'
|
||||
|
||||
const {Text, Paragraph} = Typography
|
||||
|
||||
@@ -60,24 +61,24 @@ function TldTable(filters: FiltersType) {
|
||||
|
||||
let columns = [
|
||||
{
|
||||
title: "TLD",
|
||||
title: t`TLD`,
|
||||
dataIndex: "TLD",
|
||||
width: 20
|
||||
}
|
||||
]
|
||||
|
||||
if (filters.type === 'ccTLD') columns = [...columns, {
|
||||
title: "Flag",
|
||||
title: t`Flag`,
|
||||
dataIndex: "Flag",
|
||||
width: 20
|
||||
}, {
|
||||
title: "Country",
|
||||
title: t`Country`,
|
||||
dataIndex: "Country",
|
||||
width: 200
|
||||
}]
|
||||
|
||||
if (filters.type === 'gTLD') columns = [...columns, {
|
||||
title: "Registry Operator",
|
||||
title: t`Registry Operator`,
|
||||
dataIndex: "Operator",
|
||||
width: 50
|
||||
}]
|
||||
@@ -102,16 +103,13 @@ function TldTable(filters: FiltersType) {
|
||||
export default function TldPage() {
|
||||
return <>
|
||||
<Paragraph>
|
||||
This page presents all active TLDs in the root zone database.
|
||||
{t`This page presents all active TLDs in the root zone database.`}
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
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.
|
||||
{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
|
||||
@@ -119,41 +117,36 @@ export default function TldPage() {
|
||||
items={[
|
||||
{
|
||||
key: 'sTLD',
|
||||
label: 'Sponsored Top-Level-Domains',
|
||||
label: t`Sponsored Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Top-level domains sponsored by specific organizations that set rules for
|
||||
registration and use, often related to particular interest groups or
|
||||
industries.</Text>
|
||||
<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: 'Generic Top-Level-Domains',
|
||||
label: t`Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Generic top-level domains open to everyone, not restricted by specific
|
||||
criteria, representing various themes or industries.</Text>
|
||||
<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: 'Brand Generic Top-Level-Domains',
|
||||
label: t`Brand Generic Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Generic top-level domains associated with specific brands, allowing companies
|
||||
to use their own brand names as domains.</Text>
|
||||
<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: 'Country-Code Top-Level-Domains',
|
||||
label: t`Country-Code Top-Level-Domains`,
|
||||
children: <>
|
||||
<Text>Top-level domains based on country codes, identifying websites according to
|
||||
their country of origin.</Text>
|
||||
<Text>{`Top-level domains based on country codes, identifying websites according to their country of origin.`}</Text>
|
||||
<Divider/><TldTable type='ccTLD'/>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
import {Domain, getDomain} from "../../utils/api";
|
||||
import {AxiosError} from "axios"
|
||||
import vCard from 'vcf'
|
||||
import {t} from 'ttag'
|
||||
|
||||
|
||||
type FieldType = {
|
||||
@@ -48,16 +49,16 @@ export default function DomainSearchPage() {
|
||||
setDomain(null)
|
||||
getDomain(values.ldhName).then(d => {
|
||||
setDomain(d)
|
||||
messageApi.success('Found !')
|
||||
messageApi.success(t`Found !`)
|
||||
}).catch((e: AxiosError) => {
|
||||
const data = e?.response?.data as { detail: string }
|
||||
setDomain(undefined)
|
||||
messageApi.error(data.detail ?? 'An error occurred')
|
||||
messageApi.error(data.detail ?? t`An error occurred`)
|
||||
})
|
||||
}
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
<Card title="Domain finder" style={{width: '100%'}}>
|
||||
<Card title={t`Domain finder`} style={{width: '100%'}}>
|
||||
{contextHolder}
|
||||
<Form
|
||||
name="basic"
|
||||
@@ -70,10 +71,10 @@ export default function DomainSearchPage() {
|
||||
name="ldhName"
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}, {
|
||||
pattern: /^(?=.*\.)\S*[^.\s]$/,
|
||||
message: 'This domain name does not appear to be valid',
|
||||
message: t`This domain name does not appear to be valid`,
|
||||
max: 63,
|
||||
min: 2
|
||||
}]}
|
||||
@@ -189,8 +190,7 @@ export default function DomainSearchPage() {
|
||||
: <Empty
|
||||
description={
|
||||
<Typography.Text>
|
||||
Although the domain exists in my database, it has been deleted from the WHOIS by its
|
||||
registrar.
|
||||
{t`Although the domain exists in my database, it has been deleted from the WHOIS by its registrar.`}
|
||||
</Typography.Text>
|
||||
}/>)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {Button, Card, Divider, Flex, Form, Input, message, Popconfirm, Select, S
|
||||
import {DeleteFilled, MinusCircleOutlined, PlusOutlined, ThunderboltFilled} from "@ant-design/icons";
|
||||
import {deleteWatchlist, EventAction, getWatchlists, postWatchlist} from "../../utils/api";
|
||||
import {AxiosError} from "axios";
|
||||
import {t} from 'ttag'
|
||||
|
||||
|
||||
const formItemLayout = {
|
||||
@@ -26,42 +27,42 @@ const formItemLayoutWithOutLabel = {
|
||||
|
||||
const triggerEventItems: { label: string, value: EventAction }[] = [
|
||||
{
|
||||
label: 'When a domain is expired',
|
||||
label: t`When a domain is expired`,
|
||||
value: 'expiration'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is updated',
|
||||
label: t`When a domain is updated`,
|
||||
value: 'last changed'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is deleted',
|
||||
label: t`When a domain is deleted`,
|
||||
value: 'deletion'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is transferred',
|
||||
label: t`When a domain is transferred`,
|
||||
value: 'transfer'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is locked',
|
||||
label: t`When a domain is locked`,
|
||||
value: 'locked'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is unlocked',
|
||||
label: t`When a domain is unlocked`,
|
||||
value: 'unlocked'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is reregistered',
|
||||
label: t`When a domain is reregistered`,
|
||||
value: 'reregistration'
|
||||
},
|
||||
{
|
||||
label: 'When a domain is reinstantiated',
|
||||
label: t`When a domain is reinstantiated`,
|
||||
value: 'reinstantiation'
|
||||
}
|
||||
]
|
||||
|
||||
const trigerActionItems = [
|
||||
{
|
||||
label: 'Send me an email',
|
||||
label: t`Send me an email`,
|
||||
value: 'email'
|
||||
}
|
||||
]
|
||||
@@ -78,10 +79,10 @@ export default function WatchlistPage() {
|
||||
postWatchlist(domainsURI, values.triggers).then((w) => {
|
||||
form.resetFields()
|
||||
refreshWatchlists()
|
||||
messageApi.success('Watchlist created !')
|
||||
messageApi.success(t`Watchlist created !`)
|
||||
}).catch((e: AxiosError) => {
|
||||
const data = e?.response?.data as { detail: string }
|
||||
messageApi.error(data.detail ?? 'An error occurred')
|
||||
messageApi.error(data.detail ?? t`An error occurred`)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,7 +95,7 @@ export default function WatchlistPage() {
|
||||
}, [])
|
||||
|
||||
return <Flex gap="middle" align="center" justify="center" vertical>
|
||||
<Card title="Create a watchlist" style={{width: '100%'}}>
|
||||
<Card title={t`Create a watchlist`} style={{width: '100%'}}>
|
||||
{contextHolder}
|
||||
<Form
|
||||
{...formItemLayoutWithOutLabel}
|
||||
@@ -107,7 +108,7 @@ export default function WatchlistPage() {
|
||||
{
|
||||
validator: async (_, domains) => {
|
||||
if (!domains || domains.length < 1) {
|
||||
return Promise.reject(new Error('At least one domain name'));
|
||||
return Promise.reject(new Error(t`At least one domain name`));
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -118,7 +119,7 @@ export default function WatchlistPage() {
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item
|
||||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
||||
label={index === 0 ? 'Domain names' : ''}
|
||||
label={index === 0 ? t`Domain names` : ''}
|
||||
required={true}
|
||||
key={field.key}
|
||||
>
|
||||
@@ -127,16 +128,16 @@ export default function WatchlistPage() {
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}, {
|
||||
pattern: /^(?=.*\.)\S*[^.\s]$/,
|
||||
message: 'This domain name does not appear to be valid',
|
||||
message: t`This domain name does not appear to be valid`,
|
||||
max: 63,
|
||||
min: 2
|
||||
}]}
|
||||
noStyle
|
||||
>
|
||||
<Input placeholder="Domain name" style={{width: '60%'}} autoComplete='off'/>
|
||||
<Input placeholder={t`Domain name`} style={{width: '60%'}} autoComplete='off'/>
|
||||
</Form.Item>
|
||||
{fields.length > 1 ? (
|
||||
<MinusCircleOutlined
|
||||
@@ -153,7 +154,7 @@ export default function WatchlistPage() {
|
||||
style={{width: '60%'}}
|
||||
icon={<PlusOutlined/>}
|
||||
>
|
||||
Add a Domain name
|
||||
{t`Add a Domain name`}
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors}/>
|
||||
</Form.Item>
|
||||
@@ -166,7 +167,7 @@ export default function WatchlistPage() {
|
||||
{
|
||||
validator: async (_, domains) => {
|
||||
if (!domains || domains.length < 1) {
|
||||
return Promise.reject(new Error('At least one domain trigger'));
|
||||
return Promise.reject(new Error(t`At least one domain trigger`));
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -177,7 +178,7 @@ export default function WatchlistPage() {
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item
|
||||
{...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
|
||||
label={index === 0 ? 'Domain trigger' : ''}
|
||||
label={index === 0 ? t`Domain trigger` : ''}
|
||||
required={true}
|
||||
key={field.key}
|
||||
>
|
||||
@@ -187,21 +188,21 @@ export default function WatchlistPage() {
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}]}
|
||||
noStyle name={[field.name, 'event']}>
|
||||
<Select style={{minWidth: 300}} options={triggerEventItems} showSearch
|
||||
placeholder="If this happens" optionFilterProp="label"/>
|
||||
placeholder={t`If this happens`} optionFilterProp="label"/>
|
||||
</Form.Item>
|
||||
<Form.Item {...field}
|
||||
validateTrigger={['onChange', 'onBlur']}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: 'Required'
|
||||
message: t`Required`
|
||||
}]}
|
||||
noStyle name={[field.name, 'action']}>
|
||||
<Select style={{minWidth: 300}} options={trigerActionItems} showSearch
|
||||
placeholder="Then do that"
|
||||
placeholder={t`Then do that`}
|
||||
optionFilterProp="label"/>
|
||||
</Form.Item>
|
||||
</Space>
|
||||
@@ -222,7 +223,7 @@ export default function WatchlistPage() {
|
||||
style={{width: '60%'}}
|
||||
icon={<ThunderboltFilled/>}
|
||||
>
|
||||
Add a Trigger
|
||||
{t`Add a Trigger`}
|
||||
</Button>
|
||||
<Form.ErrorList errors={errors}/>
|
||||
</Form.Item>
|
||||
@@ -232,10 +233,10 @@ export default function WatchlistPage() {
|
||||
<Form.Item>
|
||||
<Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Create
|
||||
{t`Create`}
|
||||
</Button>
|
||||
<Button type="default" htmlType="reset">
|
||||
Reset
|
||||
{t`Reset`}
|
||||
</Button>
|
||||
</Space>
|
||||
</Form.Item>
|
||||
@@ -247,19 +248,19 @@ export default function WatchlistPage() {
|
||||
{watchlists && watchlists.length > 0 && <Card title="My Watchlists" style={{width: '100%'}}>
|
||||
{watchlists.map(watchlist =>
|
||||
<>
|
||||
<Card title={"Watchlist " + watchlist.token} extra={<Popconfirm
|
||||
title="Delete the Watchlist"
|
||||
description="Are you sure to delete this Watchlist ?"
|
||||
<Card title={t`Watchlist ${watchlist.token}`} extra={<Popconfirm
|
||||
title={t`"Delete the Watchlist"`}
|
||||
description={t`Are you sure to delete this Watchlist?`}
|
||||
onConfirm={() => deleteWatchlist(watchlist.token).then(refreshWatchlists)}
|
||||
okText="Yes"
|
||||
cancelText="No"
|
||||
okText={t`"Yes"`}
|
||||
cancelText={t`No`}
|
||||
><DeleteFilled/> </Popconfirm>}>
|
||||
<Typography.Paragraph>
|
||||
Domains : {watchlist?.domains.map(d => d.ldhName).join(',')}
|
||||
{t`Domain name`} : {watchlist?.domains.map(d => d.ldhName).join(',')}
|
||||
</Typography.Paragraph>
|
||||
{
|
||||
watchlist.triggers && <Typography.Paragraph>
|
||||
Triggers : {watchlist.triggers.map(t => `${t.event} => ${t.action}`).join(',')}
|
||||
{t`Domain triggers`} : {watchlist.triggers.map(t => `${t.event} => ${t.action}`).join(',')}
|
||||
</Typography.Paragraph>
|
||||
}
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user