diff --git a/src/static/js/dashboard-resource_provider.js b/src/static/js/dashboard-resource_provider.js index c9d0bf6..3bcc422 100644 --- a/src/static/js/dashboard-resource_provider.js +++ b/src/static/js/dashboard-resource_provider.js @@ -4092,7 +4092,9 @@ async function loadExistingGroups() { } // Stale-guard for node details fetches - let __nodeDetailsSeq = 0; + // Guard against redeclaration - use window scope to persist across reloads + window.__nodeDetailsSeq = window.__nodeDetailsSeq || 0; + let __nodeDetailsSeq = window.__nodeDetailsSeq; /** * View node details @@ -4105,7 +4107,7 @@ async function loadExistingGroups() { window.__nodeDetailsController = (typeof AbortController !== 'undefined') ? new AbortController() : null; // Sequence guard to avoid race conditions - const requestId = ++__nodeDetailsSeq; + const requestId = ++window.__nodeDetailsSeq; const nodeData = await window.apiJson(`/api/dashboard/farm-nodes/${nodeId}`, { cache: 'no-store', @@ -4113,7 +4115,7 @@ async function loadExistingGroups() { }); // If a newer request started, ignore this response - if (requestId !== __nodeDetailsSeq) return; + if (requestId !== window.__nodeDetailsSeq) return; console.log('👁️ Loaded node details:', nodeData); showNodeDetailsModal(nodeData); @@ -4123,6 +4125,47 @@ async function loadExistingGroups() { } } +/** + * Delete node configuration (show confirmation modal) + */ +async function deleteNodeConfiguration(nodeId) { + console.log('🗑️ Initiating node deletion for nodeId:', nodeId); + + if (!nodeId) { + console.error('🗑️ No node ID provided for deletion'); + showNotification('Error: No node ID provided', 'error'); + return; + } + + try { + // Fetch node data to get the node name for confirmation + console.log('🗑️ Fetching node data for deletion confirmation:', nodeId); + const nodeData = await window.apiJson(`/api/dashboard/farm-nodes/${nodeId}`, { + cache: 'no-store' + }); + + console.log('🗑️ Loaded node data for deletion:', nodeData); + + // Set the pending delete node ID + window.pendingDeleteNodeId = nodeId; + + // Update the modal with node information + const deleteNodeNameElement = document.getElementById('deleteNodeName'); + if (deleteNodeNameElement) { + const nodeName = nodeData.name || `Node ${nodeId}`; + deleteNodeNameElement.textContent = nodeName; + } + + // Show the delete confirmation modal + const deleteModal = new bootstrap.Modal(document.getElementById('deleteNodeModal')); + deleteModal.show(); + + } catch (error) { + console.error('🗑️ Error preparing node deletion:', error); + showNotification(`Failed to prepare node deletion: ${error.message}`, 'error'); + } +} + /** * Confirm node deletion (called from modal) */ diff --git a/src/static/js/messaging-system.js b/src/static/js/messaging-system.js index fa759f0..5781adf 100644 --- a/src/static/js/messaging-system.js +++ b/src/static/js/messaging-system.js @@ -3,6 +3,9 @@ * Handles communication between users and providers. */ +// Guard against redeclaration +if (typeof MessagingSystem === 'undefined') { + class MessagingSystem { constructor() { this.currentThread = null; @@ -960,3 +963,5 @@ MessagingSystem.prototype.openThreadFromList = function(threadId) { // Open the specific thread in the old modal this.openThread(threadId); }; + +} // End of MessagingSystem guard diff --git a/user_data/user123_at_example_com.json b/user_data/user123_at_example_com.json index c26f5af..782da21 100644 --- a/user_data/user123_at_example_com.json +++ b/user_data/user123_at_example_com.json @@ -37,7 +37,121 @@ "deleted": null, "deleted_at": null, "deletion_reason": null, - "nodes": [], + "nodes": [ + { + "id": "grid_node_1", + "location": "Unknown, Belgium", + "status": "Online", + "capacity": { + "cpu_cores": 56, + "memory_gb": 188, + "storage_gb": 135975, + "bandwidth_mbps": 1000, + "ssd_storage_gb": 1863, + "hdd_storage_gb": 134112, + "ram_gb": 188 + }, + "used_capacity": { + "cpu_cores": 25, + "memory_gb": 92, + "storage_gb": 1021, + "bandwidth_mbps": 0, + "ssd_storage_gb": 1021, + "hdd_storage_gb": 0, + "ram_gb": 92 + }, + "uptime_percentage": 99.0, + "farming_start_date": "2025-08-10T03:03:44.241167749Z", + "last_updated": "2025-09-09T03:03:44.241194575Z", + "utilization_7_day_avg": 65.0, + "slice_formats_supported": [ + "1x1", + "2x2", + "4x4" + ], + "rental_options": null, + "total_base_slices": 0, + "allocated_base_slices": 0, + "earnings_today_usd": 0.0, + "grid_node_id": "1", + "available_combinations": [], + "slice_allocations": [], + "slice_last_calculated": null, + "marketplace_sla": { + "id": "sla-repair-90a36bcd-b6e2-45e7-872a-baeaa485f220", + "name": "Repaired Node SLA", + "uptime_guarantee": 99.8, + "response_time_hours": 24, + "resolution_time_hours": 48, + "penalty_rate": 0.01, + "uptime_guarantee_percentage": 99.8, + "base_slice_price": 0.5, + "bandwidth_guarantee_mbps": 100.0, + "last_updated": "2025-09-09T03:04:23.227212978Z" + }, + "slice_pricing": { + "base_price_per_hour": 1.0, + "currency": "USD", + "pricing_multiplier": 1.0 + }, + "grid_data": { + "capacity": { + "bandwidth_mbps": 1000, + "cpu_cores": 56, + "hdd_storage_gb": 134112, + "memory_gb": 188, + "ram_gb": 188, + "ssd_storage_gb": 1863, + "storage_gb": 135975 + }, + "certification_type": "Diy", + "city": "Unknown", + "country": "Belgium", + "farm_id": 1, + "farm_name": "Freefarm", + "farming_policy_id": 1, + "grid_node_id": 1, + "last_updated": "2025-09-09T03:03:44.240833231Z", + "location": "Unknown, Belgium", + "node_id": 1, + "public_ips": [ + "192.168.1.100" + ], + "status": "Online", + "total_resources": { + "bandwidth_mbps": 1000, + "cpu_cores": 56, + "hdd_storage_gb": 134112, + "memory_gb": 188, + "ram_gb": 188, + "ssd_storage_gb": 1863, + "storage_gb": 135975 + }, + "uptime": 99.5, + "used_resources": { + "bandwidth_mbps": 0, + "cpu_cores": 25, + "hdd_storage_gb": 0, + "memory_gb": 92, + "ram_gb": 92, + "ssd_storage_gb": 1021, + "storage_gb": 1021 + } + }, + "slice_formats": null, + "name": "Grid Node 1", + "region": "Belgium", + "node_type": "MyceliumNode", + "staking_options": null, + "availability_status": "Available", + "node_group_id": null, + "group_assignment_date": null, + "group_slice_format": null, + "group_slice_price": null, + "last_seen": "2025-09-09T03:03:44.241206636Z", + "health_score": 100.0 + } + ], "resource_provider_earnings": [], "resource_provider_settings": null, "slice_products": [],