From fd323db6d036a05dd8c5e077840731bb0255a974 Mon Sep 17 00:00:00 2001 From: julius Date: Tue, 25 Feb 2025 18:36:58 +0100 Subject: [PATCH] feat: implement highlighting of mutuality --- analysis.py | 8 ++++++-- src/App.css | 41 +++++++++++++++++++++++++---------------- src/Network.tsx | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/analysis.py b/analysis.py index 2a95135..f53fe51 100644 --- a/analysis.py +++ b/analysis.py @@ -76,7 +76,11 @@ def graph_json(): "source": c.user, "target": p, "size": max(1.0 - 0.1 * i, 0.3), - "data": {"relation": 2}, + "data": { + "relation": 2, + "origSize": max(1.0 - 0.1 * i, 0.3), + "origFill": "#bed4ff", + }, } ) for p in c.hate: @@ -86,7 +90,7 @@ def graph_json(): "source": c.user, "target": p, "size": 0.3, - "data": {"relation": 0}, + "data": {"relation": 0, "origSize": 0.3, "origFill": "#ff7c7c"}, "fill": "#ff7c7c", } ) diff --git a/src/App.css b/src/App.css index 2490f01..c3cf7c7 100644 --- a/src/App.css +++ b/src/App.css @@ -28,33 +28,42 @@ footer { .controls { z-index: 9; position: absolute; - width: 240px; - right: 24px; top: 1vh; - padding: 16px; + right: 0px; + padding: 8px; + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 8px; .control { display: flex; flex-direction: row; - margin: 4px 2px; - background-color: aliceblue; + flex-wrap: wrap; + max-width: 240px; + margin: 0px; + background-color: #F0F8FFdd; - * { - margin: 4px; + .slider, + span { + padding-left: 4px; + padding-right: 4px; } } #three-slider { display: flex; flex-direction: row; + margin: auto; + justify-content: center; + align-items: center; } } /* The switch - the box around the slider */ .switch { position: relative; - width: 68px; - height: 42px; + width: 48px; + height: 24px; } /* Hide default HTML checkbox */ @@ -81,10 +90,10 @@ footer { .slider:before { position: absolute; content: ""; - height: 26px; - width: 26px; - left: 4px; - bottom: 4px; + height: 18px; + width: 18px; + left: 3px; + bottom: 3px; background-color: white; border-radius: 50%; -webkit-transition: .4s; @@ -100,9 +109,9 @@ input:focus+.slider { } input:checked+.slider:before { - -webkit-transform: translateX(26px); - -ms-transform: translateX(26px); - transform: translateX(26px); + -webkit-transform: translateX(24px); + -ms-transform: translateX(24px); + transform: translateX(24px); } .grey { diff --git a/src/Network.tsx b/src/Network.tsx index 97298a9..0f7fa5d 100644 --- a/src/Network.tsx +++ b/src/Network.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { apiAuth } from "./api"; import { GraphCanvas, GraphCanvasRef, GraphEdge, GraphNode, SelectionProps, SelectionResult, useSelection } from "reagraph"; import { customTheme } from "./NetworkTheme"; @@ -25,6 +25,7 @@ export const GraphComponent = () => { const [threed, setThreed] = useState(false); const [likes, setLikes] = useState(2); const [popularity, setPopularity] = useState(false); + const [mutuality, setMutuality] = useState(false); const logo = document.getElementById("logo") if (logo) { logo.className = "logo networkroute"; @@ -50,9 +51,11 @@ export const GraphComponent = () => { function handlePopularity() { setPopularity(!popularity) - //graphRef.current?.fitNodesInView(); - //graphRef.current?.centerGraph(); - //graphRef.current?.resetControls(); + } + + function handleMutuality() { + colorMatches(!mutuality); + setMutuality(!mutuality); } function showLabel() { @@ -63,6 +66,27 @@ export const GraphComponent = () => { } } + function findMatches(edges: GraphEdge[]) { + const adjacencyList = edges.map((edge) => edge.source + edge.target + edge.data.relation); + return edges.filter((edge) => adjacencyList.includes(edge.target + edge.source + edge.data.relation)) + } + //const matches = useMemo(() => findMatches(data.edges), []) + + function colorMatches(mutuality: boolean) { + const matches = findMatches(data.edges); + const newEdges = data.edges; + if (mutuality) { + newEdges.forEach((edge) => { if ((likes === 1 || edge.data.relation === likes) && matches.map((edge) => edge.id).includes(edge.id)) { edge.fill = "#9c3"; edge.size = edge.size * 1.5 } }) + } else { + newEdges.forEach((edge) => { if ((likes === 1 || edge.data.relation === likes) && matches.map((edge) => edge.id).includes(edge.id)) { edge.fill = edge.data.origFill; edge.size = edge.data.origSize } }) + } + setData({ nodes: data.nodes, edges: newEdges }) + } + useEffect(() => { + if (mutuality) colorMatches(false); + colorMatches(mutuality) + }, [likes]) + const { selections, actives, onNodeClick, onCanvasClick } = useCustomSelection({ ref: graphRef, nodes: data.nodes, @@ -77,6 +101,14 @@ export const GraphComponent = () => {
+
+
+ + +
+ mutuality +
+
2D