"use client"; import { useRef, useEffect, useState } from "react"; import mermaid from "mermaid"; import { Button, Card, Chip, Dialog, DialogActions, Tooltip, DialogContent, DialogContentText, DialogTitle, IconButton, List, TextField, } from "@mui/material"; //Icons import RefreshIcon from "@mui/icons-material/Refresh"; import ZoomInIcon from "@mui/icons-material/ZoomIn"; import ZoomOutIcon from "@mui/icons-material/ZoomOut"; import FullscreenIcon from "@mui/icons-material/Fullscreen"; import DownloadIcon from "@mui/icons-material/Download"; import ResetIcon from "@mui/icons-material/Autorenew"; import FilterAltIcon from "@mui/icons-material/FilterAlt"; import ContentCopyIcon from "@mui/icons-material/ContentCopy"; // Custom Components import { NoDataOverlay } from "../noDataOverlay"; import { LoadingOverlay } from "../join/loadingOverlay"; import { useGetAllEventmessages } from "@/api/eventmessages/eventmessages"; import { mutate } from "swr"; import { eventMessages, generateMermaidString, mermaidSample } from "./helpers"; import { iconMatch } from "@/config/config"; import CopyToClipboard from "../copy_to_clipboard"; import { formatDateTime } from "@/utils/helpers"; const SequenceDiagram = () => { const { data: eventMessagesData, isLoading: loadingEventMessages, swrKey: eventMessagesKeyFunc, } = useGetAllEventmessages(); const mermaidRef: any = useRef(null); const [scale, setScale] = useState(1); const [openFilters, setOpenFilters] = useState(false); const [sequenceNr, setSequenceNr] = useState(""); const hasData = eventMessagesData?.data; // const mermaidString = generateMermaidString(eventMessagesData?.data); const mermaidString = mermaidSample; useEffect(() => { if (!loadingEventMessages && hasData) mermaid.initialize({ startOnLoad: false, securityLevel: "loose", sequence: { mirrorActors: true, showSequenceNumbers: true, }, }); if (mermaidRef.current) { mermaidRef.current.innerHTML = mermaidString; mermaid.init(undefined, mermaidRef.current); } }, [loadingEventMessages, hasData, mermaidString]); useEffect(() => { if (mermaidRef.current) { const svg = mermaidRef.current.querySelector("svg"); if (svg) { svg.style.transform = `scale(${scale})`; svg.style.transformOrigin = "top left"; mermaidRef.current.style.width = `${ svg.getBoundingClientRect().width * scale }px`; mermaidRef.current.style.height = `${ svg.getBoundingClientRect().height * scale }px`; } } }, [scale]); const onRefresh = () => { const eventMessagesKey = typeof eventMessagesKeyFunc === "function" ? eventMessagesKeyFunc() : eventMessagesKeyFunc; if (eventMessagesKey) { mutate(eventMessagesKey); } }; const zoomIn = () => { setScale((scale) => scale * 1.1); }; const zoomOut = () => { setScale((scale) => scale / 1.1); }; const resetZoom = () => { setScale(1); }; const viewInFullScreen = () => { if (mermaidRef.current) { const svg = mermaidRef.current.querySelector("svg"); const serializer = new XMLSerializer(); const svgBlob = new Blob([serializer.serializeToString(svg)], { type: "image/svg+xml", }); const url = URL.createObjectURL(svgBlob); window.open(url, "_blank"); } }; const downloadAsPng = () => { if (mermaidRef.current) { const svg = mermaidRef.current.querySelector("svg"); const svgData = new XMLSerializer().serializeToString(svg); // Create a canvas element to convert SVG to PNG const canvas = document.createElement("canvas"); const svgSize = svg.getBoundingClientRect(); canvas.width = svgSize.width; canvas.height = svgSize.height; const ctx = canvas.getContext("2d"); const img = document.createElement("img"); img.onload = () => { ctx?.drawImage(img, 0, 0); const pngData = canvas.toDataURL("image/png"); // Trigger download const link = document.createElement("a"); link.download = "sequence-diagram.png"; link.href = pngData; link.click(); }; img.src = "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))); } }; const toggleFilters = () => { setOpenFilters((prevState) => !prevState); }; const onSearchBySeqNumber = (e: any) => { setSequenceNr(e.target.value); }; const copyToClipboard = (data: any) => { navigator.clipboard.writeText(JSON.stringify(data, null, 2)).then(() => { alert("JSON copied to clipboard!"); }); }; const isFilterMatch = (index: number) => { if (!sequenceNr) return true; const filterSeqNrInt = parseInt(sequenceNr, 10); return index + 1 === filterSeqNrInt; }; if (loadingEventMessages) return ; return ( <>
{hasData ? ( <>
) : (
)}
{openFilters && ( <> All Event Messages
{eventMessages .filter((_: any, index: number) => { return isFilterMatch(index); }) .map((message: any, index: number) => { const { msg_type_name: msgType, des_name, src_name, group, group_id, timestamp, src_did, des_did, msg, } = message; const formattedTimeStamp = formatDateTime(timestamp); const IconComponent = iconMatch[msgType]; return (
{IconComponent} {message.msg_type_name} Sender: {src_name} |{" "} Receiver: {des_name} {" "} |{" "} Group: {group} | Group ID: {group_id}
{formattedTimeStamp}
Event Message {sequenceNr ? sequenceNr : index++}
                                {JSON.stringify(message, null, 2)}
                              
); })}
)} ); }; export default SequenceDiagram;