Add GPU/macvlan passthrough, container edit/update, image prune/tag
Create Container form: - GPU passthrough dropdown (AMD/Intel via /dev/dri detection, NVIDIA excluded since it needs a different runtime) - device paths strictly validated server-side against the host's own detected list. - Macvlan network support: selecting a macvlan network reveals a static IP field and hides port mappings (meaningless once the container has its own LAN address), matching Unraid Docker Manager's "Custom: br0" behavior. Networks panel gained a matching macvlan network-creation flow, with the parent-interface dropdown read from Unraid's own network.cfg so it lists exactly what Docker Manager itself offers. Containers panel: - Edit: reopens the create form pre-filled from the container's current config (image/ports/volumes/env/network/restart policy/GPU/static IP); saving stops+removes the old container and recreates it under the same settings, since podman/Docker have no in-place "modify" API for most of this. - Update: same stop/remove/recreate flow, but pulls the current image first. "Check for Updates" compares each in-use image's local digest against its origin registry (Docker Hub/GHCR/self-hosted registries all verified live) with no podman-side feature backing it - implemented via the registry's own HTTP API. A small log-modal shows progress for both actions instead of a silent wait. - Fixed a real bug hit live: PodmanClient's flat 15s HTTP timeout aborted real image pulls/container creates mid-request; bumped to 600s (nginx already allows up to 640s for this plugin's requests). Images panel: - "Prune unused" (removes every image with zero containers referencing it, not just dangling ones - confirmation copy says so explicitly since this is more aggressive than it sounds) and per-image "Tag". Also several real UI bugs found via live screenshots: unused-image prune having no visible effect until reloaded, table action-button columns drifting row to row (a bare "display:flex" on a <td> was fighting the table layout algorithm), Templates category badges dumping raw multi-tag strings from real Unraid templates, and low-contrast search/filter controls that were nearly invisible against the card background. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -229,6 +229,53 @@ window.Podman = (function () {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Small modal with a scrolling monospace log pane — for actions that run
|
||||
* several steps in sequence (checking/updating containers) where a plain
|
||||
* confirm()/alert() at the very end leaves the user with no feedback
|
||||
* that anything is happening while it runs. Returns {log, done} rather
|
||||
* than closing itself, since the caller knows when the whole sequence
|
||||
* (not just one call) has actually finished.
|
||||
*
|
||||
* @param {string} title
|
||||
* @returns {{log: (line: string) => void, done: (closeLabel?: string) => void}}
|
||||
*/
|
||||
function openLogModal(title) {
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.className = 'podman-modal-backdrop';
|
||||
backdrop.innerHTML = '' +
|
||||
'<div class="podman-modal podman-modal-wide" role="dialog" aria-modal="true">' +
|
||||
'<div class="podman-modal-head"><h3>' + escapeHtml(title) + '</h3></div>' +
|
||||
'<div class="podman-modal-body"><div class="podman-log-pane" id="podman-log-modal-pane"></div></div>' +
|
||||
'<div class="podman-modal-actions"><button type="button" class="podman-btn podman-btn-primary" data-role="close" disabled>Working…</button></div>' +
|
||||
'</div>';
|
||||
|
||||
(document.querySelector('.podman-plugin') || document.body).appendChild(backdrop);
|
||||
const pane = backdrop.querySelector('#podman-log-modal-pane');
|
||||
const closeBtn = backdrop.querySelector('[data-role="close"]');
|
||||
|
||||
function close() { backdrop.remove(); }
|
||||
closeBtn.addEventListener('click', close);
|
||||
backdrop.addEventListener('click', function (e) { if (e.target === backdrop) close(); });
|
||||
document.addEventListener('keydown', function onKey(e) {
|
||||
if (e.key === 'Escape' && !closeBtn.disabled) { close(); document.removeEventListener('keydown', onKey); }
|
||||
});
|
||||
|
||||
function log(line) {
|
||||
const row = document.createElement('div');
|
||||
row.textContent = line;
|
||||
pane.appendChild(row);
|
||||
pane.scrollTop = pane.scrollHeight;
|
||||
}
|
||||
|
||||
function done(closeLabel) {
|
||||
closeBtn.disabled = false;
|
||||
closeBtn.textContent = closeLabel || 'Close';
|
||||
}
|
||||
|
||||
return { log: log, done: done };
|
||||
}
|
||||
|
||||
/**
|
||||
* Small anchored dropdown menu — used for secondary per-row actions
|
||||
* (pause/kill/rename/...) that would otherwise clutter a table row with
|
||||
@@ -368,6 +415,7 @@ window.Podman = (function () {
|
||||
loadingRow: loadingRow,
|
||||
errorRow: errorRow,
|
||||
openFormModal: openFormModal,
|
||||
openLogModal: openLogModal,
|
||||
openContextMenu: openContextMenu,
|
||||
registerPanel: registerPanel,
|
||||
activatePanel: activatePanel,
|
||||
|
||||
Reference in New Issue
Block a user