revert graph.js refactor
This commit is contained in:
		
							parent
							
								
									2496ca26a5
								
							
						
					
					
						commit
						30ee21f087
					
				@ -1290,114 +1290,115 @@ class GraphManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enhanced hide operation using true root detection
 | 
			
		||||
     * @param {string} nodeId - The ID of the node to start hiding from
 | 
			
		||||
     * Hide a node and recursively hide any neighbors that become disconnected.
 | 
			
		||||
     * @param {string} nodeId - The ID of the node to start hiding from.
 | 
			
		||||
     */
 | 
			
		||||
    hideNodeAndOrphans(nodeId) {
 | 
			
		||||
        const historyData = { nodeIds: [] };
 | 
			
		||||
        
 | 
			
		||||
        // Step 1: Hide the target node
 | 
			
		||||
        this.nodes.update({ id: nodeId, hidden: true });
 | 
			
		||||
        historyData.nodeIds.push(nodeId);
 | 
			
		||||
        
 | 
			
		||||
        // Step 2: Recompute what should remain visible using true root detection
 | 
			
		||||
        const remainingVisible = this.computeReachableFromRoots();
 | 
			
		||||
        
 | 
			
		||||
        // Step 3: Hide any nodes that are no longer reachable
 | 
			
		||||
        const allNodes = this.nodes.get();
 | 
			
		||||
        allNodes.forEach(node => {
 | 
			
		||||
            if (!node.hidden && !remainingVisible.has(node.id) && node.id !== nodeId) {
 | 
			
		||||
                this.nodes.update({ id: node.id, hidden: true });
 | 
			
		||||
                historyData.nodeIds.push(node.id);
 | 
			
		||||
        const queue = [nodeId];
 | 
			
		||||
        const visited = new Set([nodeId]);
 | 
			
		||||
 | 
			
		||||
        while (queue.length > 0) {
 | 
			
		||||
            const currentId = queue.shift();
 | 
			
		||||
            const node = this.nodes.get(currentId);
 | 
			
		||||
            if (!node || node.hidden) continue;
 | 
			
		||||
 | 
			
		||||
            // 1. Hide the current node and add to history
 | 
			
		||||
            this.nodes.update({ id: currentId, hidden: true });
 | 
			
		||||
            historyData.nodeIds.push(currentId);
 | 
			
		||||
 | 
			
		||||
            // 2. Check its neighbors
 | 
			
		||||
            const neighbors = this.network.getConnectedNodes(currentId);
 | 
			
		||||
            for (const neighborId of neighbors) {
 | 
			
		||||
                if (visited.has(neighborId)) continue;
 | 
			
		||||
                
 | 
			
		||||
                const connectedEdges = this.network.getConnectedEdges(neighborId);
 | 
			
		||||
                let hasVisibleEdge = false;
 | 
			
		||||
                // 3. See if the neighbor still has any visible connections
 | 
			
		||||
                for (const edgeId of connectedEdges) {
 | 
			
		||||
                    const edge = this.edges.get(edgeId);
 | 
			
		||||
                    const sourceNode = this.nodes.get(edge.from);
 | 
			
		||||
                    const targetNode = this.nodes.get(edge.to);
 | 
			
		||||
                    if ((sourceNode && !sourceNode.hidden) && (targetNode && !targetNode.hidden)) {
 | 
			
		||||
                        hasVisibleEdge = true;
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // 4. If no visible connections, add to queue to be hidden
 | 
			
		||||
                if (!hasVisibleEdge) {
 | 
			
		||||
                    queue.push(neighborId);
 | 
			
		||||
                    visited.add(neighborId);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (historyData.nodeIds.length > 0) {
 | 
			
		||||
            this.addToHistory('hide', historyData);
 | 
			
		||||
            console.log(`Hidden ${historyData.nodeIds.length} nodes using true root detection`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enhanced delete operation using true root detection
 | 
			
		||||
     * @param {string} nodeId - The ID of the node to start deleting from
 | 
			
		||||
     * Delete a node and recursively delete any neighbors that become disconnected.
 | 
			
		||||
     * @param {string} nodeId - The ID of the node to start deleting from.
 | 
			
		||||
     */
 | 
			
		||||
    async deleteNodeAndOrphans(nodeId) {
 | 
			
		||||
        const deletionQueue = [nodeId];
 | 
			
		||||
        const processedForDeletion = new Set([nodeId]);
 | 
			
		||||
        const historyData = { nodes: [], edges: [] };
 | 
			
		||||
        let operationFailed = false;
 | 
			
		||||
        
 | 
			
		||||
        // Step 1: Store current state and delete target node
 | 
			
		||||
        const targetNode = this.nodes.get(nodeId);
 | 
			
		||||
        const connectedEdgeIds = this.network.getConnectedEdges(nodeId);
 | 
			
		||||
        const connectedEdges = this.edges.get(connectedEdgeIds);
 | 
			
		||||
        
 | 
			
		||||
        if (targetNode) {
 | 
			
		||||
            historyData.nodes.push(targetNode);
 | 
			
		||||
            historyData.edges.push(...connectedEdges);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        try {
 | 
			
		||||
            // Delete from backend first
 | 
			
		||||
            const response = await fetch(`/api/graph/node/${nodeId}`, { method: 'DELETE' });
 | 
			
		||||
            const result = await response.json();
 | 
			
		||||
 | 
			
		||||
        while (deletionQueue.length > 0) {
 | 
			
		||||
            const currentId = deletionQueue.shift();
 | 
			
		||||
            const node = this.nodes.get(currentId);
 | 
			
		||||
            if (!node) continue;
 | 
			
		||||
 | 
			
		||||
            const neighbors = this.network.getConnectedNodes(currentId);
 | 
			
		||||
            const connectedEdgeIds = this.network.getConnectedEdges(currentId);
 | 
			
		||||
            const edges = this.edges.get(connectedEdgeIds);
 | 
			
		||||
            
 | 
			
		||||
            if (!result.success) {
 | 
			
		||||
                throw new Error(result.error || 'Failed to delete node from backend');
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // Remove from frontend
 | 
			
		||||
            this.nodes.remove({ id: nodeId });
 | 
			
		||||
            console.log(`Node ${nodeId} deleted from backend and frontend`);
 | 
			
		||||
            
 | 
			
		||||
            // Step 2: Identify orphaned nodes using true root detection
 | 
			
		||||
            const reachableNodes = this.computeReachableFromRoots();
 | 
			
		||||
            const allRemainingNodes = this.nodes.get().filter(node => node.id !== nodeId);
 | 
			
		||||
            
 | 
			
		||||
            // Step 3: Delete orphaned nodes
 | 
			
		||||
            const orphanedNodes = allRemainingNodes.filter(node => !reachableNodes.has(node.id));
 | 
			
		||||
            
 | 
			
		||||
            for (const orphanNode of orphanedNodes) {
 | 
			
		||||
                try {
 | 
			
		||||
                    const orphanEdgeIds = this.network.getConnectedEdges(orphanNode.id);
 | 
			
		||||
                    const orphanEdges = this.edges.get(orphanEdgeIds);
 | 
			
		||||
                    
 | 
			
		||||
                    // Store for history
 | 
			
		||||
                    historyData.nodes.push(orphanNode);
 | 
			
		||||
                    historyData.edges.push(...orphanEdges);
 | 
			
		||||
                    
 | 
			
		||||
                    // Delete from backend
 | 
			
		||||
                    const orphanResponse = await fetch(`/api/graph/node/${orphanNode.id}`, { method: 'DELETE' });
 | 
			
		||||
                    const orphanResult = await orphanResponse.json();
 | 
			
		||||
                    
 | 
			
		||||
                    if (!orphanResult.success) {
 | 
			
		||||
                        console.warn(`Failed to delete orphaned node ${orphanNode.id}:`, orphanResult.error);
 | 
			
		||||
                        // Continue with other orphans rather than failing entirely
 | 
			
		||||
                    } else {
 | 
			
		||||
                        // Remove from frontend
 | 
			
		||||
                        this.nodes.remove({ id: orphanNode.id });
 | 
			
		||||
                        console.log(`Orphaned node ${orphanNode.id} deleted`);
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (error) {
 | 
			
		||||
                    console.error(`Error deleting orphaned node ${orphanNode.id}:`, error);
 | 
			
		||||
                    // Continue with other orphans
 | 
			
		||||
            // Store state for potential revert
 | 
			
		||||
            historyData.nodes.push(node);
 | 
			
		||||
            historyData.edges.push(...edges);
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                const response = await fetch(`/api/graph/node/${currentId}`, { method: 'DELETE' });
 | 
			
		||||
                const result = await response.json();
 | 
			
		||||
 | 
			
		||||
                if (!result.success) {
 | 
			
		||||
                    console.error(`Failed to delete node ${currentId} from backend:`, result.error);
 | 
			
		||||
                    operationFailed = true;
 | 
			
		||||
                    break; 
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                console.log(`Node ${currentId} deleted from backend.`);
 | 
			
		||||
                this.nodes.remove({ id: currentId }); // Remove from view
 | 
			
		||||
                
 | 
			
		||||
                // Check if former neighbors are now orphans
 | 
			
		||||
                neighbors.forEach(neighborId => {
 | 
			
		||||
                    if (!processedForDeletion.has(neighborId) && this.nodes.get(neighborId)) {
 | 
			
		||||
                        if (this.network.getConnectedEdges(neighborId).length === 0) {
 | 
			
		||||
                            deletionQueue.push(neighborId);
 | 
			
		||||
                            processedForDeletion.add(neighborId);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            } catch (error) {
 | 
			
		||||
                console.error('Error during node deletion API call:', error);
 | 
			
		||||
                operationFailed = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            console.log(`Deleted ${orphanedNodes.length + 1} nodes using true root detection`);
 | 
			
		||||
            
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error('Error during node deletion:', error);
 | 
			
		||||
            operationFailed = true;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Add to history only if primary deletion succeeded
 | 
			
		||||
 | 
			
		||||
        // Add to history only if the entire operation was successful
 | 
			
		||||
        if (!operationFailed && historyData.nodes.length > 0) {
 | 
			
		||||
            // Ensure edges in history are unique
 | 
			
		||||
            historyData.edges = Array.from(new Map(historyData.edges.map(e => [e.id, e])).values());
 | 
			
		||||
            this.addToHistory('delete', historyData);
 | 
			
		||||
        } else if (operationFailed) {
 | 
			
		||||
            console.log("Reverting UI changes due to failed delete operation");
 | 
			
		||||
            // Restore the UI to original state
 | 
			
		||||
            console.log("Reverting UI changes due to failed delete operation.");
 | 
			
		||||
            // If any part of the chain failed, restore the UI to its original state
 | 
			
		||||
            this.nodes.add(historyData.nodes);
 | 
			
		||||
            this.edges.add(historyData.edges);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user