test
This commit is contained in:
@@ -527,6 +527,10 @@ function updateSystemInfo(systemInfo) {
|
|||||||
// Update volumes store if volumes are present in systemInfo
|
// Update volumes store if volumes are present in systemInfo
|
||||||
if (systemInfo.volumes && Array.isArray(systemInfo.volumes)) {
|
if (systemInfo.volumes && Array.isArray(systemInfo.volumes)) {
|
||||||
volumesStore.set(systemInfo.volumes);
|
volumesStore.set(systemInfo.volumes);
|
||||||
|
// If we're on the volumes view, refresh the display
|
||||||
|
if (currentView === 'volumes') {
|
||||||
|
renderVolumes(systemInfo.volumes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dockerInfoEl = document.getElementById('docker-info-content');
|
const dockerInfoEl = document.getElementById('docker-info-content');
|
||||||
@@ -1047,11 +1051,24 @@ function setupDeployStackHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscription for volumes store to auto-update UI
|
||||||
|
let volumesStoreSubscription = null;
|
||||||
|
|
||||||
function loadVolumes() {
|
function loadVolumes() {
|
||||||
if (!window.activePeer) {
|
if (!window.activePeer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up subscription to auto-update UI when volumes change
|
||||||
|
if (!volumesStoreSubscription) {
|
||||||
|
volumesStoreSubscription = volumesStore.subscribe((volumes) => {
|
||||||
|
// Only auto-update if we're on the volumes view
|
||||||
|
if (currentView === 'volumes') {
|
||||||
|
renderVolumes(volumes);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Check cache first - if fresh, use it; otherwise load from server
|
// Check cache first - if fresh, use it; otherwise load from server
|
||||||
if (!volumesStore.isStale() && volumesStore.get().length > 0) {
|
if (!volumesStore.isStale() && volumesStore.get().length > 0) {
|
||||||
renderVolumes(volumesStore.get());
|
renderVolumes(volumesStore.get());
|
||||||
@@ -1103,7 +1120,8 @@ function renderVolumes(volumes) {
|
|||||||
const volumeName = btn.dataset.volumeName;
|
const volumeName = btn.dataset.volumeName;
|
||||||
showConfirmModal('Are you sure you want to remove this volume? This cannot be undone.', () => {
|
showConfirmModal('Are you sure you want to remove this volume? This cannot be undone.', () => {
|
||||||
sendCommand('removeVolume', { name: volumeName });
|
sendCommand('removeVolume', { name: volumeName });
|
||||||
setTimeout(() => loadVolumes(), 1000);
|
// The server will broadcast the updated volumes list, which will trigger the subscription
|
||||||
|
// But we can also proactively refresh if needed
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -3805,11 +3823,21 @@ function handlePeerData(data, topicId, peer) {
|
|||||||
case 'volumes':
|
case 'volumes':
|
||||||
console.log('[INFO] Handling volumes list...');
|
console.log('[INFO] Handling volumes list...');
|
||||||
// Store in cache and render
|
// Store in cache and render
|
||||||
|
let volumesToRender = null;
|
||||||
if (response.data && Array.isArray(response.data)) {
|
if (response.data && Array.isArray(response.data)) {
|
||||||
renderVolumes(response.data);
|
volumesToRender = response.data;
|
||||||
} else if (response.volumes && Array.isArray(response.volumes)) {
|
} else if (response.volumes && Array.isArray(response.volumes)) {
|
||||||
// Fallback for old format
|
// Fallback for old format
|
||||||
renderVolumes(response.volumes);
|
volumesToRender = response.volumes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (volumesToRender !== null) {
|
||||||
|
// Update store (this will trigger subscriptions)
|
||||||
|
volumesStore.set(volumesToRender);
|
||||||
|
// Render if on volumes view
|
||||||
|
if (currentView === 'volumes') {
|
||||||
|
renderVolumes(volumesToRender);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -3902,17 +3930,23 @@ function handlePeerData(data, topicId, peer) {
|
|||||||
|
|
||||||
// Handle volumes responses - update cache and route to handlers if needed
|
// Handle volumes responses - update cache and route to handlers if needed
|
||||||
// Check for volumes in response (both new format with type and old format)
|
// Check for volumes in response (both new format with type and old format)
|
||||||
|
// Note: This is a fallback for responses that weren't handled in the switch statement above
|
||||||
|
// The 'volumes' case in the switch should have already handled type: 'volumes' responses
|
||||||
let volumesArray = null;
|
let volumesArray = null;
|
||||||
if (response && response.type === 'volumes' && Array.isArray(response.data)) {
|
if (response && response.type !== 'volumes' && response.success === true && Array.isArray(response.volumes)) {
|
||||||
volumesArray = response.data;
|
// Old format volumes response that wasn't caught by switch
|
||||||
} else if (response && response.success === true && Array.isArray(response.volumes)) {
|
|
||||||
volumesArray = response.volumes;
|
volumesArray = response.volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (volumesArray !== null) {
|
if (volumesArray !== null) {
|
||||||
// Always update the cache first
|
// Always update the cache first (this will trigger subscriptions)
|
||||||
volumesStore.set(volumesArray);
|
volumesStore.set(volumesArray);
|
||||||
|
|
||||||
|
// Render if on volumes view
|
||||||
|
if (currentView === 'volumes') {
|
||||||
|
renderVolumes(volumesArray);
|
||||||
|
}
|
||||||
|
|
||||||
// Route to active volume selectors if they exist (for deploy modal)
|
// Route to active volume selectors if they exist (for deploy modal)
|
||||||
if (window.activeVolumeHandlers && window.activeVolumeHandlers.size > 0) {
|
if (window.activeVolumeHandlers && window.activeVolumeHandlers.size > 0) {
|
||||||
for (const [volumeId, handlerInfo] of window.activeVolumeHandlers.entries()) {
|
for (const [volumeId, handlerInfo] of window.activeVolumeHandlers.entries()) {
|
||||||
|
|||||||
+72
-1
@@ -1170,6 +1170,28 @@ swarm.on('connection', (peer) => {
|
|||||||
|
|
||||||
const volume = await docker.createVolume(volumeConfig);
|
const volume = await docker.createVolume(volumeConfig);
|
||||||
response = { success: true, message: `Volume "${args.name}" created successfully`, data: volume.name };
|
response = { success: true, message: `Volume "${args.name}" created successfully`, data: volume.name };
|
||||||
|
|
||||||
|
// Broadcast updated volumes list to all peers
|
||||||
|
try {
|
||||||
|
const volumesResult = await docker.listVolumes();
|
||||||
|
const volumesList = volumesResult.Volumes || [];
|
||||||
|
const update = {
|
||||||
|
type: 'volumes',
|
||||||
|
data: volumesList,
|
||||||
|
success: true,
|
||||||
|
volumes: volumesList
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const connectedPeer of connectedPeers) {
|
||||||
|
try {
|
||||||
|
connectedPeer.write(JSON.stringify(update));
|
||||||
|
} catch (peerErr) {
|
||||||
|
console.error(`[ERROR] Failed to send volume update to peer: ${peerErr.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (volErr) {
|
||||||
|
console.warn(`[WARN] Failed to broadcast volume update: ${volErr.message}`);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[ERROR] Failed to create volume: ${error.message}`);
|
console.error(`[ERROR] Failed to create volume: ${error.message}`);
|
||||||
response = { error: `Failed to create volume: ${error.message}` };
|
response = { error: `Failed to create volume: ${error.message}` };
|
||||||
@@ -1182,6 +1204,28 @@ swarm.on('connection', (peer) => {
|
|||||||
const volume = docker.getVolume(parsedData.args.name);
|
const volume = docker.getVolume(parsedData.args.name);
|
||||||
await volume.remove();
|
await volume.remove();
|
||||||
response = { success: true, message: `Volume ${parsedData.args.name} removed` };
|
response = { success: true, message: `Volume ${parsedData.args.name} removed` };
|
||||||
|
|
||||||
|
// Broadcast updated volumes list to all peers
|
||||||
|
try {
|
||||||
|
const volumesResult = await docker.listVolumes();
|
||||||
|
const volumesList = volumesResult.Volumes || [];
|
||||||
|
const update = {
|
||||||
|
type: 'volumes',
|
||||||
|
data: volumesList,
|
||||||
|
success: true,
|
||||||
|
volumes: volumesList
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const connectedPeer of connectedPeers) {
|
||||||
|
try {
|
||||||
|
connectedPeer.write(JSON.stringify(update));
|
||||||
|
} catch (peerErr) {
|
||||||
|
console.error(`[ERROR] Failed to send volume update to peer: ${peerErr.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (volErr) {
|
||||||
|
console.warn(`[WARN] Failed to broadcast volume update: ${volErr.message}`);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[ERROR] Failed to remove volume: ${error.message}`);
|
console.error(`[ERROR] Failed to remove volume: ${error.message}`);
|
||||||
response = { error: `Failed to remove volume: ${error.message}` };
|
response = { error: `Failed to remove volume: ${error.message}` };
|
||||||
@@ -1527,8 +1571,10 @@ async function initializeDockerEventStream() {
|
|||||||
try {
|
try {
|
||||||
const event = JSON.parse(chunk.toString());
|
const event = JSON.parse(chunk.toString());
|
||||||
if (event.status === "undefined") return;
|
if (event.status === "undefined") return;
|
||||||
logger.info('Docker event received', { status: event.status, id: event.id });
|
logger.info('Docker event received', { status: event.status, id: event.id, type: event.Type });
|
||||||
|
|
||||||
|
// Handle container events
|
||||||
|
if (event.Type === 'container') {
|
||||||
// Get updated container list and broadcast it to all connected peers
|
// Get updated container list and broadcast it to all connected peers
|
||||||
const containers = await docker.listContainers({ all: true });
|
const containers = await docker.listContainers({ all: true });
|
||||||
const update = { type: 'containers', data: containers };
|
const update = { type: 'containers', data: containers };
|
||||||
@@ -1540,6 +1586,31 @@ async function initializeDockerEventStream() {
|
|||||||
logger.error('Failed to send update to peer', { error: peerErr.message });
|
logger.error('Failed to send update to peer', { error: peerErr.message });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle volume events (create, destroy)
|
||||||
|
if (event.Type === 'volume' && (event.Action === 'create' || event.Action === 'destroy')) {
|
||||||
|
try {
|
||||||
|
const volumesResult = await docker.listVolumes();
|
||||||
|
const volumesList = volumesResult.Volumes || [];
|
||||||
|
const update = {
|
||||||
|
type: 'volumes',
|
||||||
|
data: volumesList,
|
||||||
|
success: true,
|
||||||
|
volumes: volumesList
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const peer of connectedPeers) {
|
||||||
|
try {
|
||||||
|
peer.write(JSON.stringify(update));
|
||||||
|
} catch (peerErr) {
|
||||||
|
logger.error('Failed to send volume update to peer', { error: peerErr.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (volErr) {
|
||||||
|
logger.error('Failed to fetch volumes after event', { error: volErr.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to process Docker event', { error: err.message });
|
logger.error('Failed to process Docker event', { error: err.message });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user