Skip to content

Commit ebc865f

Browse files
author
Your Name
committed
v3.4.2: fix update modal not opening (portal scope isolation), fix hardcoded sidebar version display, fix version source drift in update.py
1 parent 89fd259 commit ebc865f

4 files changed

Lines changed: 53 additions & 38 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.4.1
1+
3.4.2

panel/routes/update.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,31 @@ def pkg_remove(p): return f'apt-get remove -y --purge {p} && apt-get autoremove
1616
def req(): return 'user' in session
1717

1818
GITHUB_REPO = 'BrowserlessAPI/VortexPanel'
19-
CURRENT_VERSION = 'v3.4.0'
2019
VERSION_FILE = '/opt/vortexpanel/version.txt'
2120
INSTALL_DIR = '/opt/vortexpanel'
2221
REPO_DIR = '/root/Vortexpanel'
22+
CURRENT_VERSION = 'v3.4.1' # last-resort only, used solely if nothing below is readable
2323

2424
_update_job = {'running': False, 'lines': [], 'done': False, 'success': False, 'error': ''}
2525

2626
def get_current_version():
27-
# 1. Check explicit version file written on update
27+
# 1. Check explicit version file written after a successful in-panel update
2828
if os.path.exists(VERSION_FILE):
2929
v = open(VERSION_FILE).read().strip()
3030
if v and v.startswith('v'): return v
31-
# 2. Check VERSION file in install dir
32-
vf = os.path.join(INSTALL_DIR, 'VERSION')
31+
# 2. Fall back to the repo's own VERSION file (/root/Vortexpanel/VERSION) --
32+
# this is the file git pull actually keeps current, unlike
33+
# /opt/vortexpanel/VERSION which nothing in the update process ever
34+
# writes (only panel/, web/, app.py get copied to INSTALL_DIR), so that
35+
# old check #2 here was silently dead code checking a file that could
36+
# never exist. Reading the repo source directly means this self-updates
37+
# on every git pull without needing a second hand-maintained constant.
38+
vf = os.path.join(REPO_DIR, 'VERSION')
3339
if os.path.exists(vf):
3440
v = open(vf).read().strip()
3541
if v: return 'v' + v.lstrip('v')
36-
# 3. Default to hardcoded constant — always valid semver
42+
# 3. Absolute last resort — hardcoded constant, only reached if the repo
43+
# checkout itself is somehow missing its VERSION file entirely.
3744
return CURRENT_VERSION
3845

3946
def save_current_version(version):

