From bf601b57de9c1ca262c9eb81dc915497eb3efe37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=83=D0=BB?= Date: Sun, 22 Dec 2024 18:07:05 +0300 Subject: [PATCH 1/4] feat: add selection path state --- .../Graph/Cubes/SelectionDataNodes/index.tsx | 7 +++-- src/components/Universe/Graph/Cubes/index.tsx | 31 +------------------ src/components/Universe/Graph/constant.ts | 30 ++++++++++++++++++ src/stores/useGraphStore/index.ts | 9 ++++++ 4 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx index 4c4e693e2..fad8e94ea 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx @@ -31,9 +31,10 @@ export const SelectionDataNodes = memo(() => { const { normalizedSchemasByType } = useSchemaStore((s) => s) - const { selectionGraphData, setSelectionData, setSelectedNode, setSelectionGraphRadius } = useGraphStore( - useShallow((s) => s), - ) + const { selectionGraphData, selectionPath, setSelectionData, setSelectedNode, setSelectionGraphRadius } = + useGraphStore(useShallow((s) => s)) + + console.log(selectionPath) useEffect(() => { const structuredNodes = structuredClone(dataInitial?.nodes || []) diff --git a/src/components/Universe/Graph/Cubes/index.tsx b/src/components/Universe/Graph/Cubes/index.tsx index 8cfb6bcd6..4b9672456 100644 --- a/src/components/Universe/Graph/Cubes/index.tsx +++ b/src/components/Universe/Graph/Cubes/index.tsx @@ -7,42 +7,13 @@ import { useDataStore, useNodeTypes } from '~/stores/useDataStore' import { useGraphStore, useHoveredNode, useSelectedNode } from '~/stores/useGraphStore' import { NodeExtended } from '~/types' import { colors } from '~/utils' +import { COLORS_MAP } from '../constant' import { NodePoints } from './NodePoints' import { NodeWrapper } from './NodeWrapper' import { RelevanceBadges } from './RelevanceBadges' const POINTER_IN_DELAY = 200 -const COLORS_MAP = [ - '#fff', - '#9747FF', - '#00887A', - '#0098A6', - '#0288D1', - '#33691E', - '#465A65', - '#512DA7', - '#5C6BC0', - '#5D4038', - '#662C00', - '#689F39', - '#6B1B00', - '#750000', - '#78909C', - '#7E57C2', - '#8C6E63', - '#AA47BC', - '#BF360C', - '#C2175B', - '#EC407A', - '#EF6C00', - '#F5511E', - '#FF9696', - '#FFC064', - '#FFCD29', - '#FFEA60', -] - export const Cubes = memo(() => { const selectedNode = useSelectedNode() const hoveredNode = useHoveredNode() diff --git a/src/components/Universe/Graph/constant.ts b/src/components/Universe/Graph/constant.ts index 5c05f711f..c80036e18 100644 --- a/src/components/Universe/Graph/constant.ts +++ b/src/components/Universe/Graph/constant.ts @@ -19,3 +19,33 @@ export const getNodeColorByType = (nodeType: string, returnString?: boolean) => return color } + +export const COLORS_MAP = [ + '#fff', + '#9747FF', + '#00887A', + '#0098A6', + '#0288D1', + '#33691E', + '#465A65', + '#512DA7', + '#5C6BC0', + '#5D4038', + '#662C00', + '#689F39', + '#6B1B00', + '#750000', + '#78909C', + '#7E57C2', + '#8C6E63', + '#AA47BC', + '#BF360C', + '#C2175B', + '#EC407A', + '#EF6C00', + '#F5511E', + '#FF9696', + '#FFC064', + '#FFCD29', + '#FFEA60', +] diff --git a/src/stores/useGraphStore/index.ts b/src/stores/useGraphStore/index.ts index 02c54d9c2..55742ef4f 100644 --- a/src/stores/useGraphStore/index.ts +++ b/src/stores/useGraphStore/index.ts @@ -82,6 +82,7 @@ export type GraphStore = { simulationHelpers: SimulationHelpers isHovering: boolean activeEdge: Link | null + selectionPath: string[] setDisableCameraRotation: (rotation: boolean) => void setScrollEventsDisabled: (rotation: boolean) => void @@ -99,6 +100,7 @@ export type GraphStore = { simulationCreate: (nodes: Node[], links: Link[]) => void setIsHovering: (isHovering: boolean) => void removeSimulation: () => void + addToSelectionPath: (id: string) => void } const defaultData: Omit< @@ -121,6 +123,7 @@ const defaultData: Omit< | 'simulationCreate' | 'setIsHovering' | 'removeSimulation' + | 'addToSelectionPath' > = { data: null, simulation: null, @@ -138,6 +141,7 @@ const defaultData: Omit< showSelectionGraph: false, simulationHelpers: defaultSimulationHelpers, isHovering: false, + selectionPath: [], } export const useGraphStore = create()((set, get) => ({ @@ -158,6 +162,11 @@ export const useGraphStore = create()((set, get) => ({ setActiveEdge: (activeEdge) => { set({ activeEdge }) }, + addToSelectionPath: (id: string) => { + const { selectionPath } = get() + + set({ selectionPath: [...selectionPath, id] }) + }, setSelectedNode: (selectedNode) => { if (!selectedNode) { set({ From 438ae33b35bd03b7edbbdd7b39e7bca1bfefca4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=83=D0=BB?= Date: Mon, 23 Dec 2024 12:45:53 +0300 Subject: [PATCH 2/4] feat: selection path progress --- .../Graph/Cubes/SelectionDataNodes/index.tsx | 66 +++++++++---- src/stores/useGraphStore/index.ts | 4 +- src/types/index.ts | 99 +++++++++---------- 3 files changed, 98 insertions(+), 71 deletions(-) diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx index fad8e94ea..5ff99efbd 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx @@ -9,17 +9,17 @@ import { useDataStore } from '~/stores/useDataStore' import { useGraphStore, useSelectedNode, useSelectedNodeRelativeIds } from '~/stores/useGraphStore' import { useSchemaStore } from '~/stores/useSchemaStore' import { ForceSimulation } from '~/transformers/forceSimulation' -import { GraphData, Link, NodeExtended } from '~/types' +import { GraphData, Link, Node, NodeExtended } from '~/types' import { LinkPosition } from '../..' import { Connections } from './Connections' -import { Node } from './Node' +import { Node as GraphNode } from './Node' const MAX_LENGTH = 6 export const SelectionDataNodes = memo(() => { const [simulation2d, setSimulation2D] = useState(null) - const { dataInitial } = useDataStore((s) => s) + const { dataInitial, nodesNormalized } = useDataStore((s) => s) const selectedNode = useSelectedNode() const groupRef = useRef(null) @@ -37,23 +37,35 @@ export const SelectionDataNodes = memo(() => { console.log(selectionPath) useEffect(() => { - const structuredNodes = structuredClone(dataInitial?.nodes || []) const structuredLinks = structuredClone(dataInitial?.links || []) if (prevSelectedNodeId === selectedNode?.ref_id) { return } - const nodes = structuredNodes - .filter( - (f: NodeExtended) => f.ref_id === selectedNode?.ref_id || selectedNodeRelativeIds.includes(f?.ref_id || ''), - ) - .map((n: NodeExtended) => { - const fixedPosition = n.ref_id === selectedNode?.ref_id ? { fx: 0, fy: 0, fz: 0 } : {} + const pathNodes: NodeExtended[] = selectionPath + .slice(-3, -1) + .filter((id) => !!nodesNormalized.get(id)) + .map((i, index) => { + const node = nodesNormalized.get(i) as unknown as Node + + return { ...node, fx: -index * 50, fy: 0, fz: 0, x: 0, y: 0, z: 0 } + }) + + const graphNodes: NodeExtended[] = selectedNodeRelativeIds + .filter((id) => !!nodesNormalized.get(id)) + .map((id: string) => { + const node = nodesNormalized.get(id) as unknown as Node - return { ...n, x: 0, y: 0, z: 0, ...fixedPosition } + return { ...node, x: 0, y: 0, z: 0 } }) + const nodes: NodeExtended[] = [ + ...graphNodes, + ...pathNodes, + { ...selectedNode, x: 0, y: 0, z: 0, fx: 0, fy: 0, fz: 0 } as NodeExtended, + ] + if (nodes) { const links = structuredLinks.filter( (link: Link) => @@ -65,7 +77,15 @@ export const SelectionDataNodes = memo(() => { setSimulation2D(null) linksPositionRef.current = new Map() } - }, [dataInitial, selectedNode, selectedNodeRelativeIds, setSelectionData, prevSelectedNodeId]) + }, [ + dataInitial, + selectedNode, + selectedNodeRelativeIds, + setSelectionData, + prevSelectedNodeId, + selectionPath, + nodesNormalized, + ]) useEffect(() => { if (simulation2d || !selectionGraphData.nodes.length) { @@ -140,26 +160,32 @@ export const SelectionDataNodes = memo(() => { return } - const { x: sx, y: sy, z: sz } = sourceNode - const { x: tx, y: ty, z: tz } = targetNode + const { x: sx, y: sy } = sourceNode + const { x: tx, y: ty } = targetNode // Set positions for the link linksPositionRef.current.set(link.ref_id, { sx, sy, - sz, tx, ty, - tz, + sz: 0, + tz: 0, }) - const midPoint = new Vector3((sx + tx) / 2, (sy + ty) / 2, (sz + tz) / 2) + const midPoint = new Vector3((sx + tx) / 2, (sy + ty) / 2, 0) // Position the text - text.position.set(midPoint.x, midPoint.y, midPoint.z) + text.position.set(midPoint.x, midPoint.y, 1) + + // Calculate angle of rotation in 2D + const angle = Math.atan2(ty - sy, tx - sx) + + // Apply rotation to the text + text.rotation.set(0, 0, angle) // Only Z-axis rotation needed for 2D alignment // Set the line positions - Line.geometry.setPositions([sx, sy, sz, tx, ty, tz]) + Line.geometry.setPositions([sx, sy, 0, tx, ty, 0]) const { material } = Line @@ -196,7 +222,7 @@ export const SelectionDataNodes = memo(() => { {selectionGraphData?.nodes.map((node) => ( - handleSelect(node)} selected={node.ref_id === selectedNode?.ref_id} /> + handleSelect(node)} selected={node.ref_id === selectedNode?.ref_id} /> diff --git a/src/stores/useGraphStore/index.ts b/src/stores/useGraphStore/index.ts index 55742ef4f..c91a9c43f 100644 --- a/src/stores/useGraphStore/index.ts +++ b/src/stores/useGraphStore/index.ts @@ -174,10 +174,11 @@ export const useGraphStore = create()((set, get) => ({ selectedNode: null, disableCameraRotation: false, showSelectionGraph: false, + selectionPath: [], }) } - const { selectedNode: stateSelectedNode, simulation } = get() + const { selectedNode: stateSelectedNode, simulation, selectionPath } = get() if (stateSelectedNode?.ref_id !== selectedNode?.ref_id) { const selectedNodeWithCoordinates = @@ -188,6 +189,7 @@ export const useGraphStore = create()((set, get) => ({ selectedNode: selectedNodeWithCoordinates, disableCameraRotation: true, showSelectionGraph: !!selectedNode, + selectionPath: [...selectionPath, selectedNodeWithCoordinates.ref_id], }) } }, diff --git a/src/types/index.ts b/src/types/index.ts index 9fdd137db..f33828606 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -5,6 +5,55 @@ type QueryData = { ref_id: string } +export type Node = { + boost?: number | null + children?: string[] + x: number + y: number + z: number + edge_count: number + hidden?: boolean + colors?: string[] + date?: number + description?: string + episode_title?: string + hosts?: Guests[] + guests?: (null | string | Guests)[] + id?: string + image_url?: string + sender_pic?: string + sender_alias?: string + message_content?: string + keyword?: boolean + label: string + source_link?: string + link?: string + name: string + node_type: string + ref_id: string + scale?: number + show_title?: string + text?: string + timestamp?: string + topics?: string[] + type?: string + weight?: number + tweet_id?: string + posted_by?: PostedBy + twitter_handle?: string + profile_picture?: string + verified?: boolean + unique_id?: string + properties?: { [key: string]: never | undefined } + media_url?: string + start?: number + end?: number + longitude?: number + latitude?: number + coordinates?: Coordinates + audio?: Audio[] +} + export type FetchDataResponse = { nodes: Node[] edges: Link[] @@ -69,49 +118,6 @@ export type NodeRequest = { } } -export type Node = { - boost?: number | null - children?: string[] - x: number - y: number - z: number - edge_count: number - hidden?: boolean - colors?: string[] - date?: number - description?: string - episode_title?: string - hosts?: Guests[] - guests?: (null | string | Guests)[] - id?: string - image_url?: string - sender_pic?: string - sender_alias?: string - message_content?: string - keyword?: boolean - label: string - source_link?: string - link?: string - name: string - node_type: string - ref_id: string - scale?: number - show_title?: string - text?: string - timestamp?: string - topics?: string[] - type?: string - weight?: number - tweet_id?: string - posted_by?: PostedBy - twitter_handle?: string - profile_picture?: string - verified?: boolean - unique_id?: string - properties?: { [key: string]: never | undefined } - media_url?: string -} - export type DataSeriesNode = { id: string image_url?: string @@ -147,13 +153,6 @@ export type NodeExtended = Node & { fx?: number fy?: number fz?: number - start?: number - end?: number - longitude?: number - latitude?: number - coordinates?: Coordinates - audio?: Audio[] - properties?: { [key: string]: never | undefined } } export type Link = { From 878cee5a48b9ba44686bee92f7e4a6b6a3d3d01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=83=D0=BB?= Date: Mon, 23 Dec 2024 21:23:09 +0300 Subject: [PATCH 3/4] feat: updated selection graph --- .../Connections/Connection/index.tsx | 4 +- .../Cubes/SelectionDataNodes/Node/index.tsx | 9 +- .../Graph/Cubes/SelectionDataNodes/index.tsx | 147 +++++++++++------- src/components/Universe/Graph/Cubes/index.tsx | 2 - src/components/Universe/index.tsx | 2 +- 5 files changed, 105 insertions(+), 59 deletions(-) diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx index 7372715c3..e43b44003 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx @@ -29,7 +29,9 @@ const _Connection = (props: LineComponentProps) => { points={[sourceX, sourceY, sourceZ, targetX, targetY, targetZ]} /> - + + + {label} diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx index 3f04d8abf..fd8ebd191 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx @@ -63,6 +63,8 @@ const Text = styled(Flex)` color: ${colors.white}; margin-left: 16px; font-weight: 700; + width: 100px; + font-size: 16px; ` const Tag = styled(Flex)` @@ -90,8 +92,11 @@ const Tag = styled(Flex)` ` const Selected = styled(Tag)` - width: 300px; - height: 150px; + width: 200px; + height: 100px; + flex-direction: row; + justify-content: center; + align-items: center; ` const IconButton = styled(Flex)` diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx index 5ff99efbd..3b529070e 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx @@ -1,10 +1,11 @@ import { Html } from '@react-three/drei' import { forceLink, forceManyBody, forceRadial, forceSimulation } from 'd3-force-3d' -import { memo, useCallback, useEffect, useRef, useState } from 'react' +import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { Box3, Color, Group, Sphere, Vector3 } from 'three' import { Line2 } from 'three-stdlib' import { useShallow } from 'zustand/react/shallow' import { usePrevious } from '~/hooks/usePrevious' +import { fetchNodeEdges } from '~/network/fetchGraphData' import { useDataStore } from '~/stores/useDataStore' import { useGraphStore, useSelectedNode, useSelectedNodeRelativeIds } from '~/stores/useGraphStore' import { useSchemaStore } from '~/stores/useSchemaStore' @@ -19,7 +20,7 @@ const MAX_LENGTH = 6 export const SelectionDataNodes = memo(() => { const [simulation2d, setSimulation2D] = useState(null) - const { dataInitial, nodesNormalized } = useDataStore((s) => s) + const { dataInitial, nodesNormalized, addNewNode } = useDataStore((s) => s) const selectedNode = useSelectedNode() const groupRef = useRef(null) @@ -34,24 +35,62 @@ export const SelectionDataNodes = memo(() => { const { selectionGraphData, selectionPath, setSelectionData, setSelectedNode, setSelectionGraphRadius } = useGraphStore(useShallow((s) => s)) - console.log(selectionPath) + const pathNodes = useMemo(() => { + const nodes: NodeExtended[] = selectionPath + .slice(-3, -1) + .filter((id) => !!nodesNormalized.get(id)) + .map((i, index) => { + const node = nodesNormalized.get(i) as unknown as Node + + return { ...node, fx: 0, fy: -(index + 1) * 200, fz: 0, x: 0, y: 0, z: 0 } + }) + + return nodes + }, [nodesNormalized, selectionPath]) + + useEffect(() => { + const init = async () => { + if (selectedNode?.ref_id && selectedNode.ref_id !== prevSelectedNodeId) { + try { + const data = await fetchNodeEdges(selectedNode.ref_id, 0, 5) + + if (data) { + const graphNodes: NodeExtended[] = data.nodes + .filter((node) => node.ref_id !== selectedNode.ref_id) + .map((node: Node) => ({ ...node, x: 0, y: 0, z: 0 })) + + const nodes: NodeExtended[] = [ + ...graphNodes, + { ...selectedNode, x: 0, y: 0, z: 0, fx: 0, fy: 0, fz: 0 } as NodeExtended, + ] + + setSelectionData({ nodes, links: data.edges as unknown as GraphData['links'] }) + setSimulation2D(null) + linksPositionRef.current = new Map() + // + + addNewNode(data) + } + } catch (error) { + console.error(error) + } + } + } + + if (selectedNode) { + init() + } + }, [addNewNode, prevSelectedNodeId, selectedNode, setSelectionData]) useEffect(() => { + return + const structuredLinks = structuredClone(dataInitial?.links || []) if (prevSelectedNodeId === selectedNode?.ref_id) { return } - const pathNodes: NodeExtended[] = selectionPath - .slice(-3, -1) - .filter((id) => !!nodesNormalized.get(id)) - .map((i, index) => { - const node = nodesNormalized.get(i) as unknown as Node - - return { ...node, fx: -index * 50, fy: 0, fz: 0, x: 0, y: 0, z: 0 } - }) - const graphNodes: NodeExtended[] = selectedNodeRelativeIds .filter((id) => !!nodesNormalized.get(id)) .map((id: string) => { @@ -62,7 +101,6 @@ export const SelectionDataNodes = memo(() => { const nodes: NodeExtended[] = [ ...graphNodes, - ...pathNodes, { ...selectedNode, x: 0, y: 0, z: 0, fx: 0, fy: 0, fz: 0 } as NodeExtended, ] @@ -77,15 +115,7 @@ export const SelectionDataNodes = memo(() => { setSimulation2D(null) linksPositionRef.current = new Map() } - }, [ - dataInitial, - selectedNode, - selectedNodeRelativeIds, - setSelectionData, - prevSelectedNodeId, - selectionPath, - nodesNormalized, - ]) + }, [dataInitial, selectedNode, selectedNodeRelativeIds, setSelectionData, prevSelectedNodeId, nodesNormalized]) useEffect(() => { if (simulation2d || !selectionGraphData.nodes.length) { @@ -105,8 +135,8 @@ export const SelectionDataNodes = memo(() => { .id((d: NodeExtended) => d.ref_id) .distance(() => 150), ) - .force('radial', forceRadial(500, 0, 0, 0).strength(0)) - .force('charge', forceManyBody().strength(-1000)) + .force('radial', forceRadial(20, 0, 0, 0).strength(0)) + .force('charge', forceManyBody().strength(-500)) .alpha(1) .restart() @@ -115,13 +145,6 @@ export const SelectionDataNodes = memo(() => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectionGraphData, simulation2d]) - useEffect( - () => () => { - setSelectionData({ nodes: [], links: [] }) - }, - [setSelectionData], - ) - useEffect(() => { if (!simulation2d) { return @@ -145,8 +168,8 @@ export const SelectionDataNodes = memo(() => { const grConnections = groupRef.current.getObjectByName('simulation-3d-group__connections') as Group grConnections.children.forEach((g, i) => { - const r = g.children[0] // Assuming Line is the first child - const text = g.children[1] // Assuming Text is the second child + const r = g.children[0] + const text = g.children[1] if (r instanceof Line2) { const Line = r as Line2 @@ -163,7 +186,6 @@ export const SelectionDataNodes = memo(() => { const { x: sx, y: sy } = sourceNode const { x: tx, y: ty } = targetNode - // Set positions for the link linksPositionRef.current.set(link.ref_id, { sx, sy, @@ -175,16 +197,16 @@ export const SelectionDataNodes = memo(() => { const midPoint = new Vector3((sx + tx) / 2, (sy + ty) / 2, 0) - // Position the text - text.position.set(midPoint.x, midPoint.y, 1) + text.position.set(midPoint.x, midPoint.y, 2) + + let angle = Math.atan2(ty - sy, tx - sx) - // Calculate angle of rotation in 2D - const angle = Math.atan2(ty - sy, tx - sx) + if (tx < sx || (Math.abs(tx - sx) < 0.01 && ty < sy)) { + angle += Math.PI + } - // Apply rotation to the text - text.rotation.set(0, 0, angle) // Only Z-axis rotation needed for 2D alignment + text.rotation.set(0, 0, angle) - // Set the line positions Line.geometry.setPositions([sx, sy, 0, tx, ty, 0]) const { material } = Line @@ -218,18 +240,37 @@ export const SelectionDataNodes = memo(() => { ) return ( - - {selectionGraphData?.nodes.map((node) => ( - - - handleSelect(node)} selected={node.ref_id === selectedNode?.ref_id} /> - - - - - ))} - - + <> + + {selectionGraphData?.nodes.map((node) => ( + + + handleSelect(node)} + selected={node.ref_id === selectedNode?.ref_id} + /> + + + ))} + + + {false && ( + + {pathNodes.map((node) => ( + + + handleSelect(node)} + selected={node.ref_id === selectedNode?.ref_id} + /> + + + ))} + + )} + ) }) diff --git a/src/components/Universe/Graph/Cubes/index.tsx b/src/components/Universe/Graph/Cubes/index.tsx index 4b9672456..a66f4fd2a 100644 --- a/src/components/Universe/Graph/Cubes/index.tsx +++ b/src/components/Universe/Graph/Cubes/index.tsx @@ -10,7 +10,6 @@ import { colors } from '~/utils' import { COLORS_MAP } from '../constant' import { NodePoints } from './NodePoints' import { NodeWrapper } from './NodeWrapper' -import { RelevanceBadges } from './RelevanceBadges' const POINTER_IN_DELAY = 200 @@ -131,7 +130,6 @@ export const Cubes = memo(() => { - ) }) diff --git a/src/components/Universe/index.tsx b/src/components/Universe/index.tsx index 2226c8875..2ee57bdb2 100644 --- a/src/components/Universe/index.tsx +++ b/src/components/Universe/index.tsx @@ -178,7 +178,7 @@ const _Universe = () => { - + From 9eb306deb0b067e94aa974508fc9469f34a4b36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=81=D1=83=D0=BB?= Date: Tue, 24 Dec 2024 00:18:01 +0300 Subject: [PATCH 4/4] feat: update selection view data fetch --- .../Controls/CameraAnimations/index.ts | 30 ++++++++++--------- .../Graph/Connections/LineComponent.tsx | 5 ++-- .../Connections/Connection/index.tsx | 3 +- .../Cubes/SelectionDataNodes/Node/index.tsx | 4 ++- .../Graph/Cubes/SelectionDataNodes/index.tsx | 21 +++++++++---- src/components/Universe/Graph/Cubes/index.tsx | 2 +- src/components/Universe/Graph/index.tsx | 30 ++++++------------- 7 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/components/Universe/Controls/CameraAnimations/index.ts b/src/components/Universe/Controls/CameraAnimations/index.ts index e9f04569f..bc8fca123 100644 --- a/src/components/Universe/Controls/CameraAnimations/index.ts +++ b/src/components/Universe/Controls/CameraAnimations/index.ts @@ -24,7 +24,7 @@ export const useCameraAnimations = ( const isUserDragging = useControlStore((s) => s.isUserDragging) - const { graphStyle, graphRadius, disableCameraRotation } = useGraphStore((s) => s) + const { graphRadius, disableCameraRotation } = useGraphStore((s) => s) useEffect(() => { if (!enabled) { @@ -33,22 +33,24 @@ export const useCameraAnimations = ( } }, [enabled]) - useEffect(() => { - if (cameraControlsRef.current && graphRadius) { - if (graphStyle === 'sphere') { - cameraControlsRef.current.maxDistance = 8000 - cameraControlsRef.current.minDistance = 200 - cameraControlsRef.current.setTarget(0, 0, 500, true) - } else { - cameraControlsRef.current.maxDistance = cameraControlsRef.current.getDistanceToFitSphere(graphRadius + 200) - cameraControlsRef.current.minDistance = 100 - } - } - }, [graphRadius, graphStyle, cameraControlsRef]) + // useEffect(() => { + // if (cameraControlsRef.current && graphRadius) { + // cameraControlsRef.current.maxDistance = cameraControlsRef.current.getDistanceToFitSphere(graphRadius + 200) + // cameraControlsRef.current.minDistance = 100 + // } + // }, [graphRadius, cameraControlsRef]) useEffect(() => { if (!selectedNode && cameraControlsRef.current) { - cameraControlsRef.current.setLookAt(initialCameraPosition.x, initialCameraPosition.y, graphRadius, 0, 0, 0, true) + cameraControlsRef.current.setLookAt( + initialCameraPosition.x, + initialCameraPosition.y, + graphRadius + 200, + 0, + 0, + 0, + true, + ) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedNode, graphRadius]) diff --git a/src/components/Universe/Graph/Connections/LineComponent.tsx b/src/components/Universe/Graph/Connections/LineComponent.tsx index 8c9b9177a..92737f371 100644 --- a/src/components/Universe/Graph/Connections/LineComponent.tsx +++ b/src/components/Universe/Graph/Connections/LineComponent.tsx @@ -5,6 +5,7 @@ import { memo, useEffect, useRef } from 'react' import { Line2 } from 'three-stdlib' import { useGraphStore } from '~/stores/useGraphStore' import { LINE_WIDTH } from '../../constants' +import { fontProps } from '../Cubes/Text/constants' type LineComponentProps = { label: string @@ -78,8 +79,8 @@ const _LineComponent = (props: LineComponentProps) => { points={[sourceX, sourceY, sourceZ, targetX, targetY, targetZ]} /> - - {label}1 + + {label} diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx index e43b44003..8c5f202d5 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Connections/Connection/index.tsx @@ -1,6 +1,7 @@ import { Line, Text } from '@react-three/drei' import { memo, useRef } from 'react' import { Line2 } from 'three-stdlib' +import { fontProps } from '../../../Text/constants' type LineComponentProps = { label: string @@ -31,7 +32,7 @@ const _Connection = (props: LineComponentProps) => { - + {label} diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx index fd8ebd191..1f07b1446 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/Node/index.tsx @@ -57,7 +57,9 @@ export const Node = ({ onClick, node, selected, rounded = true }: Props) => { ) } -const Wrapper = styled(Flex)`` +const Wrapper = styled(Flex)` + background: black; +` const Text = styled(Flex)` color: ${colors.white}; diff --git a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx index 3b529070e..b8e52c5fe 100644 --- a/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx +++ b/src/components/Universe/Graph/Cubes/SelectionDataNodes/index.tsx @@ -55,21 +55,30 @@ export const SelectionDataNodes = memo(() => { const data = await fetchNodeEdges(selectedNode.ref_id, 0, 5) if (data) { - const graphNodes: NodeExtended[] = data.nodes - .filter((node) => node.ref_id !== selectedNode.ref_id) - .map((node: Node) => ({ ...node, x: 0, y: 0, z: 0 })) + const filteredNodes: NodeExtended[] = data.nodes.filter( + (node, index) => node.ref_id !== selectedNode.ref_id && index < 7, + ) + + const graphNodes = filteredNodes.map((node: Node) => ({ ...node, x: 0, y: 0, z: 0 })) const nodes: NodeExtended[] = [ ...graphNodes, { ...selectedNode, x: 0, y: 0, z: 0, fx: 0, fy: 0, fz: 0 } as NodeExtended, ] - setSelectionData({ nodes, links: data.edges as unknown as GraphData['links'] }) + const links = data.edges.filter( + (link: Link) => + nodes.some((node: NodeExtended) => node.ref_id === link.target) && + nodes.some((node: NodeExtended) => node.ref_id === link.source), + ) + + setSelectionData({ nodes, links: links as unknown as GraphData['links'] }) setSimulation2D(null) linksPositionRef.current = new Map() + // - addNewNode(data) + addNewNode({ nodes: filteredNodes, edges: links }) } } catch (error) { console.error(error) @@ -197,7 +206,7 @@ export const SelectionDataNodes = memo(() => { const midPoint = new Vector3((sx + tx) / 2, (sy + ty) / 2, 0) - text.position.set(midPoint.x, midPoint.y, 2) + text.position.set(midPoint.x, midPoint.y, 1) let angle = Math.atan2(ty - sy, tx - sx) diff --git a/src/components/Universe/Graph/Cubes/index.tsx b/src/components/Universe/Graph/Cubes/index.tsx index a66f4fd2a..60aa4579f 100644 --- a/src/components/Universe/Graph/Cubes/index.tsx +++ b/src/components/Universe/Graph/Cubes/index.tsx @@ -120,7 +120,7 @@ export const Cubes = memo(() => { index={index} node={node} scale={node.scale || 1} - stopFrames={hideUniverse} + stopFrames={false} /> ) })} diff --git a/src/components/Universe/Graph/index.tsx b/src/components/Universe/Graph/index.tsx index 2d653449f..17d26bd6a 100644 --- a/src/components/Universe/Graph/index.tsx +++ b/src/components/Universe/Graph/index.tsx @@ -24,7 +24,6 @@ export type LinkPosition = { export const Graph = () => { const { dataInitial, isLoadingNew, isFetching, dataNew, resetDataNew } = useDataStore((s) => s) const groupRef = useRef(null) - const cameraSettled = useRef(false) const { normalizedSchemasByType } = useSchemaStore((s) => s) const linksPositionRef = useRef(new Map()) @@ -78,25 +77,6 @@ export const Graph = () => { return } - simulation.on('tick', () => { - if (!cameraSettled.current && simulation.alpha() < 0.1) { - const nodesVector = simulation.nodes().map((i: NodeExtended) => new Vector3(i.x, i.y, i.z)) - - const boundingBox = new Box3().setFromPoints(nodesVector) - - const boundingSphere = new Sphere() - - boundingBox.getBoundingSphere(boundingSphere) - - const sphereRadius = Math.min(5000, boundingSphere.radius) - - if (false) { - setGraphRadius(sphereRadius) - cameraSettled.current = true - } - } - }) - simulation.on('end', () => { const nodesVector = simulation.nodes().map((i: NodeExtended) => { // eslint-disable-next-line no-param-reassign @@ -182,7 +162,15 @@ export const Graph = () => { const boundingBox = new Box3().setFromPoints(nodesVector) - console.log(boundingBox) + const boundingSphere = new Sphere() + + boundingBox.getBoundingSphere(boundingSphere) + + const sphereRadius = Math.min(5000, boundingSphere.radius) + + console.log(sphereRadius) + + setGraphRadius(sphereRadius) }) }, [dataInitial, simulation, setGraphRadius, normalizedSchemasByType])