container details area

This commit is contained in:
Raven Scott
2025-11-24 17:42:56 -05:00
parent 3b9efe24c3
commit 664848c1b5
2 changed files with 86 additions and 8 deletions
+46 -8
View File
@@ -1136,11 +1136,15 @@ function updateStatsCharts(containerId) {
<div class="row g-3">
<div class="col-12">
<h6 class="mb-3">CPU Usage</h6>
<canvas id="cpu-chart-canvas" height="100"></canvas>
<div class="chart-wrapper" style="height: 250px; position: relative;">
<canvas id="cpu-chart-canvas"></canvas>
</div>
</div>
<div class="col-12">
<h6 class="mb-3">Memory Usage</h6>
<canvas id="memory-chart-canvas" height="100"></canvas>
<div class="chart-wrapper" style="height: 250px; position: relative;">
<canvas id="memory-chart-canvas"></canvas>
</div>
</div>
</div>
`;
@@ -1309,7 +1313,16 @@ document.addEventListener('DOMContentLoaded', () => {
// Bulk Operations Functions
function getSelectedContainers() {
const checkboxes = document.querySelectorAll('.container-checkbox:checked');
return Array.from(checkboxes).map(cb => cb.dataset.containerId);
const selected = Array.from(checkboxes).map(cb => {
// Try dataset first, fallback to getAttribute for compatibility
const id = cb.dataset.containerId || cb.getAttribute('data-container-id');
if (!id) {
console.warn('[WARN] Checkbox missing container ID:', cb);
}
return id;
}).filter(id => id); // Filter out any undefined/null values
console.log('[DEBUG] getSelectedContainers - found', selected.length, 'selected containers');
return selected;
}
function getSelectedImages() {
@@ -1377,7 +1390,11 @@ function clearImageSelection() {
async function bulkStartContainers() {
const selected = getSelectedContainers();
if (selected.length === 0) return;
console.log('[DEBUG] bulkStartContainers - selected containers:', selected);
if (selected.length === 0) {
console.warn('[WARN] No containers selected');
return;
}
if (!confirm(`Start ${selected.length} container(s)?`)) return;
@@ -1404,7 +1421,11 @@ async function bulkStartContainers() {
async function bulkStopContainers() {
const selected = getSelectedContainers();
if (selected.length === 0) return;
console.log('[DEBUG] bulkStopContainers - selected containers:', selected);
if (selected.length === 0) {
console.warn('[WARN] No containers selected');
return;
}
if (!confirm(`Stop ${selected.length} container(s)?`)) return;
@@ -1431,7 +1452,11 @@ async function bulkStopContainers() {
async function bulkRemoveContainers() {
const selected = getSelectedContainers();
if (selected.length === 0) return;
console.log('[DEBUG] bulkRemoveContainers - selected containers:', selected);
if (selected.length === 0) {
console.warn('[WARN] No containers selected');
return;
}
if (!confirm(`Remove ${selected.length} container(s)? This action cannot be undone.`)) return;
@@ -2886,9 +2911,9 @@ function renderContainers(containers, topicId) {
row.innerHTML = `
<td>
<input type="checkbox" class="container-checkbox" data-container-id="${containerId}" onchange="updateBulkActionsToolbar()">
<input type="checkbox" class="container-checkbox" data-container-id="${containerId}">
</td>
<td>${name}</td>
<td><a href="#" class="container-name-link" data-container-id="${containerId}">${name}</a></td>
<td>${image}</td>
<td><span class="badge ${statusClass}">${state}</span></td>
<td class="cpu">
@@ -2942,6 +2967,11 @@ function renderContainers(containers, topicId) {
`;
fragment.appendChild(row);
// Add event listener for checkbox
const checkbox = row.querySelector('.container-checkbox');
if (checkbox) {
checkbox.addEventListener('change', () => updateBulkActionsToolbar());
}
// Add event listener for duplicate button
const duplicateBtn = row.querySelector('.action-duplicate');
duplicateBtn.addEventListener('click', () => openDuplicateModal(container));
@@ -2950,6 +2980,14 @@ function renderContainers(containers, topicId) {
if (detailsBtn) {
detailsBtn.addEventListener('click', () => showContainerDetails(container));
}
// Add event listener for clickable container name
const nameLink = row.querySelector('.container-name-link');
if (nameLink) {
nameLink.addEventListener('click', (e) => {
e.preventDefault();
showContainerDetails(container);
});
}
// Add event listeners for action buttons
addActionListeners(row, container);
});
+40
View File
@@ -1545,6 +1545,46 @@
--bs-table-accent-bg: rgba(99, 102, 241, 0.03);
}
/* Clickable Container Name Link - Portainer-style */
.container-name-link {
color: var(--accent-primary);
text-decoration: none;
font-weight: 500;
cursor: pointer;
transition: all var(--transition-fast);
display: inline-block;
}
.container-name-link:hover {
color: var(--accent-secondary);
text-decoration: underline;
transform: translateX(2px);
}
.container-name-link:active {
color: var(--accent-info);
transform: translateX(0);
}
.container-name-link:focus {
outline: 2px solid var(--accent-primary);
outline-offset: 2px;
border-radius: 2px;
}
/* Chart Wrapper Styles - Prevent vertical growth */
.chart-wrapper {
height: 250px;
position: relative;
width: 100%;
}
.chart-wrapper canvas {
max-height: 100%;
width: 100% !important;
height: 100% !important;
}
/* Modern Button Styles */
.btn {
border-radius: var(--border-radius-sm);