Compare commits
No commits in common. "18ff440115519a4687c127dd14c25d8e54ae71cf" and "32080e5aef8403dea55301b75a599609270308cf" have entirely different histories.
18ff440115
...
32080e5aef
@ -119,10 +119,6 @@
|
||||
<button class="main-tab-button" data-tab="backups" onclick="if(window.appTabbedManager) window.appTabbedManager.switchTab('backups')">
|
||||
<span class="tab-emoji">💾</span>
|
||||
<span class="tab-name">Backups</span>
|
||||
</button>
|
||||
<button class="main-tab-button" data-tab="updater" onclick="if(window.appTabbedManager) window.appTabbedManager.switchTab('updater')">
|
||||
<span class="tab-emoji">⬆️</span>
|
||||
<span class="tab-name">Updates</span>
|
||||
</button>
|
||||
<button class="main-tab-button" data-tab="tasks" onclick="if(window.appTabbedManager) window.appTabbedManager.switchTab('tasks')">
|
||||
<span class="tab-emoji">📋</span>
|
||||
@ -226,13 +222,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Updates Tab (per-app: version state, CVEs, recovery, history) -->
|
||||
<div class="tab-pane" id="updater-tab">
|
||||
<div class="app-updater-section" id="app-updater-section">
|
||||
<div class="updater-empty">Loading…</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tasks Tab -->
|
||||
<div class="tab-pane" id="tasks-tab">
|
||||
<div class="tasks-section">
|
||||
|
||||
@ -292,10 +292,6 @@ class AppTabbedManager {
|
||||
// IMPORTANT: Re-apply button state if there are running tasks
|
||||
this.restoreButtonState();
|
||||
break;
|
||||
case 'updater':
|
||||
await this.loadAppUpdater();
|
||||
this.restoreButtonState();
|
||||
break;
|
||||
case 'services':
|
||||
if (window.servicesManager) {
|
||||
await window.servicesManager.load(this.currentApp);
|
||||
@ -557,62 +553,6 @@ class AppTabbedManager {
|
||||
await this.backupAppCard.render();
|
||||
}
|
||||
|
||||
// Load the per-app Updates tab — version state + CVEs + recovery + history for
|
||||
// the current app. Reuses the headless UpdaterPage: the same data layer the
|
||||
// fleet Overview uses, and renderAppDetail() for the body. Actions dispatch
|
||||
// through the task system, identical to the fleet view.
|
||||
async loadAppUpdater() {
|
||||
const section = document.getElementById('app-updater-section');
|
||||
if (!section) return;
|
||||
if (typeof UpdaterPage === 'undefined') {
|
||||
section.innerHTML = '<div class="updater-empty">Updater unavailable.</div>';
|
||||
return;
|
||||
}
|
||||
if (!this.appUpdater) this.appUpdater = new UpdaterPage((window.LP && window.LP.services) || {});
|
||||
|
||||
// One delegated listener scoped to this section (the pane lives in the
|
||||
// shared layout, replaced on full navigation, so it GCs with the node).
|
||||
if (section.dataset.updBound !== '1') {
|
||||
section.dataset.updBound = '1';
|
||||
section.addEventListener('click', (e) => {
|
||||
const a = e.target.closest('[data-updater-action]');
|
||||
if (!a) return;
|
||||
const app = a.dataset.app || this.currentApp;
|
||||
switch (a.dataset.updaterAction) {
|
||||
case 'check': this.appUpdater.checkForUpdates(); break;
|
||||
case 'update': this.appUpdater.applyUpdate(app); break;
|
||||
case 'rollback': this.appUpdater.rollback(app); break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
section.innerHTML = '<div class="updater-empty">Loading…</div>';
|
||||
await this.appUpdater.refreshAll();
|
||||
const app = (this.appUpdater.apps || []).find((x) => x.name === this.currentApp);
|
||||
if (!app) {
|
||||
section.innerHTML = `<div class="updater-empty">No update data for this app yet. <button class="updater-btn updater-btn-primary" data-updater-action="check">Check now</button></div>`;
|
||||
return;
|
||||
}
|
||||
section.innerHTML = this.renderAppUpdaterHead(app) + this.appUpdater.renderAppDetail(app);
|
||||
}
|
||||
|
||||
renderAppUpdaterHead(a) {
|
||||
const up = this.appUpdater;
|
||||
const esc = (s) => up.escape(s);
|
||||
const cur = esc(a.current_version || a.current_image || '—');
|
||||
const avail = a.update_available ? esc(a.available_version || a.available_image || 'newer') : null;
|
||||
const badge = a.update_available
|
||||
? `<span class="updater-badge updater-badge-update">update available</span>`
|
||||
: (a.scanned ? `<span class="updater-badge updater-badge-ok">up to date</span>` : `<span class="updater-badge updater-badge-unknown">unscanned</span>`);
|
||||
const updBtn = a.update_available
|
||||
? `<button class="updater-btn updater-btn-primary" data-updater-action="update" data-app="${esc(a.name)}">Update</button>`
|
||||
: '';
|
||||
return `<div class="app-updater-head">
|
||||
<div class="app-updater-head-main">${badge} <span class="updater-row-ver">${cur}${avail ? ` <span class="updater-arrow">→</span> <strong>${avail}</strong>` : ''}</span></div>
|
||||
<div class="app-updater-head-actions"><button class="updater-btn" data-updater-action="check">↻ Check</button> ${updBtn}</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// Initialize the tabbed manager
|
||||
async initialize() {
|
||||
// Prevent double initialization
|
||||
@ -909,7 +849,7 @@ class AppTabbedManager {
|
||||
|
||||
// Disable config, services and backup tabs when task is running
|
||||
disableTabs() {
|
||||
const tabs = ['config', 'services', 'tools', 'backups', 'updater']
|
||||
const tabs = ['config', 'services', 'tools', 'backups']
|
||||
.map(name => document.querySelector(`.main-tab-button[data-tab="${name}"], .tab-button[data-tab="${name}"]`))
|
||||
.filter(Boolean);
|
||||
|
||||
@ -924,7 +864,7 @@ class AppTabbedManager {
|
||||
|
||||
// Enable config, services and backup tabs when task completes
|
||||
enableTabs() {
|
||||
const tabs = ['config', 'services', 'tools', 'backups', 'updater']
|
||||
const tabs = ['config', 'services', 'tools', 'backups']
|
||||
.map(name => document.querySelector(`.main-tab-button[data-tab="${name}"], .tab-button[data-tab="${name}"]`))
|
||||
.filter(Boolean);
|
||||
|
||||
|
||||
@ -172,20 +172,3 @@
|
||||
border-bottom: 1px solid var(--border-color, rgba(255, 255, 255, .08));
|
||||
}
|
||||
.ov-loc-row span:first-child { font-weight: 500; }
|
||||
|
||||
/* ---- per-app Updates tab header ----------------------------------------- */
|
||||
.app-updater-section { padding: 4px 0; }
|
||||
.app-updater-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
padding: 12px 14px;
|
||||
border: 1px solid var(--border-color, rgba(255, 255, 255, .12));
|
||||
border-radius: 10px;
|
||||
background: var(--input-bg, rgba(255, 255, 255, .03));
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.app-updater-head-main { display: flex; align-items: center; gap: 10px; }
|
||||
.app-updater-head-actions { display: flex; gap: 8px; }
|
||||
|
||||
@ -195,7 +195,6 @@ class SystemLoader {
|
||||
'/components/apps/port-manager/js/port-manager.js',
|
||||
'/core/tasks/js/task-manager.js', // Add TaskManager for backup functionality
|
||||
'/core/backup-card/js/backup-app-card.js',
|
||||
'/components/updater/js/updater-page.js', // headless reuse: per-app Updates tab + fleet Overview
|
||||
'/components/apps/services/js/services-manager.js',
|
||||
'/components/apps/tools/js/tools-manager.js',
|
||||
'/components/apps/routing/js/routing-manager.js',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user