Move Check updates into action bar and report results in the tray.
Release rolling / release (push) Successful in 11m35s
Release rolling / release (push) Successful in 11m35s
This commit is contained in:
@@ -8590,7 +8590,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
if (typeof window.refreshRegistryPanel === 'function') window.refreshRegistryPanel();
|
||||
});
|
||||
document.getElementById('check-image-updates-btn')?.addEventListener('click', () => {
|
||||
scheduleImageUpdateCheck({ force: true, clearCache: true, immediate: true });
|
||||
scheduleImageUpdateCheck({
|
||||
force: true,
|
||||
clearCache: true,
|
||||
immediate: true,
|
||||
notify: true,
|
||||
});
|
||||
});
|
||||
|
||||
// Prefer smart network modal for create buttons
|
||||
@@ -9712,7 +9717,8 @@ function ensureInitialImageUpdateCheck() {
|
||||
if (!peerId) return;
|
||||
if (imageUpdateInitialPeerId === peerId) return;
|
||||
imageUpdateInitialPeerId = peerId;
|
||||
scheduleImageUpdateCheck({ force: false, immediate: true, initial: true });
|
||||
// Silent: table indicators only — no tray spam on Containers tab open
|
||||
scheduleImageUpdateCheck({ force: false, immediate: true, initial: true, silent: true });
|
||||
}
|
||||
|
||||
async function runImageUpdateCheck(opts = {}) {
|
||||
@@ -9720,13 +9726,16 @@ async function runImageUpdateCheck(opts = {}) {
|
||||
if (currentView && currentView !== 'containers' && !opts.force) return;
|
||||
if (imageUpdateCheckInFlight && !opts.force) return;
|
||||
imageUpdateCheckInFlight = true;
|
||||
// Tray only for explicit user-triggered checks — suppress on page-load / background
|
||||
const notify =
|
||||
opts.notify === true || (opts.force === true && opts.initial !== true && opts.silent !== true);
|
||||
const silent = opts.silent === true || opts.initial === true || !notify;
|
||||
|
||||
const btn = document.getElementById('check-image-updates-btn');
|
||||
const line = document.getElementById('image-update-status-line');
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-sync-alt fa-spin me-1"></i>Checking…';
|
||||
btn.innerHTML = '<i class="fas fa-sync-alt fa-spin"></i><span>Checking…</span>';
|
||||
}
|
||||
if (line) line.textContent = 'Checking image digests against registries…';
|
||||
|
||||
// Mark visible rows as checking on force or first tab load (no client cache yet)
|
||||
const listElement = domCache.containerList || containerList;
|
||||
@@ -9765,12 +9774,12 @@ async function runImageUpdateCheck(opts = {}) {
|
||||
applyImageUpdateToRow(row, row._pdContainer);
|
||||
});
|
||||
}
|
||||
if (!silent) {
|
||||
const statuses = Object.values(byImage);
|
||||
const outdated = statuses.filter((s) => s.status === 'outdated').length;
|
||||
const updated = statuses.filter((s) => s.status === 'updated').length;
|
||||
const unknown = statuses.filter((s) => s.status === 'unknown' || s.status === 'skipped').length;
|
||||
const withErr = statuses.filter((s) => s.error).slice(0, 2);
|
||||
if (line) {
|
||||
let text =
|
||||
outdated > 0
|
||||
? `${outdated} image(s) have updates · ${updated} up to date · ${unknown} unknown/skipped`
|
||||
@@ -9782,20 +9791,28 @@ async function runImageUpdateCheck(opts = {}) {
|
||||
if (withErr.length) {
|
||||
text += ` — ${withErr.map((s) => s.error).join('; ')}`;
|
||||
}
|
||||
line.textContent = text;
|
||||
line.title = statuses
|
||||
.filter((s) => s.error)
|
||||
.map((s) => `${s.image}: ${s.error}`)
|
||||
.join('\n') || text;
|
||||
const trayType = outdated > 0 ? 'warning' : withErr.length ? 'warning' : 'info';
|
||||
if (typeof notificationManager?.add === 'function') {
|
||||
notificationManager.add(trayType, text, { badge: outdated > 0 });
|
||||
} else if (typeof showAlert === 'function') {
|
||||
showAlert(trayType, text);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if (line) line.textContent = err?.message || 'Update check failed';
|
||||
console.warn('[image-updates]', err);
|
||||
if (!silent) {
|
||||
const msg = err?.message || 'Update check failed';
|
||||
if (typeof notificationManager?.add === 'function') {
|
||||
notificationManager.add('danger', msg, { badge: true });
|
||||
} else if (typeof showAlert === 'function') {
|
||||
showAlert('danger', msg);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
imageUpdateCheckInFlight = false;
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-sync-alt me-1"></i>Check updates';
|
||||
btn.innerHTML = '<i class="fas fa-sync-alt"></i><span>Check updates</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-8
@@ -999,20 +999,15 @@
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="window.pruneResource && window.pruneResource('containers')" data-min-role="admin" title="Prune stopped containers">
|
||||
<i class="fas fa-broom"></i><span>Prune</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-info" id="check-image-updates-btn" title="Recheck registry digests for all containers">
|
||||
<i class="fas fa-sync-alt"></i><span>Check updates</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary containers-action-btn" data-bulk-op="clear" onclick="clearContainerSelection()" title="Clear selection" disabled>
|
||||
<i class="fas fa-times"></i><span>Clear</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2">
|
||||
<p class="small text-muted mb-0" id="image-update-status-line">
|
||||
Image updates: indicators compare local digests to the registry .
|
||||
</p>
|
||||
<button type="button" class="btn btn-sm btn-outline-info" id="check-image-updates-btn" title="Recheck registry digests for all containers">
|
||||
<i class="fas fa-sync-alt me-1"></i>Check updates
|
||||
</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-dark table-striped" id="containers-table">
|
||||
<thead>
|
||||
|
||||
Reference in New Issue
Block a user