From 995742ff7af7c0755f541e9f2524bcae5c2265b0 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 1 Jan 2025 18:52:21 +0200 Subject: [PATCH 01/10] check for multi edges on create instead per render --- app/components/graphView.tsx | 21 ------------ app/components/model.ts | 66 +++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index b754fd82..66d75a2d 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -221,20 +221,7 @@ export default function GraphView({ if (!start.x || !start.y || !end.x || !end.y) return - const sameNodesLinks = graph.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 - const even = index % 2 === 0 - let curve - if (start.id === end.id) { - if (even) { - curve = Math.floor(-(index / 2)) - 3 - } else { - curve = Math.floor((index + 1) / 2) + 2 - } - - link.curve = curve * 0.1 - const radius = NODE_SIZE * link.curve * 6.2; const angleOffset = -Math.PI / 4; // 45 degrees offset for text alignment const textX = start.x + radius * Math.cos(angleOffset); @@ -244,14 +231,6 @@ export default function GraphView({ ctx.translate(textX, textY); ctx.rotate(-angleOffset); } else { - if (even) { - curve = Math.floor(-(index / 2)) - } else { - curve = Math.floor((index + 1) / 2) - } - - link.curve = curve * 0.1 - const midX = (start.x + end.x) / 2 + (end.y - start.y) * (link.curve / 2); const midY = (start.y + end.y) / 2 + (start.x - end.x) * (link.curve / 2); diff --git a/app/components/model.ts b/app/components/model.ts index 44fd658d..23e18959 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -52,7 +52,7 @@ const COLORS_ORDER = [ "#80E6E6", ] -export function getCategoryColorValue(index: number): string { +export function getCategoryColorValue(index: number = 0): string { return COLORS_ORDER[index % COLORS_ORDER.length] } @@ -176,13 +176,41 @@ export class Graph { return } - let sourceId = edgeData.src_node; - let destinationId = edgeData.dest_node + let source = this.nodesMap.get(edgeData.src_node) + let target = this.nodesMap.get(edgeData.dest_node) + + if (!source) { + source = { + id: edgeData.src_node, + name: edgeData.src_node, + color: getCategoryColorValue(), + category: "", + expand: false, + visible: true, + collapsed, + isPath: !!path, + isPathSelected: path?.start?.id === edgeData.src_node || path?.end?.id === edgeData.src_node + } + } + + if (!target) { + target = { + id: edgeData.dest_node, + name: edgeData.dest_node, + color: getCategoryColorValue(), + category: "", + expand: false, + visible: true, + collapsed, + isPath: !!path, + isPathSelected: path?.start?.id === edgeData.dest_node || path?.end?.id === edgeData.dest_node + } + } link = { id: edgeData.id, - source: sourceId, - target: destinationId, + source, + target, label: edgeData.relation, visible: true, expand: false, @@ -196,6 +224,34 @@ export class Graph { newElements.links.push(link) }) + newElements.links.forEach(link => { + const start = link.source + const end = link.target + const sameNodesLinks = this.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) + const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 + const even = index % 2 === 0 + let curve + + if (start.id === end.id) { + if (even) { + curve = Math.floor(-(index / 2)) - 3 + } else { + curve = Math.floor((index + 1) / 2) + 2 + } + } else { + console.log(link.curve) + if (even) { + curve = Math.floor(-(index / 2)) + } else { + curve = Math.floor((index + 1) / 2) + } + + } + + link.curve = curve * 0.1 + }) + + return newElements } From 3cf7586f51fa75d3208ecf3354a8d27d43cbc5a9 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 6 Jan 2025 14:43:58 +0200 Subject: [PATCH 02/10] commit --- tailwind.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/tailwind.config.js b/tailwind.config.js index 14d51792..060cc1d9 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -79,6 +79,7 @@ module.exports = { animation: { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", + 'spin': 'spin 1s linear', }, }, }, From bde842e8ae84c045672a787ce59a49a6f4d52f66 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 6 Jan 2025 18:06:11 +0200 Subject: [PATCH 03/10] commit --- app/components/graphView.tsx | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 66d75a2d..f1030806 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -78,18 +78,7 @@ export default function GraphView({ setSelectedObjects([]) } - const handelNodeClick = (node: Node, evt: MouseEvent) => { - if (isShowPath) { - setPath(prev => { - if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { - return ({ start: { id: Number(node.id), name: node.name } }) - } else { - return ({ end: { id: Number(node.id), name: node.name }, start: prev.start }) - } - }) - return - } - + const handelNodeRightClick = (node: Node, evt: MouseEvent) => { if (evt.ctrlKey) { if (selectedObjects.some(obj => obj.id === node.id)) { setSelectedObjects(selectedObjects.filter(obj => obj.id !== node.id)) @@ -111,8 +100,20 @@ export default function GraphView({ setSelectedPathId(link.id) } - const handelNodeRightClick = async (node: Node) => { + const handelNodeClick = async (node: Node) => { + if (isShowPath) { + setPath(prev => { + if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { + return ({ start: { id: Number(node.id), name: node.name } }) + } else { + return ({ end: { id: Number(node.id), name: node.name }, start: prev.start }) + } + }) + return + } + const expand = !node.expand + if (expand) { const elements = await onFetchNode([node.id]) @@ -121,6 +122,7 @@ export default function GraphView({ title: `No neighbors found`, description: `No neighbors found`, }) + return } } else { From 6efd86154ee55bc0a5c44e451aaf1d30db8a11a1 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 8 Jan 2025 13:56:00 +0200 Subject: [PATCH 04/10] expand only on the seconde click --- app/components/graphView.tsx | 54 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index f1030806..4eb81d44 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -61,7 +61,7 @@ export default function GraphView({ }: Props) { const parentRef = useRef(null) - + const lastClick = useRef(new Date()) useEffect(() => { setCooldownTime(4000) setCooldownTicks(undefined) @@ -101,7 +101,35 @@ export default function GraphView({ } const handelNodeClick = async (node: Node) => { - if (isShowPath) { + const now = new Date() + + const isDoubleClick = now.getTime() - lastClick.current.getTime() < 1000 + lastClick.current = now + + if (isDoubleClick) { + const expand = !node.expand + + if (expand) { + const elements = await onFetchNode([node.id]) + + if (elements.nodes.length === 0) { + toast({ + title: `No neighbors found`, + description: `No neighbors found`, + }) + + return + } + } else { + deleteNeighbors([node]); + } + + node.expand = expand + + setSelectedObj(undefined) + setData({ ...graph.Elements }) + + } else if (isShowPath) { setPath(prev => { if (!prev?.start?.name || (prev.end?.name && prev.end?.name !== "")) { return ({ start: { id: Number(node.id), name: node.name } }) @@ -111,28 +139,6 @@ export default function GraphView({ }) return } - - const expand = !node.expand - - if (expand) { - const elements = await onFetchNode([node.id]) - - if (elements.nodes.length === 0) { - toast({ - title: `No neighbors found`, - description: `No neighbors found`, - }) - - return - } - } else { - deleteNeighbors([node]); - } - - node.expand = expand - - setSelectedObj(undefined) - setData({ ...graph.Elements }) } return ( From 9e2cf1ffca0e53967046dbec16b3f0c048f3f271 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Wed, 8 Jan 2025 15:23:46 +0200 Subject: [PATCH 05/10] fix zoom on search and in path --- app/components/chat.tsx | 18 ++++++++++++-- app/components/code-graph.tsx | 44 ++++++++++++++++++----------------- app/components/model.ts | 5 ++-- app/page.tsx | 1 + 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f11f2476..5a861f8f 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -9,6 +9,7 @@ import { cn } from "@/lib/utils"; import { TypeAnimation } from "react-type-animation"; import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { prepareArg } from "../utils"; +import { NodeObject } from "react-force-graph-2d"; type PathData = { nodes: any[] @@ -84,6 +85,7 @@ interface Props { isPathResponse: boolean | undefined setIsPathResponse: (isPathResponse: boolean | undefined) => void setData: Dispatch> + chartRef: any } const SUGGESTIONS = [ @@ -105,7 +107,7 @@ const RemoveLastPath = (messages: Message[]) => { return messages } -export function Chat({ repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData }: Props) { +export function Chat({ repo, path, setPath, graph, selectedPathId, isPathResponse, setIsPathResponse, setData, chartRef }: Props) { // Holds the messages in the chat const [messages, setMessages] = useState([]); @@ -131,7 +133,6 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons const p = paths.find((path) => [...path.links, ...path.nodes].some((e: any) => e.id === selectedPathId)) if (!p) return - handelSetSelectedPath(p) }, [selectedPathId]) @@ -154,6 +155,9 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons }, [isPathResponse]) const handelSetSelectedPath = (p: PathData) => { + const chart = chartRef.current + + if (!chart) return setSelectedPath(prev => { if (prev) { if (isPathResponse && paths.some((path) => [...path.nodes, ...path.links].every((e: any) => [...prev.nodes, ...prev.links].some((e: any) => e.id === e.id)))) { @@ -206,6 +210,9 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons }); } setData({ ...graph.Elements }) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => p.nodes.some(node => node.id === n.id)); + }, 0) } // A function that handles the change event of the url input box @@ -262,6 +269,10 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons } const handleSubmit = async () => { + const chart = chartRef.current + + if (!chart) return + setSelectedPath(undefined) if (!path?.start?.id || !path.end?.id) return @@ -297,6 +308,9 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setPath(undefined) setIsPathResponse(true) setData({ ...graph.Elements }) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => formattedPaths.some(p => p.nodes.some(node => node.id === n.id))); + }, 0) } const getTip = (disabled = false) => diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 83d27c88..0704da1f 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -14,6 +14,7 @@ import { Checkbox } from '@/components/ui/checkbox'; import dynamic from 'next/dynamic'; import { Position } from "./graphView"; import { prepareArg } from '../utils'; +import { NodeObject } from "react-force-graph-2d"; const GraphView = dynamic(() => import('./graphView')); @@ -208,34 +209,35 @@ export function CodeGraph({ nodes.forEach((node) => { node.expand = expand }) - + setSelectedObj(undefined) setData({ ...graph.Elements }) } const handelSearchSubmit = (node: any) => { - const n = { name: node.properties.name, id: node.id } - - let chartNode = graph.Elements.nodes.find(n => n.id == node.id) - - if (!chartNode?.visible) { - if (!chartNode) { - chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] - } else { - chartNode.visible = true - setCooldownTicks(undefined) - setCooldownTime(1000) - } - graph.visibleLinks(true, [chartNode.id]) - } - - setSearchNode(n) - setData({ ...graph.Elements }) - const chart = chartRef.current - + if (chart) { - chart.centerAt(chartNode.x, chartNode.y, 1000); + const n = { name: node.properties.name, id: node.id } + + let chartNode = graph.Elements.nodes.find(n => n.id == node.id) + + if (!chartNode?.visible) { + if (!chartNode) { + chartNode = graph.extend({ nodes: [node], edges: [] }).nodes[0] + } else { + chartNode.visible = true + setCooldownTicks(undefined) + setCooldownTime(1000) + } + graph.visibleLinks(true, [chartNode!.id]) + setData({ ...graph.Elements }) + } + + setSearchNode(n) + setTimeout(() => { + chart.zoomToFit(1000, 150, (n: NodeObject) => n.id === chartNode!.id); + }, 0) } } diff --git a/app/components/model.ts b/app/components/model.ts index 23e18959..080f7984 100644 --- a/app/components/model.ts +++ b/app/components/model.ts @@ -191,6 +191,7 @@ export class Graph { isPath: !!path, isPathSelected: path?.start?.id === edgeData.src_node || path?.end?.id === edgeData.src_node } + this.nodesMap.set(edgeData.src_node, source) } if (!target) { @@ -205,6 +206,7 @@ export class Graph { isPath: !!path, isPathSelected: path?.start?.id === edgeData.dest_node || path?.end?.id === edgeData.dest_node } + this.nodesMap.set(edgeData.dest_node, target) } link = { @@ -228,7 +230,7 @@ export class Graph { const start = link.source const end = link.target const sameNodesLinks = this.Elements.links.filter(l => (l.source.id === start.id && l.target.id === end.id) || (l.target.id === start.id && l.source.id === end.id)) - const index = sameNodesLinks.findIndex(l => l.id === link.id) || 0 + const index = sameNodesLinks.findIndex(l => l.id === link.id) ?? 0 const even = index % 2 === 0 let curve @@ -239,7 +241,6 @@ export class Graph { curve = Math.floor((index + 1) / 2) + 2 } } else { - console.log(link.curve) if (even) { curve = Math.floor(-(index / 2)) } else { diff --git a/app/page.tsx b/app/page.tsx index a58f1a56..ef7fa374 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -281,6 +281,7 @@ export default function Home() { Date: Sun, 19 Jan 2025 11:39:14 +0200 Subject: [PATCH 06/10] commit --- app/components/chat.tsx | 6 ++--- app/components/code-graph.tsx | 12 +++++----- app/components/elementMenu.tsx | 12 +++++----- app/components/graphView.tsx | 43 ++++++++++++++++++++++++---------- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 5a861f8f..6e2c127d 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -133,7 +133,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons const p = paths.find((path) => [...path.links, ...path.nodes].some((e: any) => e.id === selectedPathId)) if (!p) return - handelSetSelectedPath(p) + handleSetSelectedPath(p) }, [selectedPathId]) // Scroll to the bottom of the chat on new message @@ -154,7 +154,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setPaths([]) }, [isPathResponse]) - const handelSetSelectedPath = (p: PathData) => { + const handleSetSelectedPath = (p: PathData) => { const chart = chartRef.current if (!chart) return @@ -439,7 +439,7 @@ export function Chat({ repo, path, setPath, graph, selectedPathId, isPathRespons setIsPathResponse(undefined) } - handelSetSelectedPath(p) + handleSetSelectedPath(p) }} >

#{i + 1}

diff --git a/app/components/code-graph.tsx b/app/components/code-graph.tsx index 0704da1f..7a99062d 100644 --- a/app/components/code-graph.tsx +++ b/app/components/code-graph.tsx @@ -82,7 +82,7 @@ export function CodeGraph({ const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Delete') { if (selectedObj && selectedObjects.length === 0) return - handelRemove([...selectedObjects.map(obj => obj.id), selectedObj?.id].filter(id => id !== undefined)); + handleRemove([...selectedObjects.map(obj => obj.id), selectedObj?.id].filter(id => id !== undefined)); } }; @@ -214,7 +214,7 @@ export function CodeGraph({ setData({ ...graph.Elements }) } - const handelSearchSubmit = (node: any) => { + const handleSearchSubmit = (node: any) => { const chart = chartRef.current if (chart) { @@ -241,7 +241,7 @@ export function CodeGraph({ } } - const handelRemove = (ids: number[]) => { + const handleRemove = (ids: number[]) => { graph.Elements.nodes.forEach(node => { if (!ids.includes(node.id)) return node.visible = false @@ -274,7 +274,7 @@ export function CodeGraph({ value={searchNode.name} onValueChange={({ name }) => setSearchNode({ name })} icon={} - handleSubmit={handelSearchSubmit} + handleSubmit={handleSearchSubmit} node={searchNode} /> @@ -354,10 +354,10 @@ export function CodeGraph({ setPath(path) setSelectedObj(undefined) }} - handleRemove={handelRemove} + handleRemove={handleRemove} position={position} url={url} - handelExpand={handleExpand} + handleExpand={handleExpand} parentRef={containerRef} /> void; position: Position | undefined; url: string; - handelExpand: (nodes: Node[], expand: boolean) => void; + handleExpand: (nodes: Node[], expand: boolean) => void; parentRef: RefObject; } -export default function ElementMenu({ obj, objects, setPath, handleRemove, position, url, handelExpand, parentRef }: Props) { +export default function ElementMenu({ obj, objects, setPath, handleRemove, position, url, handleExpand, parentRef }: Props) { const [currentObj, setCurrentObj] = useState(); const [containerWidth, setContainerWidth] = useState(0); @@ -68,13 +68,13 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit @@ -114,13 +114,13 @@ export default function ElementMenu({ obj, objects, setPath, handleRemove, posit diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 4eb81d44..33d6f63d 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -1,7 +1,7 @@ import ForceGraph2D from 'react-force-graph-2d'; import { Graph, GraphData, Link, Node } from './model'; -import { Dispatch, RefObject, SetStateAction, useEffect, useRef } from 'react'; +import { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react'; import { toast } from '@/components/ui/use-toast'; import { Path } from '../page'; @@ -61,7 +61,23 @@ export default function GraphView({ }: Props) { const parentRef = useRef(null) - const lastClick = useRef(new Date()) + const lastClick = useRef<{ date: Date, name: string }>({ date: new Date(), name: "" }) + const [parentWidth, setParentWidth] = useState(0) + const [parentHeight, setParentHeight] = useState(0) + + useEffect(() => { + if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return + chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) + chartRef.current.d3Force('charge').strength(-300) + chartRef.current.d3Force('center').strength(0.05) + }, [chartRef, data.links.length, data.nodes.length]) + + useEffect(() => { + if (!parentRef.current) return + setParentWidth(parentRef.current.clientWidth) + setParentHeight(parentRef.current.clientHeight) + }, [parentRef.current?.clientWidth, parentRef.current?.clientHeight]) + useEffect(() => { setCooldownTime(4000) setCooldownTicks(undefined) @@ -78,7 +94,7 @@ export default function GraphView({ setSelectedObjects([]) } - const handelNodeRightClick = (node: Node, evt: MouseEvent) => { + const handleNodeRightClick = (node: Node, evt: MouseEvent) => { if (evt.ctrlKey) { if (selectedObjects.some(obj => obj.id === node.id)) { setSelectedObjects(selectedObjects.filter(obj => obj.id !== node.id)) @@ -94,18 +110,19 @@ export default function GraphView({ setPosition({ x: evt.clientX, y: evt.clientY }) } - const handelLinkClick = (link: Link, evt: MouseEvent) => { + const handleLinkClick = (link: Link, evt: MouseEvent) => { unsetSelectedObjects(evt) if (!isPathResponse || link.id === selectedPathId) return setSelectedPathId(link.id) } - const handelNodeClick = async (node: Node) => { + const handleNodeClick = async (node: Node) => { const now = new Date() + const { date, name } = lastClick.current + + const isDoubleClick = now.getTime() - date.getTime() < 1000 && name === node.name + lastClick.current = { date: now, name: node.name } - const isDoubleClick = now.getTime() - lastClick.current.getTime() < 1000 - lastClick.current = now - if (isDoubleClick) { const expand = !node.expand @@ -145,8 +162,8 @@ export default function GraphView({
setPosition(prev => { return prev && { x: prev.x + translate.x * chartRef.current.zoom(), y: prev.y + translate.y * chartRef.current.zoom() } })} - onNodeRightClick={handelNodeRightClick} - onLinkClick={handelLinkClick} + onNodeRightClick={handleNodeRightClick} + onLinkClick={handleLinkClick} onBackgroundRightClick={unsetSelectedObjects} onBackgroundClick={unsetSelectedObjects} onZoom={() => unsetSelectedObjects()} From bed88d3f1f7a0a8ca22135cfc0122309f235d671 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:02:20 +0200 Subject: [PATCH 07/10] commit --- app/components/graphView.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index 33d6f63d..d76c912e 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -65,13 +65,6 @@ export default function GraphView({ const [parentWidth, setParentWidth] = useState(0) const [parentHeight, setParentHeight] = useState(0) - useEffect(() => { - if (!chartRef.current || data.nodes.length === 0 || data.links.length === 0) return - chartRef.current.d3Force('link').id((link: any) => link.id).distance(50) - chartRef.current.d3Force('charge').strength(-300) - chartRef.current.d3Force('center').strength(0.05) - }, [chartRef, data.links.length, data.nodes.length]) - useEffect(() => { if (!parentRef.current) return setParentWidth(parentRef.current.clientWidth) From 95518d407d2e0fe65c15a77399c9697b4a779103 Mon Sep 17 00:00:00 2001 From: Anchel135 Date: Mon, 20 Jan 2025 12:11:16 +0200 Subject: [PATCH 08/10] commit --- app/components/graphView.tsx | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/app/components/graphView.tsx b/app/components/graphView.tsx index d76c912e..f9b8714a 100644 --- a/app/components/graphView.tsx +++ b/app/components/graphView.tsx @@ -66,10 +66,25 @@ export default function GraphView({ const [parentHeight, setParentHeight] = useState(0) useEffect(() => { - if (!parentRef.current) return - setParentWidth(parentRef.current.clientWidth) - setParentHeight(parentRef.current.clientHeight) - }, [parentRef.current?.clientWidth, parentRef.current?.clientHeight]) + const handleResize = () => { + if (!parentRef.current) return + setParentWidth(parentRef.current.clientWidth) + setParentHeight(parentRef.current.clientHeight) + } + + window.addEventListener('resize', handleResize) + + const observer = new ResizeObserver(handleResize) + + if (parentRef.current) { + observer.observe(parentRef.current) + } + + return () => { + window.removeEventListener('resize', handleResize) + observer.disconnect() + } + }, [parentRef]) useEffect(() => { setCooldownTime(4000) From 8e5dc72a20fecb7f393ddca2fc299238b361e53a Mon Sep 17 00:00:00 2001 From: Naseem Ali <34807727+Naseem77@users.noreply.github.com> Date: Tue, 21 Jan 2025 17:29:32 +0200 Subject: [PATCH 09/10] fix test errors --- e2e/logic/POM/codeGraph.ts | 10 ++++++++-- e2e/tests/canvas.spec.ts | 3 +-- e2e/tests/chat.spec.ts | 5 +++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/e2e/logic/POM/codeGraph.ts b/e2e/logic/POM/codeGraph.ts index 9910ded3..5c3afa2c 100644 --- a/e2e/logic/POM/codeGraph.ts +++ b/e2e/logic/POM/codeGraph.ts @@ -152,6 +152,10 @@ export default class CodeGraph extends BasePage { return this.page.locator("//main[@data-name='main-chat']/*[last()-1]/p"); } + private get responseLoadingImg(): Locator { + return this.page.locator("//img[@alt='Waiting for response']"); + } + /* Canvas Locators*/ private get canvasElement(): Locator { @@ -277,7 +281,8 @@ export default class CodeGraph extends BasePage { } async getTextInLastChatElement(): Promise{ - await delay(2500); + await this.page.waitForSelector('img[alt="Waiting for response"]', { state: 'hidden' }); + await delay(2000); return (await this.lastElementInChat.textContent())!; } @@ -349,6 +354,7 @@ export default class CodeGraph extends BasePage { await this.selectGraphInComboBoxByName(graph).waitFor({ state : 'visible'}) await this.selectGraphInComboBoxByName(graph).click(); } + await delay(2000); // graph animation delay } async createProject(url : string): Promise { @@ -417,7 +423,7 @@ export default class CodeGraph extends BasePage { async nodeClick(x: number, y: number): Promise { await this.canvasElement.hover({ position: { x, y } }); - await this.canvasElement.click({ position: { x, y } }); + await this.canvasElement.click({ position: { x, y }, button: 'right' }); } async selectCodeGraphCheckbox(checkbox: string): Promise { diff --git a/e2e/tests/canvas.spec.ts b/e2e/tests/canvas.spec.ts index 3701ac86..022500e3 100644 --- a/e2e/tests/canvas.spec.ts +++ b/e2e/tests/canvas.spec.ts @@ -43,15 +43,14 @@ test.describe("Canvas tests", () => { test(`Verify center graph button centers nodes in canvas`, async () => { const codeGraph = await browser.createNewPage(CodeGraph, urls.baseUrl); await codeGraph.selectGraph(GRAPH_ID); + await codeGraph.clickCenter(); const initialGraph = await codeGraph.getCanvasScaling(); - await codeGraph.clickZoomOut(); await codeGraph.clickZoomOut(); await codeGraph.clickCenter(); const updatedGraph = await codeGraph.getCanvasScaling(); expect(Math.abs(initialGraph.scaleX - updatedGraph.scaleX)).toBeLessThanOrEqual(0.1); expect(Math.abs(initialGraph.scaleY - updatedGraph.scaleY)).toBeLessThanOrEqual(0.1); - }) nodes.slice(0,2).forEach((node) => { diff --git a/e2e/tests/chat.spec.ts b/e2e/tests/chat.spec.ts index 1f245f11..0d1f71cc 100644 --- a/e2e/tests/chat.spec.ts +++ b/e2e/tests/chat.spec.ts @@ -110,12 +110,15 @@ test.describe("Chat tests", () => { const result = await chat.getTextInLastChatElement(); const number = result.match(/\d+/g)?.[0]!; responses.push(number); + } const identicalResponses = responses.every((value) => value === responses[0]); expect(identicalResponses).toBe(true); }); test(`Validate UI response matches API response for a given question in chat`, async () => { + const api = new ApiCalls(); + const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); const chat = await browser.createNewPage(CodeGraph, urls.baseUrl); await chat.selectGraph(GRAPH_ID); @@ -123,8 +126,6 @@ test.describe("Chat tests", () => { const uiResponse = await chat.getTextInLastChatElement(); const number = uiResponse.match(/\d+/g)?.[0]!; - const api = new ApiCalls(); - const apiResponse = await api.askQuestion(PROJECT_NAME, Node_Question); expect(number).toEqual(apiResponse.result.response.match(/\d+/g)?.[0]); }); }); From 17d8fd85ca4ef3b600e91b388b68b2d036bfd9d1 Mon Sep 17 00:00:00 2001 From: Guy Korland Date: Wed, 22 Jan 2025 10:38:36 +0200 Subject: [PATCH 10/10] Remove 'spin' animation from config --- tailwind.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tailwind.config.js b/tailwind.config.js index 060cc1d9..14d51792 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -79,7 +79,6 @@ module.exports = { animation: { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", - 'spin': 'spin 1s linear', }, }, },