// Frontend API client - calls our Express backend class FrontendApiClient { constructor() { this.baseUrl = ''; // Same origin as the current page } async getClusterMembers() { try { const response = await fetch('/api/cluster/members', { method: 'GET', headers: { 'Accept': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (error) { throw new Error(`Request failed: ${error.message}`); } } async getNodeStatus(ip) { try { // Create a proxy endpoint that forwards the request to the specific node const response = await fetch(`/api/node/status/${encodeURIComponent(ip)}`, { method: 'GET', headers: { 'Accept': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (error) { throw new Error(`Request failed: ${error.message}`); } } async getTasksStatus() { try { const response = await fetch('/api/tasks/status', { method: 'GET', headers: { 'Accept': 'application/json' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); } catch (error) { throw new Error(`Request failed: ${error.message}`); } } } // Global client instance const client = new FrontendApiClient(); // Function to refresh cluster members async function refreshClusterMembers() { const container = document.getElementById('cluster-members-container'); // Show loading state container.innerHTML = `