mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
feat: udpate watchlist entity diagram
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import {Button, Checkbox, Form, FormInstance, Input, Popconfirm, Select, Space, Typography} from "antd";
|
||||
import React, {useState} from "react";
|
||||
import {Connector, ConnectorProvider} from "../../utils/api/connectors";
|
||||
import {Connector, ConnectorProvider} from "../../../utils/api/connectors";
|
||||
import {t} from "ttag";
|
||||
import {BankOutlined} from "@ant-design/icons";
|
||||
import {
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
ovhFields as ovhFieldsFunction,
|
||||
ovhPricingMode as ovhPricingModeFunction,
|
||||
ovhSubsidiaryList as ovhSubsidiaryListFunction
|
||||
} from "../../utils/providers/ovh";
|
||||
import {helpGetTokenLink, tosHyperlink} from "../../utils/providers";
|
||||
} from "../../../utils/providers/ovh";
|
||||
import {helpGetTokenLink, tosHyperlink} from "../../../utils/providers";
|
||||
|
||||
const formItemLayoutWithOutLabel = {
|
||||
wrapperCol: {
|
||||
@@ -2,7 +2,7 @@ import {Card, Divider, Popconfirm, theme, Typography} from "antd";
|
||||
import {t} from "ttag";
|
||||
import {DeleteFilled} from "@ant-design/icons";
|
||||
import React from "react";
|
||||
import {Connector, deleteConnector} from "../../utils/api/connectors";
|
||||
import {Connector, deleteConnector} from "../../../utils/api/connectors";
|
||||
|
||||
const {useToken} = theme;
|
||||
|
||||
@@ -2,50 +2,13 @@ import {Button, Flex, Modal, Space, Typography} from "antd"
|
||||
import {t} from "ttag"
|
||||
import React, {useEffect, useState} from "react"
|
||||
import {ApartmentOutlined} from "@ant-design/icons"
|
||||
import vCard from "vcf";
|
||||
|
||||
import '@xyflow/react/dist/style.css'
|
||||
import {Background, Controls, MiniMap, ReactFlow, useEdgesState, useNodesState} from "@xyflow/react";
|
||||
import {getWatchlist, Watchlist} from "../../utils/api";
|
||||
|
||||
import dagre from 'dagre'
|
||||
import vCard from "vcf";
|
||||
|
||||
const dagreGraph = new dagre.graphlib.Graph();
|
||||
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
||||
|
||||
const nodeWidth = 172;
|
||||
const nodeHeight = 200;
|
||||
|
||||
const getLayoutedElements = (nodes: any, edges: any, direction = 'TB') => {
|
||||
const isHorizontal = direction === 'LR';
|
||||
dagreGraph.setGraph({rankdir: direction});
|
||||
|
||||
nodes.forEach((node: any) => {
|
||||
dagreGraph.setNode(node.id, {width: nodeWidth, height: nodeHeight});
|
||||
});
|
||||
|
||||
edges.forEach((edge: any) => {
|
||||
dagreGraph.setEdge(edge.source, edge.target);
|
||||
});
|
||||
|
||||
dagre.layout(dagreGraph);
|
||||
|
||||
const newNodes = nodes.map((node: any) => {
|
||||
const nodeWithPosition = dagreGraph.node(node.id)
|
||||
|
||||
return {
|
||||
...node,
|
||||
targetPosition: isHorizontal ? 'left' : 'top',
|
||||
sourcePosition: isHorizontal ? 'right' : 'bottom',
|
||||
position: {
|
||||
x: nodeWithPosition.x - nodeWidth / 2,
|
||||
y: nodeWithPosition.y - nodeHeight / 2
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return {nodes: newNodes, edges};
|
||||
}
|
||||
import {getWatchlist, Watchlist} from "../../../utils/api";
|
||||
import {translateRoles} from "../../search/EntitiesList";
|
||||
import {getLayoutedElements} from "./getLayoutedElements";
|
||||
|
||||
|
||||
function watchlistToNodes(watchlist: Watchlist) {
|
||||
@@ -79,9 +42,12 @@ function watchlistToNodes(watchlist: Watchlist) {
|
||||
}
|
||||
|
||||
const rolesToColor = (roles: string[]) => roles.includes('registrant') ? 'green' :
|
||||
roles.includes('technical') ? 'orange' : 'black'
|
||||
roles.includes('administrative') ? 'blue' :
|
||||
roles.includes('technical') ? 'orange' : 'violet'
|
||||
|
||||
function watchlistToEdges(watchlist: Watchlist) {
|
||||
const domainRole = translateRoles()
|
||||
|
||||
return watchlist.domains
|
||||
.map(d => d.entities
|
||||
.filter(e => !e.roles.includes('registrar'))
|
||||
@@ -90,6 +56,7 @@ function watchlistToEdges(watchlist: Watchlist) {
|
||||
source: e.roles.includes('technical') ? d.ldhName : e.entity.handle,
|
||||
target: e.roles.includes('technical') ? e.entity.handle : d.ldhName,
|
||||
style: {stroke: rolesToColor(e.roles), strokeWidth: 3},
|
||||
label: e.roles.map(r => Object.keys(domainRole).includes(r) ? domainRole[r as keyof typeof domainRole] : r).join(', '),
|
||||
animated: e.roles.includes('registrant'),
|
||||
}))
|
||||
).flat(2)
|
||||
@@ -138,6 +105,10 @@ export function ViewDiagramWatchlistButton({token}: { token: string }) {
|
||||
>
|
||||
{nodes && edges && <Flex style={{width: '75vw', height: '80vh'}}>
|
||||
<ReactFlow
|
||||
fitView
|
||||
colorMode='system'
|
||||
nodesConnectable={false}
|
||||
edgesReconnectable={false}
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
39
assets/components/tracking/diagram/getLayoutedElements.tsx
Normal file
39
assets/components/tracking/diagram/getLayoutedElements.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import dagre from "dagre";
|
||||
|
||||
|
||||
const dagreGraph = new dagre.graphlib.Graph();
|
||||
dagreGraph.setDefaultEdgeLabel(() => ({}));
|
||||
|
||||
const nodeWidth = 172;
|
||||
const nodeHeight = 200;
|
||||
|
||||
export const getLayoutedElements = (nodes: any, edges: any, direction = 'TB') => {
|
||||
const isHorizontal = direction === 'LR';
|
||||
dagreGraph.setGraph({rankdir: direction});
|
||||
|
||||
nodes.forEach((node: any) => {
|
||||
dagreGraph.setNode(node.id, {width: nodeWidth, height: nodeHeight});
|
||||
});
|
||||
|
||||
edges.forEach((edge: any) => {
|
||||
dagreGraph.setEdge(edge.source, edge.target);
|
||||
});
|
||||
|
||||
dagre.layout(dagreGraph);
|
||||
|
||||
const newNodes = nodes.map((node: any) => {
|
||||
const nodeWithPosition = dagreGraph.node(node.id)
|
||||
|
||||
return {
|
||||
...node,
|
||||
targetPosition: isHorizontal ? 'left' : 'top',
|
||||
sourcePosition: isHorizontal ? 'right' : 'bottom',
|
||||
position: {
|
||||
x: nodeWithPosition.x - nodeWidth / 2,
|
||||
y: nodeWithPosition.y - nodeHeight / 2
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return {nodes: newNodes, edges};
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import {Popconfirm, theme, Typography} from "antd";
|
||||
import {t} from "ttag";
|
||||
import {deleteWatchlist} from "../../utils/api";
|
||||
import {deleteWatchlist} from "../../../utils/api";
|
||||
import {DeleteFilled} from "@ant-design/icons";
|
||||
import React from "react";
|
||||
import {Watchlist} from "../../pages/tracking/WatchlistPage";
|
||||
import {Watchlist} from "../../../pages/tracking/WatchlistPage";
|
||||
|
||||
export function DeleteWatchlistButton({watchlist, onDelete}: { watchlist: Watchlist, onDelete: () => void }) {
|
||||
const {token} = theme.useToken()
|
||||
@@ -2,9 +2,9 @@ import {Button, Drawer, Form, Typography} from "antd";
|
||||
import {t} from "ttag";
|
||||
import {WatchlistForm} from "./WatchlistForm";
|
||||
import React, {useState} from "react";
|
||||
import {Watchlist} from "../../pages/tracking/WatchlistPage";
|
||||
import {Watchlist} from "../../../pages/tracking/WatchlistPage";
|
||||
import {EditOutlined} from "@ant-design/icons";
|
||||
import {Connector} from "../../utils/api/connectors";
|
||||
import {Connector} from "../../../utils/api/connectors";
|
||||
|
||||
export function UpdateWatchlistButton({watchlist, onUpdateWatchlist, connectors}: {
|
||||
watchlist: Watchlist,
|
||||
@@ -2,8 +2,8 @@ import {Button, Form, FormInstance, Input, Select, SelectProps, Space, Tag} from
|
||||
import {t} from "ttag";
|
||||
import {ApiOutlined, MinusCircleOutlined, PlusOutlined} from "@ant-design/icons";
|
||||
import React from "react";
|
||||
import {Connector} from "../../utils/api/connectors";
|
||||
import {actionToColor, domainEvent} from "../search/EventTimeline";
|
||||
import {Connector} from "../../../utils/api/connectors";
|
||||
import {actionToColor, domainEvent} from "../../search/EventTimeline";
|
||||
|
||||
type TagRender = SelectProps['tagRender'];
|
||||
|
||||
@@ -2,14 +2,14 @@ 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 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 {Connector} from "../../../utils/api/connectors";
|
||||
import {UpdateWatchlistButton} from "./UpdateWatchlistButton";
|
||||
import {DeleteWatchlistButton} from "./DeleteWatchlistButton";
|
||||
import {ViewDiagramWatchlistButton} from "./ViewDiagramWatchlistButton";
|
||||
import {ViewDiagramWatchlistButton} from "../diagram/ViewDiagramWatchlistButton";
|
||||
|
||||
export function WatchlistsList({watchlists, onDelete, onUpdateWatchlist, connectors}: {
|
||||
watchlists: Watchlist[],
|
||||
Reference in New Issue
Block a user