From a5d7ced6da89ef4e2fac86ea6120c4288c4637a6 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Tue, 9 Apr 2024 16:08:56 +0700 Subject: [PATCH 1/8] add filter for NFT --- public/locales/en/translation.json | 12 +++++++-- src/hooks/useTicketsType.ts | 7 +++++- .../Details/AddressDetails/AddressDetails.tsx | 16 ++++++++++-- src/pages/TicketsType/TicketList.tsx | 25 +++++++++++++++++++ src/pages/TicketsType/TicketsType.helpers.ts | 15 +++++++++++ src/pages/TicketsType/TicketsType.tsx | 17 ++++++++++++- src/routes/index.tsx | 11 ++++++++ 7 files changed, 97 insertions(+), 6 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index a2826df9..32273c5c 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -3370,8 +3370,16 @@ "message": "Total Cost", "description": "Used for the Tickets page" }, - "registeringSupernode": { - "message": "Registering Supernode", + "available": { + "message": "Yes", + "description": "Used for the Tickets page" + }, + "unAvailable": { + "message": "No", + "description": "Used for the Tickets page" + }, + "publiclyAccessible": { + "message": "Publicly Accessible", "description": "Used for the Tickets page" } }, diff --git a/src/hooks/useTicketsType.ts b/src/hooks/useTicketsType.ts index 08d4bb4a..cb743495 100644 --- a/src/hooks/useTicketsType.ts +++ b/src/hooks/useTicketsType.ts @@ -10,6 +10,7 @@ export default function useTicketsType( limit: number, period: string, status: string, + nftStatus: string, customDateRange: { startDate: number; endDate: number | null; @@ -21,6 +22,10 @@ export default function useTicketsType( if (status) { qStatus = `&status=${status}`; } + let qNftStatus = ''; + if (status) { + qNftStatus = `&nftStatus=${nftStatus}`; + } let dateParam = ''; if (customDateRange.startDate) { @@ -36,7 +41,7 @@ export default function useTicketsType( total: number; senses: TSenseRequests[]; }>( - `${URLS.GET_TICKETS}/${type}?offset=${offset}&limit=${limit}&sort=${sort}&type=${type}${dateParam}${qStatus}&include=all`, + `${URLS.GET_TICKETS}/${type}?offset=${offset}&limit=${limit}&sort=${sort}&type=${type}${dateParam}${qStatus}${qNftStatus}&include=all`, axiosGet, SWR_OPTIONS, ); diff --git a/src/pages/Details/AddressDetails/AddressDetails.tsx b/src/pages/Details/AddressDetails/AddressDetails.tsx index 9207ba48..7c66a876 100644 --- a/src/pages/Details/AddressDetails/AddressDetails.tsx +++ b/src/pages/Details/AddressDetails/AddressDetails.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { useParams } from 'react-router-dom'; +import { useParams, useNavigate } from 'react-router-dom'; import { CircularProgress, Grid } from '@mui/material'; import Box from '@mui/material/Box'; import Tooltip from '@mui/material/Tooltip'; @@ -10,7 +10,7 @@ import InfinityTable, { ISortData, } from '@components/InfinityTable/InfinityTable'; import { translate, translateDropdown } from '@utils/helpers/i18n'; - +import * as ROUTES from '@utils/constants/routes'; import { getCurrencyName, isPastelBurnAddress } from '@utils/appInfo'; import * as TableStyles from '@components/Table/Table.styles'; import Fire from '@components/SvgIcon/Fire'; @@ -35,6 +35,7 @@ interface IAddressDataRef { } const AddressDetails = () => { + const navigate = useNavigate(); const [status, setStatus] = useState(''); const { id } = useParams(); @@ -76,6 +77,17 @@ const AddressDetails = () => { } }; + useEffect(() => { + if ( + !swrData.isLoading && + !swrData?.data?.totalReceived && + !swrData?.data?.totalSent && + !swrData?.data?.balance?.length + ) { + navigate(ROUTES.NOT_FOUND); + } + }, [swrData]); + useEffect(() => { handleShowSubMenu(); window.addEventListener('resize', handleShowSubMenu); diff --git a/src/pages/TicketsType/TicketList.tsx b/src/pages/TicketsType/TicketList.tsx index 2b270c54..9cdfe466 100644 --- a/src/pages/TicketsType/TicketList.tsx +++ b/src/pages/TicketsType/TicketList.tsx @@ -64,6 +64,7 @@ import noImagePlaceholder from '@assets/images/no-image-placeholder.svg'; import { TICKET_TYPE_OPTIONS, TICKET_STATUS_OPTIONS, + NFT_TICKET_STATUS_OPTIONS, TICKET_SORT_OPTIONS, } from './TicketsType.helpers'; @@ -106,7 +107,9 @@ interface ITicketsList { handleSelectTime: (_event: MouseEvent) => void; selectedTime: string; onStatusChange: (_value: string) => void; + onNftStatusChange: (_value: string) => void; selectedStatus: string; + selectedNftStatus: string; onDateRangeApply?: (_startDate: number, _endDate: number | null) => void; defaultDateRange?: { startDate: number; @@ -124,7 +127,9 @@ const TicketsList: React.FC = ({ handleSelectTime, selectedTime, onStatusChange, + onNftStatusChange, selectedStatus, + selectedNftStatus, onDateRangeApply, defaultDateRange, ticketSort, @@ -361,6 +366,10 @@ const TicketsList: React.FC = ({ onStatusChange(event.target.value as string); }; + const handleNftStatusChange = (event: SelectChangeEvent) => { + onNftStatusChange(event.target.value as string); + }; + const handleSortChange = (event: SelectChangeEvent) => { onTicketSortChange(event.target.value as string); }; @@ -372,6 +381,13 @@ const TicketsList: React.FC = ({ })); }; + const getNftStatusOptions = () => { + return NFT_TICKET_STATUS_OPTIONS.map(option => ({ + ...option, + name: translateDropdown(option.name), + })); + }; + const getSortOptions = () => { return TICKET_SORT_OPTIONS.map(option => ({ ...option, @@ -410,6 +426,15 @@ const TicketsList: React.FC = ({ label={translateDropdown('pages.ticketsType.ticketType')} classNameWrapper="dropdown-ticket-type" /> + {['pastel-nft'].includes(ticketType) ? ( + + ) : null} {['sense', 'cascade'].includes(ticketType) ? ( <> { const [selectedType, setTicketType] = useState(type as string); const [selectedSort, setTicketSort] = useState(TICKET_SORT_OPTIONS[0].value); const [selectedStatus, setSelectedStatus] = useState(TICKET_STATUS_OPTIONS[0].value); + const [selectedNftStatus, setSelectedNftStatus] = useState( + NFT_TICKET_STATUS_OPTIONS[0].value, + ); const [selectedTime, setSelectedTime] = useState(blocksPeriodFilters[4].value); const [currentPage, setCurrentPage] = useState(0); const [customDateRange, setCustomDateRange] = useState<{ @@ -34,6 +41,7 @@ const TicketsType: React.FC = () => { LIMIT, selectedTime, selectedStatus, + selectedNftStatus, customDateRange, currentPage * LIMIT, selectedSort, @@ -73,6 +81,11 @@ const TicketsType: React.FC = () => { setSelectedStatus(value); }; + const handleNftStatusChange = (value: string) => { + setCurrentPage(0); + setSelectedNftStatus(value); + }; + const handleDateRangeApply = (_startDate: number, _endDate: number | null) => { setCurrentPage(0); setCustomDateRange({ @@ -104,7 +117,9 @@ const TicketsType: React.FC = () => { handleSelectTime={handleSelectTime} selectedTime={selectedTime} onStatusChange={handleStatusChange} + onNftStatusChange={handleNftStatusChange} selectedStatus={selectedStatus} + selectedNftStatus={selectedNftStatus} onDateRangeApply={handleDateRangeApply} /> diff --git a/src/routes/index.tsx b/src/routes/index.tsx index 47684082..a45c6732 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -72,6 +72,7 @@ const CascadeDetails = loadable(() => import('@pages/Details/CascadeDetails/Casc const NftDetails = loadable(() => import('@pages/Details/NftDetails/NftDetails')); const FeeSchedule = loadable(() => import('@pages/HistoricalStatistics/FeeSchedule')); const PSLBurnt = loadable(() => import('@pages/HistoricalStatistics/PSLBurnt')); +const Page404 = loadable(() => import('@pages/404/404')); const explorerRoutes = { id: 'routes.explorer', @@ -488,6 +489,15 @@ const nftDetailsRoutes = { children: null, }; +const page404Routes = { + id: 'routes.pages.content.message', + path: ROUTES.NOT_FOUND, + icon: , + component: Page404, + seoTitle: 'routes.pages.content.message', + children: null, +}; + export const pageRoutes = [ explorerRoutes, movementRoutes, @@ -531,6 +541,7 @@ export const pageRoutes = [ nftDetailsRoutes, feeScheduleStatisticsRoutes, pslBurntStatisticsRoutes, + page404Routes, ]; export const sidebarRoutes = [ From 205be3ad7ab9bcf87505a57dc41ed2d2596a99a0 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 3 May 2024 11:44:57 +0700 Subject: [PATCH 2/8] add graph for block detail page --- package.json | 3 + public/locales/en/translation.json | 17 +- .../BlockDetails/BlockDetails.helpers.tsx | 194 +++++++++ .../BlockDetails/BlockDetails.styles.ts | 6 + .../Details/BlockDetails/BlockDetails.tsx | 2 + src/pages/Details/BlockDetails/GraphChart.tsx | 105 +++++ src/utils/types/IAddress.ts | 9 + src/utils/types/IBlocks.ts | 2 + yarn.lock | 391 +++++++++++++++++- 9 files changed, 726 insertions(+), 3 deletions(-) create mode 100644 src/pages/Details/BlockDetails/GraphChart.tsx diff --git a/package.json b/package.json index 1b25e2f6..43b73a6f 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "axios": "1.6.7", "buffer": "6.0.3", "css-vendor": "2.0.8", + "dagre": "0.8.5", "date-fns": "3.3.1", "echarts": "5.5.0", "echarts-for-react": "3.0.2", @@ -76,6 +77,7 @@ "react-share": "5.1.0", "react-timeago": "7.2.0", "react-virtualized": "9.22.5", + "reactflow": "11.11.2", "redux": "5.0.1", "redux-persist": "6.0.0", "redux-thunk": "3.1.0", @@ -86,6 +88,7 @@ "devDependencies": { "@babel/plugin-proposal-private-property-in-object": "7.21.11", "@redux-devtools/extension": "3.3.0", + "@types/dagre": "0.7.52", "@types/enzyme": "3.10.18", "@types/file-saver": "2.0.7", "@types/jest": "29.5.12", diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 32273c5c..91c864b7 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1874,8 +1874,23 @@ "minedByPool": { "message": "Mined by a pool", "description": "Used for the CascadeAndSenseStatistics page" + }, + "chartTransactions": { + "message": "Transactions", + "description": "Used for the CascadeAndSenseStatistics page" + }, + "beforeTransactions": { + "message": "Before", + "description": "Used for the CascadeAndSenseStatistics page" + }, + "afterTransactions": { + "message": "After", + "description": "Used for the CascadeAndSenseStatistics page" + }, + "currentBalance": { + "message": "Current balance", + "description": "Used for the CascadeAndSenseStatistics page" } - }, "pastelIdDetails": { "tickets": { diff --git a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx index a4420d71..999b5e25 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx @@ -1,10 +1,19 @@ import { Grid, Typography } from '@mui/material'; import parse from 'html-react-parser'; +import { Node, Edge, Position, MarkerType } from 'reactflow'; +import dagre from 'dagre'; +import { getCurrencyName } from '@utils/appInfo'; +import { formatAddress } from '@utils/helpers/format'; +import { formatNumber } from '@utils/helpers/formatNumbers/formatNumbers'; +import { IBlock } from '@utils/types/IBlocks'; import { HeaderType } from '@components/Table/Table'; import * as Styles from './BlockDetails.styles'; +const dagreGraph = new dagre.graphlib.Graph(); +dagreGraph.setDefaultEdgeLabel(() => ({})); + export const blockHeaders: Array = [ { id: 1, header: 'pages.blockDetails.height' }, { id: 3, header: 'pages.blockDetails.confirmations' }, @@ -29,3 +38,188 @@ export const generateDetailsElement = (name: string, value: string) => ( ); + +export const getGraphChartData = (block: IBlock) => { + const nodes: Node[] = []; + const edges: Edge[] = []; + const position = { x: 0, y: 0 }; + + if (block.transactions?.length) { + nodes.push({ + id: `block-${block.height}`, + sourcePosition: 'right' as Position, + data: { label: `${block.height}` }, + position, + connectable: false, + style: { + borderRadius: '100%', + width: '45px', + height: '45px', + padding: '5px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + width: 135, + height: 45, + }); + + let counter = 1; + block.transactions.forEach(transaction => { + const addresses = block.addresses?.filter(e => e.transactionHash === transaction.id); + nodes.push({ + id: `node-block-trans-${counter}`, + sourcePosition: 'right' as Position, + targetPosition: 'left' as Position, + data: { label: `${counter}` }, + position, + style: { + borderRadius: '4px', + width: '18px', + height: '18px', + padding: '2px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#E8CD95', + color: '#000', + }, + width: 72, + height: 18, + }); + edges.push({ + id: `edges-node-block-trans-${counter}`, + source: `block-${block.height}`, + target: `node-block-trans-${counter}`, + label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + markerEnd: { + type: MarkerType.Arrow, + }, + }); + nodes.push({ + id: `trans-${transaction.id}`, + sourcePosition: 'right' as Position, + targetPosition: 'left' as Position, + data: { label: `${formatAddress(transaction.id, 5, -3)}` }, + position, + style: { + borderRadius: '100%', + width: '50px', + height: '50px', + padding: '5px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + fontSize: '8px', + }, + width: 150, + height: 50, + }); + edges.push({ + id: `edges-node-block-trans-trans-2-${counter}`, + source: `node-block-trans-${counter}`, + target: `trans-${transaction.id}`, + label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + markerEnd: { + type: MarkerType.Arrow, + }, + }); + counter += 1; + if (addresses?.length) { + nodes.push({ + id: `node-trans-address-${counter}`, + sourcePosition: 'right' as Position, + targetPosition: 'left' as Position, + data: { label: `${counter}` }, + position, + style: { + borderRadius: '4px', + width: '18px', + height: '18px', + padding: '2px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#E8CD95', + color: '#000', + }, + width: 72, + height: 18, + }); + edges.push({ + id: `edges-node-trans-address-${counter}`, + source: `trans-${transaction.id}`, + target: `node-trans-address-${counter}`, + label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + markerEnd: { + type: MarkerType.Arrow, + }, + }); + addresses.forEach((address, index) => { + nodes.push({ + id: `address-detail-${index}-${transaction.id}-${address.address}`, + sourcePosition: 'right' as Position, + targetPosition: 'left' as Position, + data: { label: `${formatAddress(address.address, 5, -3)}` }, + position, + style: { + borderRadius: '100%', + width: '50px', + height: '50px', + padding: '5px', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + fontSize: '8px', + }, + width: 200, + height: 25, + }); + edges.push({ + id: `node-trans-address-end-${index}-${transaction.id}-${address.address}-${counter}`, + source: `node-trans-address-${counter}`, + target: `address-detail-${index}-${transaction.id}-${address.address}`, + label: `${formatNumber(address.amount, { decimalsLength: 2 })} ${getCurrencyName()}`, + markerEnd: { + type: MarkerType.Arrow, + }, + }); + }); + counter += 1; + } + }); + } + + const isHorizontal = true; + dagreGraph.setGraph({ rankdir: 'LR' }); + nodes.forEach(node => { + dagreGraph.setNode(node.id, { width: node.width, height: node.height }); + }); + + edges.forEach(edge => { + dagreGraph.setEdge(edge.source, edge.target); + }); + + dagre.layout(dagreGraph); + + nodes.forEach(node => { + const newNode = node; + const nodeWithPosition = dagreGraph.node(node.id); + newNode.targetPosition = (isHorizontal ? 'left' : 'top') as Position; + newNode.sourcePosition = (isHorizontal ? 'right' : 'bottom') as Position; + + const width = node.width || 0; + const height = node.height || 0; + newNode.position = { + x: nodeWithPosition.x - width / 2, + y: nodeWithPosition.y - height / 2, + }; + + return newNode; + }); + + return { + nodes, + edges, + }; +}; diff --git a/src/pages/Details/BlockDetails/BlockDetails.styles.ts b/src/pages/Details/BlockDetails/BlockDetails.styles.ts index 34e09675..fe940ab0 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.styles.ts +++ b/src/pages/Details/BlockDetails/BlockDetails.styles.ts @@ -39,6 +39,12 @@ export const Wrapper = styled('div')` } } + .react-flow__panel.react-flow__attribution { + a { + font-size: 4px; + } + } + .custom-table { &.block { .table__row-header { diff --git a/src/pages/Details/BlockDetails/BlockDetails.tsx b/src/pages/Details/BlockDetails/BlockDetails.tsx index 3553896b..30f0eb5a 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.tsx @@ -38,6 +38,7 @@ import { blockHeaders, transactionHeaders, generateDetailsElement } from './Bloc import * as Styles from './BlockDetails.styles'; import TicketsList from './Tickets'; import MinedIcon from './MinedIcon'; +import GraphChart from './GraphChart'; const BlockDetails = () => { const navigate = useNavigate(); @@ -266,6 +267,7 @@ const BlockDetails = () => { blockWrapperClassName="mb-12" /> + {block?.tickets?.length ? ( diff --git a/src/pages/Details/BlockDetails/GraphChart.tsx b/src/pages/Details/BlockDetails/GraphChart.tsx new file mode 100644 index 00000000..e20ac756 --- /dev/null +++ b/src/pages/Details/BlockDetails/GraphChart.tsx @@ -0,0 +1,105 @@ +import { MouseEvent, useState } from 'react'; +import ReactFlow, { useNodesState, useEdgesState, Node } from 'reactflow'; +import { Typography, Popover, Box } from '@mui/material'; +import parse from 'html-react-parser'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import 'reactflow/dist/style.css'; + +import { getCurrencyName } from '@utils/appInfo'; +import { formatNumber } from '@utils/helpers/formatNumbers/formatNumbers'; +import { IBlock } from '@utils/types/IBlocks'; +import * as TableStyles from '@components/Table/Table.styles'; +import * as PastelIdStyles from '@pages/Details/PastelIdDetails/PastelIdDetails.styles'; +import * as SupernodesStyles from '@pages/Supernodes/Supernodes.styles'; +import { ITransactionAddress } from '@utils/types/IAddress'; +import { translate } from '@utils/helpers/i18n'; + +import * as Styles from './BlockDetails.styles'; +import { getGraphChartData } from './BlockDetails.helpers'; + +export default function GraphChart({ block }: { block: IBlock }) { + const data = getGraphChartData(block); + const [nodes] = useNodesState(data.nodes); + const [edges] = useEdgesState(data.edges); + const [anchorEl, setAnchorEl] = useState(null); + const [selectedAddress, setSelectedAddress] = useState(null); + + const handleNodeMouseEnter = (event: MouseEvent, node: Node) => { + const isAddress = node.id.indexOf('address-detail-') !== -1; + if (isAddress) { + if (anchorEl) { + setAnchorEl(null); + setSelectedAddress(null); + } else { + setAnchorEl(event.currentTarget as HTMLButtonElement); + const parseId = node.id.split('-'); + const currentAddress = block.addresses?.find( + add => + add.address === parseId[parseId.length - 1] && + add.transactionHash === parseId[parseId.length - 2], + ); + if (currentAddress) { + setSelectedAddress(currentAddress); + } + } + } + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const open = Boolean(anchorEl); + const id = open ? 'simple-popover' : undefined; + + return ( + + + + + {parse(translate('pages.blockDetails.chartTransactions'))} + + + + + + {selectedAddress ? ( + + + {parse(translate('pages.blockDetails.beforeTransactions'))}:{' '} + {formatNumber(selectedAddress.preTotal, { decimalsLength: 2 })}{' '} + {getCurrencyName()} + + + {parse(translate('pages.blockDetails.afterTransactions'))}:{' '} + {formatNumber(selectedAddress.amount + selectedAddress.preTotal, { + decimalsLength: 2, + })}{' '} + {getCurrencyName()} + + + {parse(translate('pages.blockDetails.currentBalance'))}:{' '} + {formatNumber(selectedAddress.total, { decimalsLength: 2 })} {getCurrencyName()} + + + ) : null} + + + + + ); +} diff --git a/src/utils/types/IAddress.ts b/src/utils/types/IAddress.ts index a797e5ba..44e26129 100644 --- a/src/utils/types/IAddress.ts +++ b/src/utils/types/IAddress.ts @@ -11,3 +11,12 @@ export interface IAddress { outgoingSum: number; data: Array; } + +export interface ITransactionAddress { + address: string; + transactionHash: string; + amount: number; + direction: string; + preTotal: number; + total: number; +} diff --git a/src/utils/types/IBlocks.ts b/src/utils/types/IBlocks.ts index eb5e03c1..af69b782 100644 --- a/src/utils/types/IBlocks.ts +++ b/src/utils/types/IBlocks.ts @@ -1,4 +1,5 @@ import { ITicket, TSenseRequests } from './ITransactions'; +import { ITransactionAddress } from './IAddress'; export interface IBlockTransaction { id: string; @@ -29,6 +30,7 @@ export interface IBlock { ticketsList: string; senses: TSenseRequests[]; type?: string; + addresses?: ITransactionAddress[]; } export interface IRawBlock { diff --git a/yarn.lock b/yarn.lock index 4159e9d3..c4882afc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2278,6 +2278,72 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== +"@reactflow/background@11.3.12": + version "11.3.12" + resolved "https://registry.yarnpkg.com/@reactflow/background/-/background-11.3.12.tgz#9c9491cce4659bae13074fcdb48ac25664879d3f" + integrity sha512-jBuWVb43JQy5h4WOS7G0PU8voGTEJNA+qDmx8/jyBtrjbasTesLNfQvboTGjnQYYiJco6mw5vrtQItAJDNoIqw== + dependencies: + "@reactflow/core" "11.11.2" + classcat "^5.0.3" + zustand "^4.4.1" + +"@reactflow/controls@11.2.12": + version "11.2.12" + resolved "https://registry.yarnpkg.com/@reactflow/controls/-/controls-11.2.12.tgz#85e2aa5de17e2af28a5ecf6a75bb9c828a20640b" + integrity sha512-L9F3+avFRShoprdT+5oOijm5gVsz2rqWCXBzOAgD923L1XFGIspdiHLLf8IlPGsT+mfl0GxbptZhaEeEzl1e3g== + dependencies: + "@reactflow/core" "11.11.2" + classcat "^5.0.3" + zustand "^4.4.1" + +"@reactflow/core@11.11.2": + version "11.11.2" + resolved "https://registry.yarnpkg.com/@reactflow/core/-/core-11.11.2.tgz#c62f78297bda9d2e86a12228617ec3f91fbd4b22" + integrity sha512-+GfgyskweL1PsgRSguUwfrT2eDotlFgaKfDLm7x0brdzzPJY2qbCzVetaxedaiJmIli3817iYbILvE9qLKwbRA== + dependencies: + "@types/d3" "^7.4.0" + "@types/d3-drag" "^3.0.1" + "@types/d3-selection" "^3.0.3" + "@types/d3-zoom" "^3.0.1" + classcat "^5.0.3" + d3-drag "^3.0.0" + d3-selection "^3.0.0" + d3-zoom "^3.0.0" + zustand "^4.4.1" + +"@reactflow/minimap@11.7.12": + version "11.7.12" + resolved "https://registry.yarnpkg.com/@reactflow/minimap/-/minimap-11.7.12.tgz#6b2fc671ee17e37ccd3bc038ae8d2121d0ce6291" + integrity sha512-SRDU77c2PCF54PV/MQfkz7VOW46q7V1LZNOQlXAp7dkNyAOI6R+tb9qBUtUJOvILB+TCN6pRfD9fQ+2T99bW3Q== + dependencies: + "@reactflow/core" "11.11.2" + "@types/d3-selection" "^3.0.3" + "@types/d3-zoom" "^3.0.1" + classcat "^5.0.3" + d3-selection "^3.0.0" + d3-zoom "^3.0.0" + zustand "^4.4.1" + +"@reactflow/node-resizer@2.2.12": + version "2.2.12" + resolved "https://registry.yarnpkg.com/@reactflow/node-resizer/-/node-resizer-2.2.12.tgz#df82a7dfba883afea6a01a9c8210008a1ddba01f" + integrity sha512-6LHJGuI1zHyRrZHw5gGlVLIWnvVxid9WIqw8FMFSg+oF2DuS3pAPwSoZwypy7W22/gDNl9eD1Dcl/OtFtDFQ+w== + dependencies: + "@reactflow/core" "11.11.2" + classcat "^5.0.4" + d3-drag "^3.0.0" + d3-selection "^3.0.0" + zustand "^4.4.1" + +"@reactflow/node-toolbar@1.3.12": + version "1.3.12" + resolved "https://registry.yarnpkg.com/@reactflow/node-toolbar/-/node-toolbar-1.3.12.tgz#89e7aa9d34b6213bb5e64c344d4e2e3cb7af3163" + integrity sha512-4kJRvNna/E3y2MZW9/80wTKwkhw4pLJiz3D5eQrD13XcmojSb1rArO9CiwyrI+rMvs5gn6NlCFB4iN1F+Q+lxQ== + dependencies: + "@reactflow/core" "11.11.2" + classcat "^5.0.3" + zustand "^4.4.1" + "@redux-devtools/extension@3.3.0": version "3.3.0" resolved "https://registry.yarnpkg.com/@redux-devtools/extension/-/extension-3.3.0.tgz#bc775d289f15604c472112920beac2cf4dbb7907" @@ -2574,6 +2640,221 @@ dependencies: "@types/node" "*" +"@types/d3-array@*": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" + integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + +"@types/d3-axis@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.6.tgz#e760e5765b8188b1defa32bc8bb6062f81e4c795" + integrity sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-brush@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.6.tgz#c2f4362b045d472e1b186cdbec329ba52bdaee6c" + integrity sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-chord@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.6.tgz#1706ca40cf7ea59a0add8f4456efff8f8775793d" + integrity sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg== + +"@types/d3-color@*": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.1.3.tgz#368c961a18de721da8200e80bf3943fb53136af2" + integrity sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A== + +"@types/d3-contour@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.6.tgz#9ada3fa9c4d00e3a5093fed0356c7ab929604231" + integrity sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg== + dependencies: + "@types/d3-array" "*" + "@types/geojson" "*" + +"@types/d3-delaunay@*": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz#185c1a80cc807fdda2a3fe960f7c11c4a27952e1" + integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== + +"@types/d3-dispatch@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7" + integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ== + +"@types/d3-drag@*", "@types/d3-drag@^3.0.1": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.7.tgz#b13aba8b2442b4068c9a9e6d1d82f8bcea77fc02" + integrity sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-dsv@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.7.tgz#0a351f996dc99b37f4fa58b492c2d1c04e3dac17" + integrity sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g== + +"@types/d3-ease@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.2.tgz#e28db1bfbfa617076f7770dd1d9a48eaa3b6c51b" + integrity sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA== + +"@types/d3-fetch@*": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.7.tgz#c04a2b4f23181aa376f30af0283dbc7b3b569980" + integrity sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA== + dependencies: + "@types/d3-dsv" "*" + +"@types/d3-force@*": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.9.tgz#dd96ccefba4386fe4ff36b8e4ee4e120c21fcf29" + integrity sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA== + +"@types/d3-format@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.4.tgz#b1e4465644ddb3fdf3a263febb240a6cd616de90" + integrity sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g== + +"@types/d3-geo@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.1.0.tgz#b9e56a079449174f0a2c8684a9a4df3f60522440" + integrity sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ== + dependencies: + "@types/geojson" "*" + +"@types/d3-hierarchy@*": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz#6023fb3b2d463229f2d680f9ac4b47466f71f17b" + integrity sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg== + +"@types/d3-interpolate@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz#412b90e84870285f2ff8a846c6eb60344f12a41c" + integrity sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA== + dependencies: + "@types/d3-color" "*" + +"@types/d3-path@*": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.1.0.tgz#2b907adce762a78e98828f0b438eaca339ae410a" + integrity sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ== + +"@types/d3-polygon@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.2.tgz#dfae54a6d35d19e76ac9565bcb32a8e54693189c" + integrity sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA== + +"@types/d3-quadtree@*": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz#d4740b0fe35b1c58b66e1488f4e7ed02952f570f" + integrity sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg== + +"@types/d3-random@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" + integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== + +"@types/d3-scale-chromatic@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" + integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== + +"@types/d3-scale@*": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" + integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + dependencies: + "@types/d3-time" "*" + +"@types/d3-selection@*", "@types/d3-selection@^3.0.3": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.10.tgz#98cdcf986d0986de6912b5892e7c015a95ca27fe" + integrity sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg== + +"@types/d3-shape@*": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.1.6.tgz#65d40d5a548f0a023821773e39012805e6e31a72" + integrity sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA== + dependencies: + "@types/d3-path" "*" + +"@types/d3-time-format@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.3.tgz#d6bc1e6b6a7db69cccfbbdd4c34b70632d9e9db2" + integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== + +"@types/d3-time@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" + integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + +"@types/d3-timer@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.2.tgz#70bbda77dc23aa727413e22e214afa3f0e852f70" + integrity sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw== + +"@types/d3-transition@*": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.8.tgz#677707f5eed5b24c66a1918cde05963021351a8f" + integrity sha512-ew63aJfQ/ms7QQ4X7pk5NxQ9fZH/z+i24ZfJ6tJSfqxJMrYLiK01EAs2/Rtw/JreGUsS3pLPNV644qXFGnoZNQ== + dependencies: + "@types/d3-selection" "*" + +"@types/d3-zoom@*", "@types/d3-zoom@^3.0.1": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.8.tgz#dccb32d1c56b1e1c6e0f1180d994896f038bc40b" + integrity sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw== + dependencies: + "@types/d3-interpolate" "*" + "@types/d3-selection" "*" + +"@types/d3@^7.4.0": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.4.3.tgz#d4550a85d08f4978faf0a4c36b848c61eaac07e2" + integrity sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww== + dependencies: + "@types/d3-array" "*" + "@types/d3-axis" "*" + "@types/d3-brush" "*" + "@types/d3-chord" "*" + "@types/d3-color" "*" + "@types/d3-contour" "*" + "@types/d3-delaunay" "*" + "@types/d3-dispatch" "*" + "@types/d3-drag" "*" + "@types/d3-dsv" "*" + "@types/d3-ease" "*" + "@types/d3-fetch" "*" + "@types/d3-force" "*" + "@types/d3-format" "*" + "@types/d3-geo" "*" + "@types/d3-hierarchy" "*" + "@types/d3-interpolate" "*" + "@types/d3-path" "*" + "@types/d3-polygon" "*" + "@types/d3-quadtree" "*" + "@types/d3-random" "*" + "@types/d3-scale" "*" + "@types/d3-scale-chromatic" "*" + "@types/d3-selection" "*" + "@types/d3-shape" "*" + "@types/d3-time" "*" + "@types/d3-time-format" "*" + "@types/d3-timer" "*" + "@types/d3-transition" "*" + "@types/d3-zoom" "*" + +"@types/dagre@0.7.52": + version "0.7.52" + resolved "https://registry.yarnpkg.com/@types/dagre/-/dagre-0.7.52.tgz#edbf0bca6922cd0ad1936a7486f9d03523d7565a" + integrity sha512-XKJdy+OClLk3hketHi9Qg6gTfe1F3y+UFnHxKA2rn9Dw+oXa4Gb378Ztz9HlMgZKSxpPmn4BNVh9wgkpvrK1uw== + "@types/enzyme@3.10.18": version "3.10.18" resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-3.10.18.tgz#86010e7cb56cf1450dd391b8cc3a788f6a6fadef" @@ -2633,6 +2914,11 @@ resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.7.tgz#8dbb2f24bdc7486c54aa854eb414940bbd056f7d" integrity sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A== +"@types/geojson@*": + version "7946.0.14" + resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613" + integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg== + "@types/graceful-fs@^4.1.2", "@types/graceful-fs@^4.1.3": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -4229,6 +4515,11 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== +classcat@^5.0.3, classcat@^5.0.4: + version "5.0.5" + resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.5.tgz#8c209f359a93ac302404a10161b501eba9c09c77" + integrity sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w== + classnames@^2.2.6, classnames@^2.3.2: version "2.5.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" @@ -4747,6 +5038,76 @@ csstype@^3.0.2, csstype@^3.1.3: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== +"d3-color@1 - 3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +"d3-dispatch@1 - 3": + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-ease@1 - 3": + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +"d3-interpolate@1 - 3": + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +"d3-timer@1 - 3": + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3": + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +dagre@0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" + integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== + dependencies: + graphlib "^2.1.8" + lodash "^4.17.15" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -6221,6 +6582,13 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphlib@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + gsap@3.12.5: version "3.12.5" resolved "https://registry.yarnpkg.com/gsap/-/gsap-3.12.5.tgz#136c02dad4c673b441bdb1ca00104bfcb4eae7f4" @@ -8377,7 +8745,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -10136,6 +10504,18 @@ react@18.2.0: dependencies: loose-envify "^1.1.0" +reactflow@11.11.2: + version "11.11.2" + resolved "https://registry.yarnpkg.com/reactflow/-/reactflow-11.11.2.tgz#4968866a9372e6004ad1e424a2141996f0ba769a" + integrity sha512-o1fT3stSdhzW+SedCGNSmEvZvULZygZIMLyW67NcWNZrgwx1wuJfzLg5fuQ0Nzf389wItumZX/zP3zdaPX7lEw== + dependencies: + "@reactflow/background" "11.3.12" + "@reactflow/controls" "11.2.12" + "@reactflow/core" "11.11.2" + "@reactflow/minimap" "11.7.12" + "@reactflow/node-resizer" "2.2.12" + "@reactflow/node-toolbar" "1.3.12" + read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" @@ -11629,7 +12009,7 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: +use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -12329,3 +12709,10 @@ zrender@5.5.0: integrity sha512-O3MilSi/9mwoovx77m6ROZM7sXShR/O/JIanvzTwjN3FORfLSr81PsUGd7jlaYOeds9d8tw82oP44+3YucVo+w== dependencies: tslib "2.3.0" + +zustand@^4.4.1: + version "4.5.2" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848" + integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g== + dependencies: + use-sync-external-store "1.2.0" From 345e262e181f7c9002360d87b8324ff91d822f97 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 3 May 2024 13:34:15 +0700 Subject: [PATCH 3/8] update UI for flow chart --- public/locales/en/translation.json | 2 +- .../BlockDetails/BlockDetails.helpers.tsx | 33 +++++----- .../BlockDetails/BlockDetails.styles.ts | 4 +- src/pages/Details/BlockDetails/GraphChart.tsx | 65 ++++++++++++++++++- 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 91c864b7..147873c9 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1876,7 +1876,7 @@ "description": "Used for the CascadeAndSenseStatistics page" }, "chartTransactions": { - "message": "Transactions", + "message": "Flow", "description": "Used for the CascadeAndSenseStatistics page" }, "beforeTransactions": { diff --git a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx index 999b5e25..31655704 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx @@ -52,16 +52,17 @@ export const getGraphChartData = (block: IBlock) => { position, connectable: false, style: { - borderRadius: '100%', - width: '45px', - height: '45px', + borderRadius: '4px', + width: '50px', + height: '30px', padding: '5px', display: 'flex', alignItems: 'center', justifyContent: 'center', + fontSize: '10px', }, - width: 135, - height: 45, + width: 150, + height: 30, }); let counter = 1; @@ -83,6 +84,7 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', backgroundColor: '#E8CD95', color: '#000', + fontSize: '10px', }, width: 72, height: 18, @@ -100,20 +102,20 @@ export const getGraphChartData = (block: IBlock) => { id: `trans-${transaction.id}`, sourcePosition: 'right' as Position, targetPosition: 'left' as Position, - data: { label: `${formatAddress(transaction.id, 5, -3)}` }, + data: { label: `${formatAddress(transaction.id, 3, -3)}` }, position, style: { - borderRadius: '100%', + borderRadius: '4px', width: '50px', - height: '50px', + height: '30px', padding: '5px', display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '8px', + fontSize: '10px', }, width: 150, - height: 50, + height: 30, }); edges.push({ id: `edges-node-block-trans-trans-2-${counter}`, @@ -142,6 +144,7 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', backgroundColor: '#E8CD95', color: '#000', + fontSize: '10px', }, width: 72, height: 18, @@ -160,20 +163,20 @@ export const getGraphChartData = (block: IBlock) => { id: `address-detail-${index}-${transaction.id}-${address.address}`, sourcePosition: 'right' as Position, targetPosition: 'left' as Position, - data: { label: `${formatAddress(address.address, 5, -3)}` }, + data: { label: `${formatAddress(address.address, 3, -3)}` }, position, style: { - borderRadius: '100%', + borderRadius: '4px', width: '50px', - height: '50px', + height: '30px', padding: '5px', display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '8px', + fontSize: '10px', }, width: 200, - height: 25, + height: 30, }); edges.push({ id: `node-trans-address-end-${index}-${transaction.id}-${address.address}-${counter}`, diff --git a/src/pages/Details/BlockDetails/BlockDetails.styles.ts b/src/pages/Details/BlockDetails/BlockDetails.styles.ts index fe940ab0..5bb2b489 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.styles.ts +++ b/src/pages/Details/BlockDetails/BlockDetails.styles.ts @@ -40,9 +40,7 @@ export const Wrapper = styled('div')` } .react-flow__panel.react-flow__attribution { - a { - font-size: 4px; - } + display: none; } .custom-table { diff --git a/src/pages/Details/BlockDetails/GraphChart.tsx b/src/pages/Details/BlockDetails/GraphChart.tsx index e20ac756..aa125a44 100644 --- a/src/pages/Details/BlockDetails/GraphChart.tsx +++ b/src/pages/Details/BlockDetails/GraphChart.tsx @@ -1,5 +1,14 @@ import { MouseEvent, useState } from 'react'; -import ReactFlow, { useNodesState, useEdgesState, Node } from 'reactflow'; +import ReactFlow, { + useNodesState, + useEdgesState, + Node, + // EdgeProps, + // getBezierPath, + // EdgeLabelRenderer, + // BaseEdge, + // EdgeTypes, +} from 'reactflow'; import { Typography, Popover, Box } from '@mui/material'; import parse from 'html-react-parser'; @@ -18,6 +27,52 @@ import { translate } from '@utils/helpers/i18n'; import * as Styles from './BlockDetails.styles'; import { getGraphChartData } from './BlockDetails.helpers'; +// const CustomEdge: FC = ({ +// id, +// sourceX, +// sourceY, +// targetX, +// targetY, +// sourcePosition, +// targetPosition, +// data, +// }) => { +// const [edgePath, labelX, labelY] = getBezierPath({ +// sourceX, +// sourceY, +// sourcePosition, +// targetX, +// targetY, +// targetPosition, +// }); + +// return ( +// <> +// +// +//
+// {data.label} adsdasd +//
+//
+// +// ); +// }; + +// const edgeTypes: EdgeTypes = { +// custom: CustomEdge, +// }; + export default function GraphChart({ block }: { block: IBlock }) { const data = getGraphChartData(block); const [nodes] = useNodesState(data.nodes); @@ -62,7 +117,13 @@ export default function GraphChart({ block }: { block: IBlock }) { - + Date: Fri, 3 May 2024 13:50:22 +0700 Subject: [PATCH 4/8] update layout for graph --- .../BlockDetails/BlockDetails.helpers.tsx | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx index 31655704..e1bdff4f 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx @@ -44,6 +44,12 @@ export const getGraphChartData = (block: IBlock) => { const edges: Edge[] = []; const position = { x: 0, y: 0 }; + const isHorizontal = block.transactions?.length < 3; + const nodeWidth = isHorizontal ? 150 : 50; + const nodeHeight = isHorizontal ? 30 : 90; + const edgeNodeWidth = isHorizontal ? 72 : 18; + const edgeNodeHeight = isHorizontal ? 18 : 72; + if (block.transactions?.length) { nodes.push({ id: `block-${block.height}`, @@ -61,8 +67,8 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', fontSize: '10px', }, - width: 150, - height: 30, + width: nodeWidth, + height: nodeHeight, }); let counter = 1; @@ -86,8 +92,8 @@ export const getGraphChartData = (block: IBlock) => { color: '#000', fontSize: '10px', }, - width: 72, - height: 18, + width: edgeNodeWidth, + height: edgeNodeHeight, }); edges.push({ id: `edges-node-block-trans-${counter}`, @@ -114,8 +120,8 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', fontSize: '10px', }, - width: 150, - height: 30, + width: nodeWidth, + height: nodeHeight, }); edges.push({ id: `edges-node-block-trans-trans-2-${counter}`, @@ -146,8 +152,8 @@ export const getGraphChartData = (block: IBlock) => { color: '#000', fontSize: '10px', }, - width: 72, - height: 18, + width: edgeNodeWidth, + height: edgeNodeHeight, }); edges.push({ id: `edges-node-trans-address-${counter}`, @@ -175,8 +181,8 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', fontSize: '10px', }, - width: 200, - height: 30, + width: nodeWidth, + height: nodeHeight, }); edges.push({ id: `node-trans-address-end-${index}-${transaction.id}-${address.address}-${counter}`, @@ -193,8 +199,7 @@ export const getGraphChartData = (block: IBlock) => { }); } - const isHorizontal = true; - dagreGraph.setGraph({ rankdir: 'LR' }); + dagreGraph.setGraph({ rankdir: isHorizontal ? 'LR' : 'TB' }); nodes.forEach(node => { dagreGraph.setNode(node.id, { width: node.width, height: node.height }); }); From 870d1d33ba02ed9ae8192452654e4f3b84f0a085 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 3 May 2024 14:27:56 +0700 Subject: [PATCH 5/8] update default zoom --- src/pages/Details/BlockDetails/GraphChart.tsx | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/pages/Details/BlockDetails/GraphChart.tsx b/src/pages/Details/BlockDetails/GraphChart.tsx index aa125a44..5857d4b1 100644 --- a/src/pages/Details/BlockDetails/GraphChart.tsx +++ b/src/pages/Details/BlockDetails/GraphChart.tsx @@ -3,6 +3,8 @@ import ReactFlow, { useNodesState, useEdgesState, Node, + useReactFlow, + ReactFlowProvider, // EdgeProps, // getBezierPath, // EdgeLabelRenderer, @@ -73,12 +75,14 @@ import { getGraphChartData } from './BlockDetails.helpers'; // custom: CustomEdge, // }; -export default function GraphChart({ block }: { block: IBlock }) { +function ReactFlowChart({ block }: { block: IBlock }) { const data = getGraphChartData(block); const [nodes] = useNodesState(data.nodes); const [edges] = useEdgesState(data.edges); const [anchorEl, setAnchorEl] = useState(null); const [selectedAddress, setSelectedAddress] = useState(null); + const [isDefaultZoom, setDefaultZoom] = useState(false); + const { zoomIn } = useReactFlow(); const handleNodeMouseEnter = (event: MouseEvent, node: Node) => { const isAddress = node.id.indexOf('address-detail-') !== -1; @@ -108,6 +112,17 @@ export default function GraphChart({ block }: { block: IBlock }) { const open = Boolean(anchorEl); const id = open ? 'simple-popover' : undefined; + const handleZoom = () => { + if (!isDefaultZoom && block.transactions.length > 2) { + setTimeout(() => { + for (let i = 0; i <= 2; i += 1) { + zoomIn(); + } + setDefaultZoom(true); + }, 500); + } + }; + return ( @@ -120,9 +135,10 @@ export default function GraphChart({ block }: { block: IBlock }) { ); } + +export default function GraphChart({ block }: { block: IBlock }) { + return ( + + + + ); +} From 5dcb3deeca559e8ed39820ccc1a392aa8a9b3e9d Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 3 May 2024 16:08:16 +0700 Subject: [PATCH 6/8] update layout for flow chart --- .../BlockDetails/BlockDetails.helpers.tsx | 40 +++++- src/pages/Details/BlockDetails/GraphChart.tsx | 125 +++++++++++------- 2 files changed, 111 insertions(+), 54 deletions(-) diff --git a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx index e1bdff4f..04b833c8 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx @@ -45,7 +45,7 @@ export const getGraphChartData = (block: IBlock) => { const position = { x: 0, y: 0 }; const isHorizontal = block.transactions?.length < 3; - const nodeWidth = isHorizontal ? 150 : 50; + const nodeWidth = isHorizontal ? 110 : 50; const nodeHeight = isHorizontal ? 30 : 90; const edgeNodeWidth = isHorizontal ? 72 : 18; const edgeNodeHeight = isHorizontal ? 18 : 72; @@ -99,10 +99,18 @@ export const getGraphChartData = (block: IBlock) => { id: `edges-node-block-trans-${counter}`, source: `block-${block.height}`, target: `node-block-trans-${counter}`, - label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + data: { + label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + isHorizontal, + type: 'block', + }, markerEnd: { type: MarkerType.Arrow, }, + type: 'custom', + style: { + fontSize: '10px', + }, }); nodes.push({ id: `trans-${transaction.id}`, @@ -127,10 +135,17 @@ export const getGraphChartData = (block: IBlock) => { id: `edges-node-block-trans-trans-2-${counter}`, source: `node-block-trans-${counter}`, target: `trans-${transaction.id}`, - label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + data: { + label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + isHorizontal, + }, markerEnd: { type: MarkerType.Arrow, }, + type: 'custom', + style: { + fontSize: '10px', + }, }); counter += 1; if (addresses?.length) { @@ -159,10 +174,17 @@ export const getGraphChartData = (block: IBlock) => { id: `edges-node-trans-address-${counter}`, source: `trans-${transaction.id}`, target: `node-trans-address-${counter}`, - label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + data: { + label: `${formatNumber(transaction.totalAmount, { decimalsLength: 2 })} ${getCurrencyName()}`, + isHorizontal, + }, markerEnd: { type: MarkerType.Arrow, }, + type: 'custom', + style: { + fontSize: '10px', + }, }); addresses.forEach((address, index) => { nodes.push({ @@ -188,10 +210,18 @@ export const getGraphChartData = (block: IBlock) => { id: `node-trans-address-end-${index}-${transaction.id}-${address.address}-${counter}`, source: `node-trans-address-${counter}`, target: `address-detail-${index}-${transaction.id}-${address.address}`, - label: `${formatNumber(address.amount, { decimalsLength: 2 })} ${getCurrencyName()}`, + data: { + label: `${formatNumber(address.amount, { decimalsLength: 2 })} ${getCurrencyName()}`, + type: 'address', + isHorizontal, + }, markerEnd: { type: MarkerType.Arrow, }, + type: 'custom', + style: { + fontSize: '10px', + }, }); }); counter += 1; diff --git a/src/pages/Details/BlockDetails/GraphChart.tsx b/src/pages/Details/BlockDetails/GraphChart.tsx index 5857d4b1..5cfa28c4 100644 --- a/src/pages/Details/BlockDetails/GraphChart.tsx +++ b/src/pages/Details/BlockDetails/GraphChart.tsx @@ -1,15 +1,17 @@ -import { MouseEvent, useState } from 'react'; +import { MouseEvent, useState, FC } from 'react'; import ReactFlow, { useNodesState, useEdgesState, Node, useReactFlow, ReactFlowProvider, - // EdgeProps, + EdgeProps, // getBezierPath, - // EdgeLabelRenderer, - // BaseEdge, - // EdgeTypes, + getSmoothStepPath, + EdgeLabelRenderer, + BaseEdge, + EdgeTypes, + MarkerType, } from 'reactflow'; import { Typography, Popover, Box } from '@mui/material'; import parse from 'html-react-parser'; @@ -29,51 +31,76 @@ import { translate } from '@utils/helpers/i18n'; import * as Styles from './BlockDetails.styles'; import { getGraphChartData } from './BlockDetails.helpers'; -// const CustomEdge: FC = ({ -// id, -// sourceX, -// sourceY, -// targetX, -// targetY, -// sourcePosition, -// targetPosition, -// data, -// }) => { -// const [edgePath, labelX, labelY] = getBezierPath({ -// sourceX, -// sourceY, -// sourcePosition, -// targetX, -// targetY, -// targetPosition, -// }); +const CustomEdge: FC = ({ + id, + sourceX, + sourceY, + targetX, + targetY, + sourcePosition, + targetPosition, + data, + markerEnd, + style, +}) => { + const [edgePath, labelX, labelY] = getSmoothStepPath({ + sourceX, + sourceY, + sourcePosition, + targetX, + targetY, + targetPosition, + borderRadius: 0, + }); -// return ( -// <> -// -// -//
-// {data.label} adsdasd -//
-//
-// -// ); -// }; + let transform = `translate(-30%, -55%) translate(${labelX}px,${labelY}px)`; + if (data?.type === 'address') { + transform = `translateX(-30%) translate(${labelX + 10}px,${targetY - 5}px)`; + } + if (!data.isHorizontal) { + transform = `translateX(-50%) translate(${targetX}px,${labelY + 10}px)`; + if (data?.type === 'address') { + transform = `translate(-50%, -50%) translate(${targetX}px,${labelY + 30}px)`; + } + if (data?.type === 'block') { + transform = `translateX(-50%) translate(${targetX}px,${labelY + 20}px)`; + } + } + return ( + <> + + + +
+ {data.label} +
+
+ + ); +}; -// const edgeTypes: EdgeTypes = { -// custom: CustomEdge, -// }; +const edgeTypes: EdgeTypes = { + custom: CustomEdge, +}; function ReactFlowChart({ block }: { block: IBlock }) { const data = getGraphChartData(block); @@ -136,7 +163,7 @@ function ReactFlowChart({ block }: { block: IBlock }) { nodes={nodes} edges={edges} onNodeClick={handleNodeMouseEnter} - // edgeTypes={edgeTypes} + edgeTypes={edgeTypes} fitView onInit={handleZoom} /> From 3983b7188d5bcb8f3f0d9ad4056fc485aa29a0ef Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 3 May 2024 16:17:36 +0700 Subject: [PATCH 7/8] update font size --- .../BlockDetails/BlockDetails.helpers.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx index 04b833c8..b443e351 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx @@ -65,7 +65,7 @@ export const getGraphChartData = (block: IBlock) => { display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '10px', + fontSize: '8px', }, width: nodeWidth, height: nodeHeight, @@ -90,7 +90,7 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', backgroundColor: '#E8CD95', color: '#000', - fontSize: '10px', + fontSize: '8px', }, width: edgeNodeWidth, height: edgeNodeHeight, @@ -109,7 +109,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '10px', + fontSize: '8px', }, }); nodes.push({ @@ -126,7 +126,7 @@ export const getGraphChartData = (block: IBlock) => { display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '10px', + fontSize: '8px', }, width: nodeWidth, height: nodeHeight, @@ -144,7 +144,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '10px', + fontSize: '8px', }, }); counter += 1; @@ -165,7 +165,7 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', backgroundColor: '#E8CD95', color: '#000', - fontSize: '10px', + fontSize: '8px', }, width: edgeNodeWidth, height: edgeNodeHeight, @@ -183,7 +183,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '10px', + fontSize: '8px', }, }); addresses.forEach((address, index) => { @@ -201,7 +201,7 @@ export const getGraphChartData = (block: IBlock) => { display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '10px', + fontSize: '8px', }, width: nodeWidth, height: nodeHeight, @@ -220,7 +220,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '10px', + fontSize: '8px', }, }); }); From eba5c4c9878b31b878c5bdf6d97ad5004a4b2207 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 3 May 2024 17:09:06 +0700 Subject: [PATCH 8/8] update font zise and position for edge --- .../BlockDetails/BlockDetails.helpers.tsx | 18 +++++++++--------- src/pages/Details/BlockDetails/GraphChart.tsx | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx index b443e351..e76a9426 100644 --- a/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx +++ b/src/pages/Details/BlockDetails/BlockDetails.helpers.tsx @@ -65,7 +65,7 @@ export const getGraphChartData = (block: IBlock) => { display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, width: nodeWidth, height: nodeHeight, @@ -90,7 +90,7 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', backgroundColor: '#E8CD95', color: '#000', - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, width: edgeNodeWidth, height: edgeNodeHeight, @@ -109,7 +109,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, }); nodes.push({ @@ -126,7 +126,7 @@ export const getGraphChartData = (block: IBlock) => { display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, width: nodeWidth, height: nodeHeight, @@ -144,7 +144,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, }); counter += 1; @@ -165,7 +165,7 @@ export const getGraphChartData = (block: IBlock) => { justifyContent: 'center', backgroundColor: '#E8CD95', color: '#000', - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, width: edgeNodeWidth, height: edgeNodeHeight, @@ -183,7 +183,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, }); addresses.forEach((address, index) => { @@ -201,7 +201,7 @@ export const getGraphChartData = (block: IBlock) => { display: 'flex', alignItems: 'center', justifyContent: 'center', - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, width: nodeWidth, height: nodeHeight, @@ -220,7 +220,7 @@ export const getGraphChartData = (block: IBlock) => { }, type: 'custom', style: { - fontSize: '8px', + fontSize: !isHorizontal ? '10px' : '8px', }, }); }); diff --git a/src/pages/Details/BlockDetails/GraphChart.tsx b/src/pages/Details/BlockDetails/GraphChart.tsx index 5cfa28c4..9f4b1379 100644 --- a/src/pages/Details/BlockDetails/GraphChart.tsx +++ b/src/pages/Details/BlockDetails/GraphChart.tsx @@ -53,7 +53,7 @@ const CustomEdge: FC = ({ borderRadius: 0, }); - let transform = `translate(-30%, -55%) translate(${labelX}px,${labelY}px)`; + let transform = `translate(-50%, -55%) translate(${labelX}px,${labelY}px)`; if (data?.type === 'address') { transform = `translateX(-30%) translate(${labelX + 10}px,${targetY - 5}px)`; } @@ -84,7 +84,7 @@ const CustomEdge: FC = ({ background: '#fff', padding: `0 5px`, borderRadius: 0, - fontSize: '8px', + fontSize: !data.isHorizontal ? '10px' : '8px', lineHeight: 1, fontWeight: 400, textAlign: 'left',