{
"data": {
"mob.near": {
"widget": {
"VotersGraph": {
"": "State.init({ accountId: props.accountId });\n\nconst data = fetch(\n \"https://raw.githubusercontent.com/zavodil/near-nft-owners-list/main/output_election_votes.txt\"\n);\n\nconst [voters, setVoters] = useState(null);\n\nuseEffect(() => {\n if (!data.ok) {\n return;\n }\n const voters = {};\n Object.values(\n data.body\n .split(\"\\n\")\n .map((line) => line.split(\"|\"))\n .filter((data) => data.length === 5)\n ).forEach((item) => {\n const account_id = item[0];\n if (voters[account_id] == undefined) {\n voters[account_id] = {};\n }\n voters[account_id][item[3]] = item[4].toLowerCase();\n });\n setVoters(voters);\n}, [data]);\n\nif (!voters) {\n return \"Loading\";\n}\n\nconst [message, setMessage] = useState({\n nodes: [\n {\n id: \"A\",\n group: 1,\n },\n {\n id: \"B\",\n group: 1,\n },\n {\n id: \"C\",\n group: 1,\n },\n ],\n links: [\n {\n source: \"A\",\n target: \"B\",\n value: 1,\n },\n {\n source: \"B\",\n target: \"C\",\n value: 1,\n },\n {\n source: \"C\",\n target: \"A\",\n value: 1,\n },\n ],\n});\n\nuseEffect(() => {}, [voters]);\n\nconst code = `\n<!DOCTYPE html>\n<meta charset=\"utf-8\">\n\n<!-- Load d3.js -->\n<script src=\"https://d3js.org/d3.v6.js\"></script>\n\n<svg id=\"graph\"></svg>\n\n<script>\n\nconst run = (data) => {\n const width = 640;\n const height = 480;\n\n // Specify the color scale.\n const color = d3.scaleOrdinal(d3.schemeCategory10);\n\n // The force simulation mutates links and nodes, so create a copy\n // so that re-evaluating this cell produces the same result.\n const links = data.links.map(d => ({...d}));\n const nodes = data.nodes.map(d => ({...d}));\n\n // Create a simulation with several forces.\n const simulation = d3.forceSimulation(nodes)\n .force(\"link\", d3.forceLink(links).id(d => d.id))\n .force(\"charge\", d3.forceManyBody())\n .force(\"center\", d3.forceCenter(width / 2, height / 2))\n .on(\"tick\", ticked);\n\n // Create the SVG container.\n const svg = d3.select(\"#graph\")\n .attr(\"width\", width)\n .attr(\"height\", height)\n .attr(\"viewBox\", [0, 0, width, height])\n .attr(\"style\", \"max-width: 100%; height: auto;\");\n\n // Add a line for each link, and a circle for each node.\n const link = svg.append(\"g\")\n .attr(\"stroke\", \"#999\")\n .attr(\"stroke-opacity\", 0.6)\n .selectAll()\n .data(links)\n .join(\"line\")\n .attr(\"stroke-width\", d => Math.sqrt(d.value));\n\n const node = svg.append(\"g\")\n .attr(\"stroke\", \"#fff\")\n .attr(\"stroke-width\", 1.5)\n .selectAll()\n .data(nodes)\n .join(\"circle\")\n .attr(\"r\", 5)\n .attr(\"fill\", d => color(d.group));\n\n node.append(\"title\")\n .text(d => d.id);\n\n // Add a drag behavior.\n node.call(d3.drag()\n .on(\"start\", dragstarted)\n .on(\"drag\", dragged)\n .on(\"end\", dragended));\n\n // Set the position attributes of links and nodes each time the simulation ticks.\n function ticked() {\n link\n .attr(\"x1\", d => d.source.x)\n .attr(\"y1\", d => d.source.y)\n .attr(\"x2\", d => d.target.x)\n .attr(\"y2\", d => d.target.y);\n\n node\n .attr(\"cx\", d => d.x)\n .attr(\"cy\", d => d.y);\n }\n\n // Reheat the simulation when drag starts, and fix the subject position.\n function dragstarted(event) {\n if (!event.active) simulation.alphaTarget(0.3).restart();\n event.subject.fx = event.subject.x;\n event.subject.fy = event.subject.y;\n }\n\n // Update the subject (dragged node) position during drag.\n function dragged(event) {\n event.subject.fx = event.x;\n event.subject.fy = event.y;\n }\n\n // Restore the target alpha so the simulation cools after dragging ends.\n // Unfix the subject position now that it’s no longer being dragged.\n function dragended(event) {\n if (!event.active) simulation.alphaTarget(0);\n event.subject.fx = null;\n event.subject.fy = null;\n }\n\n // When this cell is re-run, stop the previous simulation. (This doesn’t\n // really matter since the target alpha is zero and the simulation will\n // stop naturally, but it’s a good practice.)\n // invalidation.then(() => simulation.stop());\n\n return simulation;\n};\n\nlet simulation = null;\n\nwindow.addEventListener(\"message\", (event) => {\n simulation && simulation.stop();\n simulation = run(event.data);\n});\n\n</script>\n`;\n\nconst [onMessage] = useState(() => {\n return (data) => {\n console.log(data);\n };\n});\n\nreturn (\n <iframe\n className=\"w-100 h-100\"\n style={{ minHeight: \"600px\" }}\n srcDoc={code}\n message={message}\n onMessage={onMessage}\n />\n);\n"
}
}
}
}
}