web/static/js/app.js

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ function rootApp() {
292292
online: true,
293293
moduleStatus: {},
294294
updateAvailable: false,
295+
panelVersion: '',
295296
updateModal: {
296297
show:false, current:'v3.1.0', latest:'', name:'',
297298
body:'', published:'', url:'', error:'',
@@ -412,6 +413,11 @@ function rootApp() {
412413
const r = await get('/api/modules');
413414
if (r.ok) r.modules.forEach(m => { this.moduleStatus[m.id] = m.installed; });
414415
} catch {}
416+
// Sidebar version display
417+
try {
418+
const uv = await get('/api/update/version');
419+
if (uv.ok) this.panelVersion = uv.version;
420+
} catch {}
415421
// Silent update check after 3s
416422
setTimeout(() => this.silentUpdateCheck(), 3000);
417423
document.dispatchEvent(new CustomEvent('vortex-logged-in'));
@@ -466,10 +472,7 @@ function rootApp() {
466472
},
467473

468474
async openUpdateModal() {
469-
this.updateModal.show = true;
470-
this.$nextTick(() => {
471-
document.dispatchEvent(new CustomEvent('vortex-check-update'));
472-
});
475+
document.dispatchEvent(new CustomEvent('vortex-open-update-modal'));
473476
},
474477
};
475478
}
@@ -498,7 +501,7 @@ function dashboardPage() {
498501
async init() {
499502
await Promise.all([this.loadStats(),this.loadServices(),this.loadSslAlerts()]);
500503
this.loading = false;
501-
this.$nextTick(() => this._initCharts());
504+
this._waitForChartJs();
502505
setInterval(()=>this.loadStats(),5000);
503506
setInterval(()=>this.loadSslAlerts(),60000); // recheck every minute, not every 5s
504507
document.addEventListener("vortex-logged-in", () => { this.init(); });
@@ -556,6 +559,12 @@ function dashboardPage() {
556559
};
557560
},
558561

562+
_waitForChartJs(attempt = 0) {
563+
if (typeof Chart !== 'undefined') { this.$nextTick(() => this._initCharts()); return; }
564+
if (attempt >= 40) { console.warn('[VortexPanel] Chart.js failed to load after 10s — dashboard charts will stay empty. Check the Network tab for a failed request to cdnjs.cloudflare.com/ajax/libs/Chart.js.'); return; }
565+
setTimeout(() => this._waitForChartJs(attempt + 1), 250);
566+
},
567+
559568
_initCharts() {
560569
if (typeof Chart === 'undefined') return; // CDN not loaded yet — retry next tick
561570
const c = this._chartColors();
@@ -4676,12 +4685,14 @@ function cdnPage() {
46764685
// --- UPDATE MODAL ---------------------------------------------------------------
46774686
function updateModalData() {
46784687
return {
4688+
show: false, current: '', latest: '', name: '', body: '', published: '',
46794689
checkState: 'checking',
46804690
updating: false, updateDone: false, updateSuccess: false,
46814691
updateError: '', updateLines: [], updateProgress: 0,
46824692
errorMsg: '', _pollTimer: null,
46834693

46844694
async init() {
4695+
document.addEventListener('vortex-open-update-modal', ()=>{ this.show=true; this.checkForUpdates(); });
46854696
document.addEventListener('vortex-check-update', ()=>this.checkForUpdates());
46864697
await this.checkForUpdates();
46874698
},
@@ -4691,18 +4702,19 @@ function updateModalData() {
46914702
try {
46924703
const r = await get('/api/update/check');
46934704

4694-
// Sync version to parent rootApp
4705+
this.current = r.current || 'v3.0.0';
4706+
this.latest = r.latest || r.current || 'v3.0.0';
4707+
this.name = r.name || 'VortexPanel';
4708+
this.body = r.body || '';
4709+
this.published = r.published || '';
4710+
4711+
// Sync updateAvailable to rootApp -- that flag drives the topbar
4712+
// button's glow/badge, which genuinely lives in rootApp's own scope
4713+
// (unlike this modal, which sits in the disconnected portal).
46954714
try {
46964715
const appEl = document.querySelector('[x-data="rootApp()"]');
46974716
const app = appEl ? Alpine.$data(appEl) : null;
4698-
if (app) {
4699-
app.updateModal.current = r.current || 'v3.0.0';
4700-
app.updateModal.latest = r.latest || r.current || 'v3.0.0';
4701-
app.updateModal.name = r.name || 'VortexPanel';
4702-
app.updateModal.body = r.body || '';
4703-
app.updateModal.published = r.published || '';
4704-
if (r.has_update) app.updateAvailable = true;
4705-
}
4717+
if (app && r.has_update) app.updateAvailable = true;
47064718
} catch {}
47074719

47084720
if (r.error && !r.current) { this.errorMsg=r.error; this.checkState='error'; return; }
@@ -4715,11 +4727,7 @@ function updateModalData() {
47154727
},
47164728

47174729
async startUpdate() {
4718-
let version = '';
4719-
try {
4720-
const appEl = document.querySelector('[x-data="rootApp()"]');
4721-
if (appEl) version = Alpine.$data(appEl).updateModal.latest || '';
4722-
} catch {}
4730+
const version = this.latest || '';
47234731
this.updating=true; this.updateDone=false; this.updateSuccess=false;
47244732
this.updateLines=[`🚀 Starting update to ${version}…`]; this.updateProgress=5;
47254733
const r = await post('/api/update/start', {version});

web/templates/index.html

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@
103103
<div class="logo-icon">⚡</div>
104104
<div>
105105
<div class="logo-text">VortexPanel</div>
106-
<div class="logo-ver">v3.4</div>
106+
<div class="logo-ver" x-text="panelVersion||'v3.4'"></div>
107107
</div>
108108
</div>
109109

@@ -7976,9 +7976,9 @@
79767976
</div>
79777977

79787978
<!-- PANEL UPDATE MODAL -->
7979-
<div class="modal-overlay" x-show="updateModal.show" style="z-index:500"
7979+
<div class="modal-overlay" x-show="show" style="z-index:500"
79807980
x-data="updateModalData()"
7981-
@click.self="updateModal.show=false">
7981+
@click.self="show=false">
79827982
<div class="modal" style="max-width:600px">
79837983

79847984
<!-- Header -->
@@ -7988,11 +7988,11 @@
79887988
<div>
79897989
<div class="modal-title">VortexPanel Update</div>
79907990
<div style="font-size:11px;color:var(--text-muted);margin-top:1px">
7991-
Current: <span style="font-family:var(--font-mono);color:var(--accent)" x-text="updateModal.current"></span>
7991+
Current: <span style="font-family:var(--font-mono);color:var(--accent)" x-text="current"></span>
79927992
</div>
79937993
</div>
79947994
</div>
7995-
<button class="modal-close" @click="updateModal.show=false">×</button>
7995+
<button class="modal-close" @click="show=false">×</button>
79967996
</div>
79977997

79987998
<!-- Checking state -->
@@ -8005,7 +8005,7 @@
80058005
<div x-show="checkState==='uptodate'" style="text-align:center;padding:32px">
80068006
<div style="font-size:40px;margin-bottom:12px">✅</div>
80078007
<div style="font-size:16px;font-weight:600;margin-bottom:6px">You are up to date!</div>
8008-
<div style="font-size:13px;color:var(--text-muted)" x-text="'VortexPanel '+(updateModal.current||'v3.0.0')+' is the latest version'"></div>
8008+
<div style="font-size:13px;color:var(--text-muted)" x-text="'VortexPanel '+(current||'v3.0.0')+' is the latest version'"></div>
80098009
<div style="margin-top:16px">
80108010
<a href="https://github.com/BrowserlessAPI/Vortexpanel/releases" target="_blank" style="font-size:12px;color:var(--accent);text-decoration:none">View all releases on GitHub ↗</a>
80118011
</div>
@@ -8018,20 +8018,20 @@
80188018
<div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px">
80198019
<div>
80208020
<div style="font-size:12px;color:var(--text-muted);margin-bottom:3px">New version available</div>
8021-
<div style="font-size:22px;font-weight:700;color:var(--accent)" x-text="updateModal.latest"></div>
8021+
<div style="font-size:22px;font-weight:700;color:var(--accent)" x-text="latest"></div>
80228022
</div>
80238023
<div style="text-align:right">
80248024
<div style="font-size:11px;color:var(--text-muted)">Released</div>
8025-
<div style="font-size:12px;font-weight:500" x-text="updateModal.published ? new Date(updateModal.published).toLocaleDateString() : ''"></div>
8025+
<div style="font-size:12px;font-weight:500" x-text="published ? new Date(published).toLocaleDateString() : ''"></div>
80268026
</div>
80278027
</div>
80288028
</div>
80298029

80308030
<!-- Release notes -->
8031-
<div x-show="updateModal.body" style="margin-bottom:16px">
8031+
<div x-show="body" style="margin-bottom:16px">
80328032
<div style="font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:8px;text-transform:uppercase;letter-spacing:.5px">📋 What's New</div>
80338033
<div style="background:var(--bg-raised);border:1px solid var(--border);border-radius:8px;padding:14px;max-height:200px;overflow-y:auto;font-size:12px;color:var(--text-secondary);line-height:1.7;white-space:pre-wrap"
8034-
x-text="updateModal.body"></div>
8034+
x-text="body"></div>
80358035
</div>
80368036

80378037
<!-- Warning -->
@@ -8040,7 +8040,7 @@
80408040
</div>
80418041

80428042
<button class="btn btn-primary" style="width:100%;justify-content:center;font-size:14px;padding:12px" @click="startUpdate()">
8043-
Update to <span x-text="updateModal.latest" style="margin-left:4px"></span>
8043+
Update to <span x-text="latest" style="margin-left:4px"></span>
80448044
</button>
80458045
</div>
80468046

@@ -8094,9 +8094,9 @@
80948094
</div>
80958095
<div x-show="updateDone && !updateSuccess" style="font-size:12px;color:var(--red)" x-text="'✗ '+updateError"></div>
80968096
<div style="flex:1"></div>
8097-
<button class="btn btn-ghost" @click="updateModal.show=false" x-show="!updateDone">Running...</button>
8097+
<button class="btn btn-ghost" @click="show=false" x-show="!updateDone">Running...</button>
80988098
<button class="btn btn-primary" @click="location.reload()" x-show="updateDone && updateSuccess">Reload Page</button>
8099-
<button class="btn btn-ghost" @click="updateModal.show=false" x-show="updateDone && !updateSuccess">Close</button>
8099+
<button class="btn btn-ghost" @click="show=false" x-show="updateDone && !updateSuccess">Close</button>
81008100
</div>
81018101
</div>
81028102

0 commit comments

Comments
 (0)