diff --git a/assets/components/tracking/watchlist/CalendarWatchlistButton.tsx b/assets/components/tracking/watchlist/CalendarWatchlistButton.tsx
new file mode 100644
index 0000000..9e541bf
--- /dev/null
+++ b/assets/components/tracking/watchlist/CalendarWatchlistButton.tsx
@@ -0,0 +1,22 @@
+import {CalendarFilled} from "@ant-design/icons";
+import {t} from "ttag";
+import {Popover, QRCode, Typography} from "antd";
+import React from "react";
+import {Watchlist} from "../../../pages/tracking/WatchlistPage";
+
+export function CalendarWatchlistButton({watchlist}: { watchlist: Watchlist }) {
+
+ const icsResourceLink = `${window.location.origin}/api/watchlists/${watchlist.token}/calendar`
+
+ return
+ }>
+
+
+
+}
\ No newline at end of file
diff --git a/assets/components/tracking/watchlist/WatchlistCard.tsx b/assets/components/tracking/watchlist/WatchlistCard.tsx
new file mode 100644
index 0000000..2ef9827
--- /dev/null
+++ b/assets/components/tracking/watchlist/WatchlistCard.tsx
@@ -0,0 +1,87 @@
+import {Card, Divider, Flex, Space, Table, Tag, Typography} from "antd";
+import {DisconnectOutlined, LinkOutlined} from "@ant-design/icons";
+import {t} from "ttag";
+import {ViewDiagramWatchlistButton} from "./diagram/ViewDiagramWatchlistButton";
+import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
+import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
+import punycode from "punycode/punycode";
+import {actionToColor, domainEvent} from "../../search/EventTimeline";
+import React, {useState} from "react";
+import {Watchlist} from "../../../pages/tracking/WatchlistPage";
+import {Connector} from "../../../utils/api/connectors";
+import useBreakpoint from "../../../hooks/useBreakpoint";
+import {CalendarWatchlistButton} from "./CalendarWatchlistButton";
+
+export function WatchlistCard({watchlist, onUpdateWatchlist, connectors, onDelete}: {
+ watchlist: Watchlist,
+ onUpdateWatchlist: (values: { domains: string[], triggers: string[], token: string }) => Promise,
+ connectors: (Connector & { id: string })[],
+ onDelete: () => void
+}) {
+ const sm = useBreakpoint('sm')
+ const domainEventTranslated = domainEvent()
+
+ const columns = [
+ {
+ title: t`Domain names`,
+ dataIndex: 'domains'
+ },
+ {
+ title: t`Tracked events`,
+ dataIndex: 'events'
+ }
+ ]
+
+ return <>
+
+ {
+ watchlist.connector ?
+ } color="lime-inverse" title={watchlist.connector.id}/> :
+ } color="default"
+ title={t`This Watchlist is not linked to a Connector.`}/>
+ }
+
+ {t`Watchlist` + (watchlist.name ? ` (${watchlist.name})` : '')}
+
+ >
+ }
+ size='small'
+ style={{width: '100%'}}
+ extra={
+
+
+
+
+
+
+
+
+
+ }
+ >
+
+ {punycode.toUnicode(d.ldhName)}),
+ events: watchlist.triggers?.filter(t => t.action === 'email')
+ .map(t =>
+ {domainEventTranslated[t.event as keyof typeof domainEventTranslated]}
+
+ )
+ }]}
+ {...(sm ? {scroll: {y: 'max-content'}} : {scroll: {y: 240}})}
+ />
+
+
+ >
+}
\ No newline at end of file
diff --git a/assets/components/tracking/watchlist/WatchlistsList.tsx b/assets/components/tracking/watchlist/WatchlistsList.tsx
index aed54fd..2cb01f1 100644
--- a/assets/components/tracking/watchlist/WatchlistsList.tsx
+++ b/assets/components/tracking/watchlist/WatchlistsList.tsx
@@ -1,15 +1,7 @@
-import {Card, Divider, Space, Table, Tag, Typography} from "antd";
-import {t} from "ttag";
-import {CalendarFilled, DisconnectOutlined, LinkOutlined} from "@ant-design/icons";
import React from "react";
-import useBreakpoint from "../../../hooks/useBreakpoint";
-import {actionToColor, domainEvent} from "../../search/EventTimeline";
import {Watchlist} from "../../../pages/tracking/WatchlistPage";
-import punycode from "punycode/punycode";
import {Connector} from "../../../utils/api/connectors";
-import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
-import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
-import {ViewDiagramWatchlistButton} from "./diagram/ViewDiagramWatchlistButton";
+import {WatchlistCard} from "./WatchlistCard";
export function WatchlistsList({watchlists, onDelete, onUpdateWatchlist, connectors}: {
watchlists: Watchlist[],
@@ -17,79 +9,15 @@ export function WatchlistsList({watchlists, onDelete, onUpdateWatchlist, connect
onUpdateWatchlist: (values: { domains: string[], triggers: string[], token: string }) => Promise,
connectors: (Connector & { id: string })[]
}) {
- const sm = useBreakpoint('sm')
- const domainEventTranslated = domainEvent()
-
-
- const columns = [
- {
- title: t`Domain names`,
- dataIndex: 'domains'
- },
- {
- title: t`Tracked events`,
- dataIndex: 'events'
- }
- ]
return <>
{watchlists.map(watchlist =>
- <>
-
- {
- watchlist.connector ?
- } color="lime-inverse" title={watchlist.connector.id}/> :
- } color="default"
- title={t`This Watchlist is not linked to a Connector.`}/>
- }
-
- {t`Watchlist` + (watchlist.name ? ` (${watchlist.name})` : '')}
-
- >
- }
- size='small'
- style={{width: '100%'}}
- extra={
-
-
-
-
-
-
-
-
-
-
-
- }
- >
-
- {punycode.toUnicode(d.ldhName)}),
- events: watchlist.triggers?.filter(t => t.action === 'email')
- .map(t =>
- {domainEventTranslated[t.event as keyof typeof domainEventTranslated]}
-
- )
- }]}
- {...(sm ? {scroll: {y: 'max-content'}} : {scroll: {y: 240}})}
- />
-
-
- >
- )}
+
+ )
+ }
>
}
\ No newline at end of file
diff --git a/assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx b/assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx
index 75875b4..fbc4395 100644
--- a/assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx
+++ b/assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx
@@ -10,12 +10,6 @@ import {getLayoutedElements} from "./getLayoutedElements";
import {watchlistToNodes} from "./watchlistToNodes";
import {watchlistToEdges} from "./watchlistToEdges";
-export type DiagramConfig = {
- tld?: boolean
- nameserver?: boolean
- entities?: boolean
-}
-
export function ViewDiagramWatchlistButton({token}: { token: string }) {
const [open, setOpen] = useState(false)
@@ -24,9 +18,11 @@ export function ViewDiagramWatchlistButton({token}: { token: string }) {
const [edges, setEdges, onEdgesChange] = useEdgesState([])
useEffect(() => {
- setNodes([])
setEdges([])
+ setNodes([])
+ }, [])
+ useEffect(() => {
if (!open) return
setLoading(true)
getWatchlist(token).then(w => {
@@ -58,19 +54,22 @@ export function ViewDiagramWatchlistButton({token}: { token: string }) {
}
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
- width='85vw'
+ width='90vw'
+ height='100%'
>
-
+
diff --git a/assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx b/assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx
index 7284258..1111858 100644
--- a/assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx
+++ b/assets/components/tracking/watchlist/diagram/watchlistToEdges.tsx
@@ -40,9 +40,10 @@ export const tldToEdge = (d: Domain) => ({
label: t`Registry`
})
-export function watchlistToEdges(watchlist: Watchlist) {
- const entitiesEdges = watchlist.domains.map(d => domainEntitiesToEdges(d)).flat()
+export function watchlistToEdges(watchlist: Watchlist, withRegistrar = false, withTld = false) {
+ const entitiesEdges = watchlist.domains.map(d => domainEntitiesToEdges(d, withRegistrar)).flat()
const nameserversEdges = watchlist.domains.map(domainNSToEdges).flat()
+ const tldEdge = watchlist.domains.map(tldToEdge)
- return [...entitiesEdges, ...nameserversEdges]
+ return [...entitiesEdges, ...nameserversEdges, ...(withTld ? tldEdge : [])]
}
diff --git a/assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx b/assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx
index 30186cb..c2818d8 100644
--- a/assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx
+++ b/assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx
@@ -20,6 +20,7 @@ export const domainEntitiesToNode = (d: Domain, withRegistrar = false) => d.enti
return {
id: e.entity.handle,
+ type: e.roles.includes('registrant') || e.roles.includes('registrar') ? 'input' : 'output',
data: {label},
style: {
width: 200
@@ -30,6 +31,7 @@ export const domainEntitiesToNode = (d: Domain, withRegistrar = false) => d.enti
export const tldToNode = (tld: Tld) => ({
id: tld.tld,
data: {label: t`.${tld.tld} Registry`},
+ type: 'input',
style: {
width: 200
}
@@ -38,17 +40,18 @@ export const tldToNode = (tld: Tld) => ({
export const nsToNode = (ns: Nameserver) => ({
id: ns.ldhName,
data: {label: ns.ldhName},
+ type: 'output',
style: {
width: 200
}
})
-export function watchlistToNodes(watchlist: Watchlist) {
+export function watchlistToNodes(watchlist: Watchlist, withRegistrar = false, withTld = false) {
const domains = watchlist.domains.map(domainToNode)
- const entities = [...new Set(watchlist.domains.map(d => domainEntitiesToNode(d)).flat())]
+ const entities = [...new Set(watchlist.domains.map(d => domainEntitiesToNode(d, withRegistrar)).flat())]
const tlds = [...new Set(watchlist.domains.map(d => d.tld))].map(tldToNode)
- const nameservers = [...new Set(watchlist.domains.map(d => d.nameservers))].flat().map(nsToNode)
+ const nameservers = [...new Set(watchlist.domains.map(d => d.nameservers))].flat().map(nsToNode, withRegistrar)
- return [...domains, ...entities, ...nameservers]
+ return [...domains, ...entities, ...nameservers, ...(withTld ? tlds : [])]
}
\ No newline at end of file
diff --git a/translations/translations.pot b/translations/translations.pot
index 2a5dca5..32a8269 100644
--- a/translations/translations.pot
+++ b/translations/translations.pot
@@ -252,8 +252,8 @@ msgstr ""
msgid "At least one domain name"
msgstr ""
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:26
#: assets/components/tracking/watchlist/WatchlistForm.tsx:100
-#: assets/components/tracking/watchlist/WatchlistsList.tsx:26
msgid "Domain names"
msgstr ""
@@ -265,8 +265,8 @@ msgstr ""
msgid "Add a Domain name"
msgstr ""
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:30
#: assets/components/tracking/watchlist/WatchlistForm.tsx:142
-#: assets/components/tracking/watchlist/WatchlistsList.tsx:30
msgid "Tracked events"
msgstr ""
@@ -317,11 +317,11 @@ msgstr ""
msgid "Cancel"
msgstr ""
-#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:43
+#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:39
msgid "View the Watchlist Entity Diagram"
msgstr ""
-#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:48
+#: assets/components/tracking/watchlist/diagram/ViewDiagramWatchlistButton.tsx:44
msgid "Watchlist Entity Diagram"
msgstr ""
@@ -329,11 +329,19 @@ msgstr ""
msgid "Registry"
msgstr ""
-#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:32
+#: assets/components/tracking/watchlist/diagram/watchlistToNodes.tsx:33
#, javascript-format
msgid ".${ tld.tld } Registry"
msgstr ""
+#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:14
+msgid "QR Code for iCalendar export"
+msgstr ""
+
+#: assets/components/tracking/watchlist/CalendarWatchlistButton.tsx:17
+msgid "Export events to iCalendar format"
+msgstr ""
+
#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:12
#: assets/components/tracking/watchlist/DeleteWatchlistButton.tsx:19
msgid "Delete the Watchlist"
@@ -343,18 +351,14 @@ msgstr ""
msgid "Are you sure to delete this Watchlist?"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistsList.tsx:46
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:43
msgid "This Watchlist is not linked to a Connector."
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistsList.tsx:49
+#: assets/components/tracking/watchlist/WatchlistCard.tsx:46
msgid "Watchlist"
msgstr ""
-#: assets/components/tracking/watchlist/WatchlistsList.tsx:60
-msgid "Export events to iCalendar format"
-msgstr ""
-
#: assets/components/Sider.tsx:29
msgid "Home"
msgstr ""