+ >
diff --git a/assets/components/tracking/watchlist/WatchlistForm.tsx b/assets/components/tracking/watchlist/WatchlistForm.tsx
index a2bddb0..33cdd49 100644
--- a/assets/components/tracking/watchlist/WatchlistForm.tsx
+++ b/assets/components/tracking/watchlist/WatchlistForm.tsx
@@ -4,11 +4,16 @@ import {t} from 'ttag'
import {ApiOutlined, MinusCircleOutlined, PlusOutlined} from '@ant-design/icons'
import React from 'react'
import type {Connector} from '../../../utils/api/connectors'
-import {rdapEventDetailTranslation, rdapEventNameTranslation} from '../../../utils/functions/rdapTranslation'
+import {
+ rdapDomainStatusCodeDetailTranslation,
+ rdapEventDetailTranslation,
+ rdapEventNameTranslation
+} from '../../../utils/functions/rdapTranslation'
import {actionToColor} from '../../../utils/functions/actionToColor'
import {actionToIcon} from '../../../utils/functions/actionToIcon'
import type {EventAction, Watchlist} from '../../../utils/api'
import {formItemLayoutWithOutLabel} from "../../../utils/providers"
+import {eppStatusCodeToColor} from "../../../utils/functions/eppStatusCodeToColor"
type TagRender = SelectProps['tagRender']
@@ -26,14 +31,15 @@ const formItemLayout = {
export function WatchlistForm({form, connectors, onFinish, isCreation}: {
form: FormInstance
connectors: Array
- onFinish: (values: { domains: string[], trackedEvents: string[], token: string }) => void
+ onFinish: (values: { domains: string[], trackedEvents: string[], trackedEppStatus: string[], token: string }) => void
isCreation: boolean,
watchList?: Watchlist,
}) {
const rdapEventNameTranslated = rdapEventNameTranslation()
const rdapEventDetailTranslated = rdapEventDetailTranslation()
+ const rdapDomainStatusCodeDetailTranslated = rdapDomainStatusCodeDetailTranslation()
- const triggerTagRenderer: TagRender = ({value, closable, onClose}: {
+ const eventActionTagRenderer: TagRender = ({value, closable, onClose}: {
value: EventAction
closable: boolean
onClose: () => void
@@ -60,12 +66,41 @@ export function WatchlistForm({form, connectors, onFinish, isCreation}: {
)
}
+ const domainStatusTagRenderer: TagRender = ({value, closable, onClose}: {
+ value: EventAction
+ closable: boolean
+ onClose: () => void
+ }) => {
+ const onPreventMouseDown = (event: React.MouseEvent) => {
+ event.preventDefault()
+ event.stopPropagation()
+ }
+ return (
+
+
+ {value}
+
+
+ )
+ }
+
return (
@@ -155,7 +190,7 @@ export function WatchlistForm({form, connectors, onFinish, isCreation}: {
+
+
+
void
- onUpdateWatchlist: (values: { domains: string[], trackedEvents: string[], token: string }) => Promise
+ onUpdateWatchlist: (values: { domains: string[], trackedEvents: string[], trackedEppStatus: string[], token: string }) => Promise
connectors: Array
}) {
return (
diff --git a/assets/pages/tracking/WatchlistPage.tsx b/assets/pages/tracking/WatchlistPage.tsx
index 51e49e5..61f678a 100644
--- a/assets/pages/tracking/WatchlistPage.tsx
+++ b/assets/pages/tracking/WatchlistPage.tsx
@@ -15,6 +15,7 @@ interface FormValuesType {
name?: string
domains: string[]
trackedEvents: string[]
+ trackedEppStatus: string[]
connector?: string
dsn?: string[]
}
@@ -25,6 +26,7 @@ const getRequestDataFromFormCreation = (values: FormValuesType) => {
name: values.name,
domains: domainsURI,
trackedEvents: values.trackedEvents,
+ trackedEppStatus: values.trackedEppStatus,
connector: values.connector !== undefined ? ('/api/connectors/' + values.connector) : undefined,
dsn: values.dsn
}
diff --git a/assets/utils/api/index.ts b/assets/utils/api/index.ts
index ef37e56..7bd2b0c 100644
--- a/assets/utils/api/index.ts
+++ b/assets/utils/api/index.ts
@@ -81,6 +81,7 @@ export interface WatchlistRequest {
name?: string
domains: string[]
trackedEvents?: string[]
+ trackedEppStatus?: string[]
connector?: string
dsn?: string[]
}
@@ -91,6 +92,7 @@ export interface Watchlist {
token: string
domains: Domain[]
trackedEvents?: string[]
+ trackedEppStatus?: string[]
dsn?: string[]
connector?: {
id: string
diff --git a/assets/utils/functions/eppStatusCodeToColor.tsx b/assets/utils/functions/eppStatusCodeToColor.tsx
index 66d83e4..132b648 100644
--- a/assets/utils/functions/eppStatusCodeToColor.tsx
+++ b/assets/utils/functions/eppStatusCodeToColor.tsx
@@ -1,8 +1,9 @@
-export const eppStatusCodeToColor = (s: string) =>
- ['active', 'ok'].includes(s)
- ? 'green'
- : ['pending delete', 'redemption period'].includes(s)
- ? 'red'
- : s.startsWith('client')
- ? 'purple'
- : s.startsWith('server') ? 'geekblue' : 'blue'
+export const eppStatusCodeToColor = (s?: string) =>
+ s === undefined ? 'default' :
+ ['active', 'ok'].includes(s)
+ ? 'green'
+ : ['pending delete', 'redemption period'].includes(s)
+ ? 'red'
+ : s.startsWith('client')
+ ? 'purple'
+ : s.startsWith('server') ? 'geekblue' : 'blue'
diff --git a/assets/utils/functions/rdapTranslation.ts b/assets/utils/functions/rdapTranslation.ts
index 875eb98..1523d78 100644
--- a/assets/utils/functions/rdapTranslation.ts
+++ b/assets/utils/functions/rdapTranslation.ts
@@ -68,23 +68,7 @@ export const rdapEventDetailTranslation = () => ({
'enum validation expiration': t`Association of phone number represented by this ENUM domain to registrant has expired or will expire at a predetermined date and time.`
})
-/**
- * @see https://www.iana.org/assignments/rdap-json-values/rdap-json-values.xhtml
- * @see https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en
- */
-export const rdapStatusCodeDetailTranslation = () => ({
- validated: t`Signifies that the data of the object instance has been found to be accurate.`,
- 'renew prohibited': t`Renewal or reregistration of the object instance is forbidden.`,
- 'update prohibited': t`Updates to the object instance are forbidden.`,
- 'transfer prohibited': t`Transfers of the registration from one registrar to another are forbidden.`,
- 'delete prohibited': t`Deletion of the registration of the object instance is forbidden.`,
- proxy: t`The registration of the object instance has been performed by a third party.`,
- private: t`The information of the object instance is not designated for public consumption.`,
- removed: t`Some of the information of the object instance has not been made available and has been removed.`,
- obscured: t`Some of the information of the object instance has been altered for the purposes of not readily revealing the actual information of the object instance.`,
- associated: t`The object instance is associated with other object instances in the registry.`,
- locked: t`Changes to the object instance cannot be made, including the association of other object instances.`,
-
+export const rdapDomainStatusCodeDetailTranslation = () => ({
active: t`This is the standard status for a domain, meaning it has no pending operations or prohibitions.`,
inactive: t`This status code indicates that delegation information (name servers) has not been associated with your domain. Your domain is not activated in the DNS and will not resolve.`,
'pending create': t`This status code indicates that a request to create your domain has been received and is being processed.`,
@@ -110,6 +94,27 @@ export const rdapStatusCodeDetailTranslation = () => ({
'server hold': t`This status code is set by your domain's Registry Operator. Your domain is not activated in the DNS.`,
'transfer period': t`This grace period is provided after the successful transfer of a domain name from one registrar to another. If the new registrar deletes the domain name during this period, the registry provides a credit to the registrar for the cost of the transfer.`,
+})
+
+/**
+ * @see https://www.iana.org/assignments/rdap-json-values/rdap-json-values.xhtml
+ * @see https://www.icann.org/resources/pages/epp-status-codes-2014-06-16-en
+ */
+export const rdapStatusCodeDetailTranslation = () => ({
+ validated: t`Signifies that the data of the object instance has been found to be accurate.`,
+ 'renew prohibited': t`Renewal or reregistration of the object instance is forbidden.`,
+ 'update prohibited': t`Updates to the object instance are forbidden.`,
+ 'transfer prohibited': t`Transfers of the registration from one registrar to another are forbidden.`,
+ 'delete prohibited': t`Deletion of the registration of the object instance is forbidden.`,
+ proxy: t`The registration of the object instance has been performed by a third party.`,
+ private: t`The information of the object instance is not designated for public consumption.`,
+ removed: t`Some of the information of the object instance has not been made available and has been removed.`,
+ obscured: t`Some of the information of the object instance has been altered for the purposes of not readily revealing the actual information of the object instance.`,
+ associated: t`The object instance is associated with other object instances in the registry.`,
+ locked: t`Changes to the object instance cannot be made, including the association of other object instances.`,
+
+ ...rdapDomainStatusCodeDetailTranslation(),
+
administrative: t`The object instance has been allocated administratively (i.e., not for use by the recipient in their own right in operational networks).`,
reserved: t`The object instance has been allocated to an IANA special-purpose address registry.`
})
diff --git a/migrations/Version20251019211214.php b/migrations/Version20251019211214.php
new file mode 100644
index 0000000..321cd78
--- /dev/null
+++ b/migrations/Version20251019211214.php
@@ -0,0 +1,31 @@
+addSql("ALTER TABLE watch_list ADD tracked_epp_status JSONB DEFAULT '[]'::jsonb");
+ $this->addSql('ALTER TABLE watch_list ALTER tracked_epp_status DROP DEFAULT ');
+ $this->addSql('ALTER TABLE watch_list ALTER tracked_epp_status SET NOT NULL');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('ALTER TABLE watch_list DROP tracked_epp_status');
+ }
+}
diff --git a/src/Entity/WatchList.php b/src/Entity/WatchList.php
index 0408966..736be2f 100644
--- a/src/Entity/WatchList.php
+++ b/src/Entity/WatchList.php
@@ -199,6 +199,15 @@ class WatchList
])]
private array $trackedEvents = [];
+ #[ORM\Column(type: Types::JSON)]
+ #[Groups(['watchlist:list', 'watchlist:item', 'watchlist:create', 'watchlist:update'])]
+ #[Assert\Unique]
+ #[Assert\All([
+ new Assert\Type('string'),
+ new Assert\NotBlank(),
+ ])]
+ private array $trackedEppStatus = [];
+
public function __construct()
{
$this->token = Uuid::v4();
@@ -311,4 +320,16 @@ class WatchList
return $this;
}
+
+ public function getTrackedEppStatus(): array
+ {
+ return $this->trackedEppStatus;
+ }
+
+ public function setTrackedEppStatus(array $trackedEppStatus): static
+ {
+ $this->trackedEppStatus = $trackedEppStatus;
+
+ return $this;
+ }
}
diff --git a/src/MessageHandler/SendDomainEventNotifHandler.php b/src/MessageHandler/SendDomainEventNotifHandler.php
index 248288e..e4d65fe 100644
--- a/src/MessageHandler/SendDomainEventNotifHandler.php
+++ b/src/MessageHandler/SendDomainEventNotifHandler.php
@@ -4,10 +4,14 @@ namespace App\MessageHandler;
use App\Entity\Domain;
use App\Entity\DomainEvent;
+use App\Entity\DomainStatus;
use App\Entity\WatchList;
use App\Message\SendDomainEventNotif;
+use App\Notifier\DomainStatusUpdateNotification;
use App\Notifier\DomainUpdateNotification;
+use App\Repository\DomainEventRepository;
use App\Repository\DomainRepository;
+use App\Repository\DomainStatusRepository;
use App\Repository\WatchListRepository;
use App\Service\ChatNotificationService;
use App\Service\InfluxdbService;
@@ -37,6 +41,8 @@ final readonly class SendDomainEventNotifHandler
#[Autowire(param: 'influxdb_enabled')]
private bool $influxdbEnabled,
private InfluxdbService $influxdbService,
+ private DomainEventRepository $domainEventRepository,
+ private DomainStatusRepository $domainStatusRepository,
) {
$this->sender = new Address($mailerSenderEmail, $mailerSenderName);
}
@@ -51,20 +57,28 @@ final readonly class SendDomainEventNotifHandler
$watchList = $this->watchListRepository->findOneBy(['token' => $message->watchListToken]);
/** @var Domain $domain */
$domain = $this->domainRepository->findOneBy(['ldhName' => $message->ldhName]);
+ $recipient = new Recipient($watchList->getUser()->getEmail());
/*
* For each new event whose date is after the domain name update date (before the current domain name update)
*/
- /** @var DomainEvent $event */
- foreach ($domain->getEvents()->filter(
- fn ($event) => $message->updatedAt < $event->getDate() && $event->getDate() < new \DateTimeImmutable()) as $event
- ) {
+ /** @var DomainEvent[] $newEvents */
+ $newEvents = $this->domainEventRepository->createQueryBuilder('de')
+ ->select()
+ ->where('de.domain = :domain')
+ ->andWhere('de.date > :updatedAt')
+ ->andWhere('de.date < :now')
+ ->setParameter('domain', $domain)
+ ->setParameter('updatedAt', $domain->getUpdatedAt())
+ ->setParameter('now', new \DateTimeImmutable())
+ ->getQuery()->getResult();
+
+ foreach ($newEvents as $event) {
if (!in_array($event->getAction(), $watchList->getTrackedEvents())) {
continue;
}
- $recipient = new Recipient($watchList->getUser()->getEmail());
$notification = new DomainUpdateNotification($this->sender, $event);
$this->logger->info('New action has been detected on this domain name : an email is sent to user', [
@@ -75,6 +89,10 @@ final readonly class SendDomainEventNotifHandler
$this->mailer->send($notification->asEmailMessage($recipient)->getMessage());
+ if ($this->influxdbEnabled) {
+ $this->influxdbService->addDomainNotificationPoint($domain, 'email', true);
+ }
+
$webhookDsn = $watchList->getWebhookDsn();
if (null !== $webhookDsn && 0 !== count($webhookDsn)) {
$this->logger->info('New action has been detected on this domain name : a notification is sent to user', [
@@ -84,11 +102,64 @@ final readonly class SendDomainEventNotifHandler
]);
$this->chatNotificationService->sendChatNotification($watchList, $notification);
+ if ($this->influxdbEnabled) {
+ $this->influxdbService->addDomainNotificationPoint($domain, 'chat', true);
+ }
}
+ $this->statService->incrementStat('stats.alert.sent');
+ }
+
+ /** @var DomainStatus $domainStatus */
+ $domainStatus = $this->domainStatusRepository->createQueryBuilder('ds')
+ ->select()
+ ->where('ds.domain = :domain')
+ ->andWhere('ds.createdAt > :createdAt')
+ ->andWhere('ds.createdAt < :now')
+ ->orderBy('ds.createdAt DESC')
+ ->setParameter('domain', $domain)
+ ->setParameter('createdAt', $domain->getUpdatedAt())
+ ->setParameter('now', new \DateTimeImmutable())
+ ->getQuery()
+ ->getOneOrNullResult();
+
+ if (null !== $domainStatus && count(array_intersect(
+ $watchList->getTrackedEppStatus(),
+ [...$domainStatus->getAddStatus(), ...$domainStatus->getDeleteStatus()]
+ ))) {
+ $notification = new DomainStatusUpdateNotification($this->sender, $domain, $domainStatus);
+
+ $this->logger->info('New domain status has been detected on this domain name : an email is sent to user', [
+ 'addStatus' => $domainStatus->getAddStatus(),
+ 'deleteStatus' => $domainStatus->getDeleteStatus(),
+ 'status' => $domain->getStatus(),
+ 'ldhName' => $message->ldhName,
+ 'username' => $watchList->getUser()->getUserIdentifier(),
+ ]);
+
+ $this->mailer->send($notification->asEmailMessage($recipient)->getMessage());
+
if ($this->influxdbEnabled) {
- $this->influxdbService->addDomainNotificationPoint($domain, 'chat', true);
+ $this->influxdbService->addDomainNotificationPoint($domain, 'email', true);
}
+
+ $webhookDsn = $watchList->getWebhookDsn();
+ if (null !== $webhookDsn && 0 !== count($webhookDsn)) {
+ $this->logger->info('New domain status has been detected on this domain name : a notification is sent to user', [
+ 'addStatus' => $domainStatus->getAddStatus(),
+ 'deleteStatus' => $domainStatus->getDeleteStatus(),
+ 'status' => $domain->getStatus(),
+ 'ldhName' => $message->ldhName,
+ 'username' => $watchList->getUser()->getUserIdentifier(),
+ ]);
+
+ $this->chatNotificationService->sendChatNotification($watchList, $notification);
+
+ if ($this->influxdbEnabled) {
+ $this->influxdbService->addDomainNotificationPoint($domain, 'chat', true);
+ }
+ }
+
$this->statService->incrementStat('stats.alert.sent');
}
}
diff --git a/src/Notifier/DomainStatusUpdateNotification.php b/src/Notifier/DomainStatusUpdateNotification.php
new file mode 100644
index 0000000..077eca9
--- /dev/null
+++ b/src/Notifier/DomainStatusUpdateNotification.php
@@ -0,0 +1,69 @@
+domain->getLdhName();
+ $this->subject("Domain EPP status changed $ldhName")
+ ->content("Domain name $ldhName EPP status has been updated.")
+ ->importance(Notification::IMPORTANCE_HIGH);
+
+ return ChatMessage::fromNotification($this);
+ }
+
+ public function asPushMessage(?RecipientInterface $recipient = null, ?string $transport = null): ?PushMessage
+ {
+ $ldhName = $this->domain->getLdhName();
+ $this->subject("Domain EPP status changed $ldhName")
+ ->content("Domain name $ldhName EPP status has been updated.")
+ ->importance(Notification::IMPORTANCE_HIGH);
+
+ return PushMessage::fromNotification($this);
+ }
+
+ public function asEmailMessage(EmailRecipientInterface $recipient): EmailMessage
+ {
+ $ldhName = $this->domain->getLdhName();
+
+ $email = (new TemplatedEmail())
+ ->from($this->sender)
+ ->to($recipient->getEmail())
+ ->priority(Email::PRIORITY_HIGH)
+ ->subject("Domain EPP status changed $ldhName")
+ ->htmlTemplate('emails/success/domain_updated.html.twig')
+ ->locale('en')
+ ->context([
+ 'domain' => $this->domain,
+ 'domainStatus' => $this->domainStatus,
+ ]);
+
+ $email->getHeaders()
+ ->addTextHeader('In-Reply-To', "<$ldhName+updated@domain-watchdog>")
+ ->addTextHeader('References', "<$ldhName+updated@domain-watchdog>");
+
+ return new EmailMessage($email);
+ }
+}
diff --git a/templates/emails/errors/connector_credentials.html.twig b/templates/emails/errors/connector_credentials.html.twig
index b10f514..4cc7f73 100644
--- a/templates/emails/errors/connector_credentials.html.twig
+++ b/templates/emails/errors/connector_credentials.html.twig
@@ -17,6 +17,6 @@
To resolve this issue, please verify the login credentials associated with the connector and update them if necessary.
Thank you for your attention,
- Sincerely,
+ Best regards
This domain has been identified as deleted and is potentially available for registration until it is registered by another party.
- Thank you for your understanding,
- Sincerely,
+ Thank you for your attention.
+ Best regards
{% endblock %}
\ No newline at end of file
diff --git a/templates/emails/errors/domain_order.html.twig b/templates/emails/errors/domain_order.html.twig
index dbc713f..0587aa8 100644
--- a/templates/emails/errors/domain_order.html.twig
+++ b/templates/emails/errors/domain_order.html.twig
@@ -14,7 +14,7 @@
A temporary interruption is affecting the registration of this domain name.
A temporary outage affects the provision of domain name information.
-
Thank you for your understanding,
- Sincerely,
+
Thank you for your attention.
+ Best regards
{% endblock %}
diff --git a/templates/emails/success/confirmation_email.html.twig b/templates/emails/success/confirmation_email.html.twig
index 0324caf..bda868e 100644
--- a/templates/emails/success/confirmation_email.html.twig
+++ b/templates/emails/success/confirmation_email.html.twig
@@ -8,7 +8,7 @@
Confirm my Email.
This link will expire in {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.
- Thank you for your understanding,
- Sincerely,
+ Thank you for your attention.
+ Best regards
{% endblock %}
diff --git a/templates/emails/success/domain_ordered.html.twig b/templates/emails/success/domain_ordered.html.twig
index 376cc7f..bc436ca 100644
--- a/templates/emails/success/domain_ordered.html.twig
+++ b/templates/emails/success/domain_ordered.html.twig
@@ -9,7 +9,7 @@
Domain name: {{ domain.ldhName }} Connector provider : {{ provider }}
- Thank you for your understanding,
- Sincerely,
+ Thank you for your attention.
+ Best regards
{% endblock %}
diff --git a/templates/emails/success/domain_status_updated.twig b/templates/emails/success/domain_status_updated.twig
new file mode 100644
index 0000000..294bc91
--- /dev/null
+++ b/templates/emails/success/domain_status_updated.twig
@@ -0,0 +1,23 @@
+{% extends "emails/base.html.twig" %}
+{% set email_color = '#0056b3' %}
+{% set title = 'Domain Watchdog Alert' %}
+{% block content %}
+
Hello,
+
We would like to inform you that a change has been detected in the EPP status of one of the domains on your watchlist.
+
+
+ Domain name: {{ domain.ldhName }}
+ Current EPP status: {{ domain.status | join(' | ') }}
+ {% if domainStatus.addStatus is not empty %}
+ [+] Added status: {{ domainStatus.addStatus | join(' | ') }}
+ {% endif %}
+ {% if domainStatus.deleteStatus is not empty %}
+ [-] Removed status: {{ domainStatus.deleteStatus | join(' | ') }}
+ {% endif %}
+
- Thank you for your understanding,
- Sincerely,
+ Thank you for your attention.
+ Best regards
{% endblock %}
diff --git a/tests/State/WatchListUpdateProcessorTest.php b/tests/State/WatchListUpdateProcessorTest.php
index 0c1eefc..1d68eb2 100644
--- a/tests/State/WatchListUpdateProcessorTest.php
+++ b/tests/State/WatchListUpdateProcessorTest.php
@@ -45,6 +45,7 @@ final class WatchListUpdateProcessorTest extends ApiTestCase
'domains' => ['/api/domains/iana.org', '/api/domains/example.com'],
'name' => 'My modified Watchlist',
'trackedEvents' => ['last changed'],
+ 'trackedEppStatus' => [],
]]);
$this->assertResponseIsSuccessful();
$this->assertMatchesResourceItemJsonSchema(WatchList::class);
@@ -61,6 +62,7 @@ final class WatchListUpdateProcessorTest extends ApiTestCase
'domains' => $domains,
'name' => 'My Watchlist',
'trackedEvents' => ['last changed', 'transfer', 'expiration', 'deletion'],
+ 'trackedEppStatus' => ['redemption period', 'pending delete', 'client hold', 'server hold'],
'connector' => $connectorId,
]]);
diff --git a/translations/translations.pot b/translations/translations.pot
index b5d7fc3..967e157 100644
--- a/translations/translations.pot
+++ b/translations/translations.pot
@@ -44,8 +44,8 @@ msgstr ""
#: assets/components/RegisterForm.tsx:39
#: assets/components/RegisterForm.tsx:47
#: assets/components/search/DomainSearchBar.tsx:28
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:120
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:223
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:155
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:284
#: assets/utils/providers/forms/AutoDnsConnectorForm.tsx:21
#: assets/utils/providers/forms/AutoDnsConnectorForm.tsx:32
#: assets/utils/providers/forms/AutoDnsConnectorForm.tsx:47
@@ -164,72 +164,64 @@ msgid "Entities"
msgstr ""
#: assets/components/search/DomainSearchBar.tsx:31
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:123
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:158
msgid "This domain name does not appear to be valid"
msgstr ""
-#: assets/components/Sider.tsx:32
+#: assets/components/Sider.tsx:31
msgid "Home"
msgstr ""
-#: assets/components/Sider.tsx:38
+#: assets/components/Sider.tsx:37
msgid "Search"
msgstr ""
-#: assets/components/Sider.tsx:44
+#: assets/components/Sider.tsx:43
#: assets/components/tracking/watchlist/TrackedDomainTable.tsx:175
msgid "Domain"
msgstr ""
-#: assets/components/Sider.tsx:45
+#: assets/components/Sider.tsx:44
msgid "Domain Finder"
msgstr ""
-#: assets/components/Sider.tsx:52
-msgid "Entity"
-msgstr ""
-
-#: assets/components/Sider.tsx:53
-msgid "Entity Finder"
-msgstr ""
-
-#: assets/components/Sider.tsx:72
-#: assets/components/Sider.tsx:73
+#: assets/components/Sider.tsx:63
+#: assets/components/Sider.tsx:64
msgid "Infrastructure"
msgstr ""
-#: assets/components/Sider.tsx:79
+#: assets/components/Sider.tsx:70
#: assets/pages/StatisticsPage.tsx:114
#: assets/pages/infrastructure/TldPage.tsx:79
msgid "TLD"
msgstr ""
-#: assets/components/Sider.tsx:80
+#: assets/components/Sider.tsx:71
msgid "TLD list"
msgstr ""
-#: assets/components/Sider.tsx:87
-#: assets/components/Sider.tsx:88
+#: assets/components/Sider.tsx:78
+#: assets/components/Sider.tsx:79
msgid "ICANN list"
msgstr ""
-#: assets/components/Sider.tsx:96
+#: assets/components/Sider.tsx:87
msgid "Tracking"
msgstr ""
-#: assets/components/Sider.tsx:102
+#: assets/components/Sider.tsx:93
msgid "My Watchlists"
msgstr ""
-#: assets/components/Sider.tsx:109
+#: assets/components/Sider.tsx:100
msgid "Tracking table"
msgstr ""
-#: assets/components/Sider.tsx:116
+#: assets/components/Sider.tsx:107
msgid "My Connectors"
msgstr ""
-#: assets/components/Sider.tsx:140
+#: assets/components/Sider.tsx:131
#.
#. {
#. key: 'tools',
@@ -248,16 +240,16 @@ msgstr ""
msgid "Statistics"
msgstr ""
-#: assets/components/Sider.tsx:150
+#: assets/components/Sider.tsx:141
#: assets/pages/UserPage.tsx:17
msgid "My Account"
msgstr ""
-#: assets/components/Sider.tsx:155
+#: assets/components/Sider.tsx:146
msgid "Log out"
msgstr ""
-#: assets/components/Sider.tsx:163
+#: assets/components/Sider.tsx:154
#: assets/pages/LoginPage.tsx:35
#: assets/pages/LoginPage.tsx:45
msgid "Log in"
@@ -291,7 +283,7 @@ msgid "Next"
msgstr ""
#: assets/components/tracking/connector/ConnectorForm.tsx:96
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:270
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:331
msgid "Create"
msgstr ""
@@ -459,90 +451,100 @@ msgstr ""
msgid "Edit the Watchlist"
msgstr ""
-#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:45
+#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:46
msgid "Update a Watchlist"
msgstr ""
-#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:55
+#: assets/components/tracking/watchlist/UpdateWatchlistButton.tsx:56
msgid "Cancel"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistCard.tsx:35
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:46
msgid "This Watchlist is not linked to a Connector."
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistCard.tsx:40
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:51
msgid "Watchlist"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:76
-msgid "Name"
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:88
-msgid "Watchlist Name"
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:89
-msgid "Naming the Watchlist makes it easier to find in the list below."
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:100
-msgid "At least one domain name"
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:111
-msgid "Domain names"
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:129
-msgid "Domain name"
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:148
-msgid "Add a Domain name"
-msgstr ""
-
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:156
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:88
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:191
msgid "Tracked events"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:158
-msgid "At least one trigger"
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:110
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:217
+msgid "Tracked EPP status"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:182
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:197
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:111
+msgid "Name"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:123
+msgid "Watchlist Name"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:124
+msgid "Naming the Watchlist makes it easier to find in the list below."
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:135
+msgid "At least one domain name"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:146
+msgid "Domain names"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:164
+msgid "Domain name"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:183
+msgid "Add a Domain name"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:193
+msgid "At least one event"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:219
+msgid "At least one EPP status"
+msgstr ""
+
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:243
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:258
msgid "Connector"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:192
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:253
msgid ""
"Please make sure the connector information is valid to purchase a domain "
"that may be available soon."
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:214
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:275
msgid "DSN"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:226
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:287
msgid "This DSN does not appear to be valid"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:250
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:311
msgid "Check out this link to the Symfony documentation to help you build the DSN"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:260
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:321
msgid "Add a Webhook"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:270
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:331
msgid "Update"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistForm.tsx:273
+#: assets/components/tracking/watchlist/WatchlistForm.tsx:334
msgid "Reset"
msgstr ""
@@ -579,17 +581,17 @@ msgid ""
msgstr ""
#: assets/pages/infrastructure/IcannRegistrarPage.tsx:111
-#: assets/utils/functions/rdapTranslation.ts:120
+#: assets/utils/functions/rdapTranslation.ts:125
msgid "Accredited"
msgstr ""
#: assets/pages/infrastructure/IcannRegistrarPage.tsx:116
-#: assets/utils/functions/rdapTranslation.ts:121
+#: assets/utils/functions/rdapTranslation.ts:126
msgid "Reserved"
msgstr ""
#: assets/pages/infrastructure/IcannRegistrarPage.tsx:121
-#: assets/utils/functions/rdapTranslation.ts:119
+#: assets/utils/functions/rdapTranslation.ts:124
msgid "Terminated"
msgstr ""
@@ -723,15 +725,15 @@ msgstr ""
msgid "Create a Connector"
msgstr ""
-#: assets/pages/tracking/WatchlistPage.tsx:43
+#: assets/pages/tracking/WatchlistPage.tsx:45
msgid "Watchlist created !"
msgstr ""
-#: assets/pages/tracking/WatchlistPage.tsx:55
+#: assets/pages/tracking/WatchlistPage.tsx:57
msgid "Watchlist updated !"
msgstr ""
-#: assets/pages/tracking/WatchlistPage.tsx:79
+#: assets/pages/tracking/WatchlistPage.tsx:81
msgid "Create a Watchlist"
msgstr ""
@@ -953,102 +955,45 @@ msgid ""
"has expired or will expire at a predetermined date and time."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:76
-msgid ""
-"Signifies that the data of the object instance has been found to be "
-"accurate."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:77
-msgid "Renewal or reregistration of the object instance is forbidden."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:78
-msgid "Updates to the object instance are forbidden."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:79
-msgid "Transfers of the registration from one registrar to another are forbidden."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:80
-msgid "Deletion of the registration of the object instance is forbidden."
-msgstr ""
-
+#: assets/utils/functions/rdapTranslation.ts:72
#: assets/utils/functions/rdapTranslation.ts:81
-msgid "The registration of the object instance has been performed by a third party."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:82
-msgid ""
-"The information of the object instance is not designated for public "
-"consumption."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:83
-msgid ""
-"Some of the information of the object instance has not been made available "
-"and has been removed."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:84
-msgid ""
-"Some of the information of the object instance has been altered for the "
-"purposes of not readily revealing the actual information of the object "
-"instance."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:85
-msgid ""
-"The object instance is associated with other object instances in the "
-"registry."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:86
-msgid ""
-"Changes to the object instance cannot be made, including the association of "
-"other object instances."
-msgstr ""
-
-#: assets/utils/functions/rdapTranslation.ts:88
-#: assets/utils/functions/rdapTranslation.ts:97
msgid ""
"This is the standard status for a domain, meaning it has no pending "
"operations or prohibitions."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:89
+#: assets/utils/functions/rdapTranslation.ts:73
msgid ""
"This status code indicates that delegation information (name servers) has "
"not been associated with your domain. Your domain is not activated in the "
"DNS and will not resolve."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:90
+#: assets/utils/functions/rdapTranslation.ts:74
msgid ""
"This status code indicates that a request to create your domain has been "
"received and is being processed."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:91
+#: assets/utils/functions/rdapTranslation.ts:75
msgid ""
"This status code indicates that a request to renew your domain has been "
"received and is being processed."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:92
+#: assets/utils/functions/rdapTranslation.ts:76
msgid ""
"This status code indicates that a request to transfer your domain to a new "
"registrar has been received and is being processed."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:93
+#: assets/utils/functions/rdapTranslation.ts:77
msgid ""
"This status code indicates that a request to update your domain has been "
"received and is being processed."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:94
+#: assets/utils/functions/rdapTranslation.ts:78
msgid ""
"This status code may be mixed with redemptionPeriod or pendingRestore. In "
"such case, depending on the status (i.e. redemptionPeriod or "
@@ -1063,7 +1008,7 @@ msgid ""
"policies."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:95
+#: assets/utils/functions/rdapTranslation.ts:79
msgid ""
"This grace period is provided after the initial registration of a domain "
"name. If the registrar deletes the domain name during this period, the "
@@ -1071,7 +1016,7 @@ msgid ""
"registration."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:96
+#: assets/utils/functions/rdapTranslation.ts:80
msgid ""
"This grace period is provided after a domain name registration period "
"expires and is extended (renewed) automatically by the registry. If the "
@@ -1079,13 +1024,13 @@ msgid ""
"a credit to the registrar for the cost of the renewal."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:98
+#: assets/utils/functions/rdapTranslation.ts:82
msgid ""
"This status code tells your domain's registry to reject requests to delete "
"the domain."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:99
+#: assets/utils/functions/rdapTranslation.ts:83
msgid ""
"This status code tells your domain's registry to not activate your domain "
"in the DNS and as a consequence, it will not resolve. It is an uncommon "
@@ -1093,26 +1038,26 @@ msgid ""
"your domain is subject to deletion."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:100
+#: assets/utils/functions/rdapTranslation.ts:84
msgid ""
"This status code tells your domain's registry to reject requests to renew "
"your domain. It is an uncommon status that is usually enacted during legal "
"disputes or when your domain is subject to deletion."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:101
+#: assets/utils/functions/rdapTranslation.ts:85
msgid ""
"This status code tells your domain's registry to reject requests to "
"transfer the domain from your current registrar to another."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:102
+#: assets/utils/functions/rdapTranslation.ts:86
msgid ""
"This status code tells your domain's registry to reject requests to update "
"the domain."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:103
+#: assets/utils/functions/rdapTranslation.ts:87
msgid ""
"This status code indicates that your registrar has asked the registry to "
"restore your domain that was in redemptionPeriod status. Your registry will "
@@ -1122,7 +1067,7 @@ msgid ""
"the restoration request, the domain will revert to redemptionPeriod status."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:104
+#: assets/utils/functions/rdapTranslation.ts:88
msgid ""
"This status code indicates that your registrar has asked the registry to "
"delete your domain. Your domain will be held in this status for 30 days. "
@@ -1131,7 +1076,7 @@ msgid ""
"registration."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:105
+#: assets/utils/functions/rdapTranslation.ts:89
msgid ""
"This grace period is provided after a domain name registration period is "
"explicitly extended (renewed) by the registrar. If the registrar deletes "
@@ -1139,14 +1084,14 @@ msgid ""
"registrar for the cost of the renewal."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:106
+#: assets/utils/functions/rdapTranslation.ts:90
msgid ""
"This status code prevents your domain from being deleted. It is an uncommon "
"status that is usually enacted during legal disputes, at your request, or "
"when a redemptionPeriod status is in place."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:107
+#: assets/utils/functions/rdapTranslation.ts:91
msgid ""
"This status code indicates your domain's Registry Operator will not allow "
"your registrar to renew your domain. It is an uncommon status that is "
@@ -1154,7 +1099,7 @@ msgid ""
"deletion."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:108
+#: assets/utils/functions/rdapTranslation.ts:92
msgid ""
"This status code prevents your domain from being transferred from your "
"current registrar to another. It is an uncommon status that is usually "
@@ -1162,20 +1107,20 @@ msgid ""
"redemptionPeriod status is in place."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:109
+#: assets/utils/functions/rdapTranslation.ts:93
msgid ""
"This status code locks your domain preventing it from being updated. It is "
"an uncommon status that is usually enacted during legal disputes, at your "
"request, or when a redemptionPeriod status is in place."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:110
+#: assets/utils/functions/rdapTranslation.ts:94
msgid ""
"This status code is set by your domain's Registry Operator. Your domain is "
"not activated in the DNS."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:111
+#: assets/utils/functions/rdapTranslation.ts:95
msgid ""
"This grace period is provided after the successful transfer of a domain "
"name from one registrar to another. If the new registrar deletes the domain "
@@ -1183,13 +1128,70 @@ msgid ""
"for the cost of the transfer."
msgstr ""
+#: assets/utils/functions/rdapTranslation.ts:104
+msgid ""
+"Signifies that the data of the object instance has been found to be "
+"accurate."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:105
+msgid "Renewal or reregistration of the object instance is forbidden."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:106
+msgid "Updates to the object instance are forbidden."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:107
+msgid "Transfers of the registration from one registrar to another are forbidden."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:108
+msgid "Deletion of the registration of the object instance is forbidden."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:109
+msgid "The registration of the object instance has been performed by a third party."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:110
+msgid ""
+"The information of the object instance is not designated for public "
+"consumption."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:111
+msgid ""
+"Some of the information of the object instance has not been made available "
+"and has been removed."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:112
+msgid ""
+"Some of the information of the object instance has been altered for the "
+"purposes of not readily revealing the actual information of the object "
+"instance."
+msgstr ""
+
#: assets/utils/functions/rdapTranslation.ts:113
msgid ""
+"The object instance is associated with other object instances in the "
+"registry."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:114
+msgid ""
+"Changes to the object instance cannot be made, including the association of "
+"other object instances."
+msgstr ""
+
+#: assets/utils/functions/rdapTranslation.ts:118
+msgid ""
"The object instance has been allocated administratively (i.e., not for use "
"by the recipient in their own right in operational networks)."
msgstr ""
-#: assets/utils/functions/rdapTranslation.ts:114
+#: assets/utils/functions/rdapTranslation.ts:119
msgid ""
"The object instance has been allocated to an IANA special-purpose address "
"registry."