From b4e25ae66d81f7a91e8240316290b2284abfc11b Mon Sep 17 00:00:00 2001 From: MacRimi Date: Mon, 29 Sep 2025 18:07:30 +0200 Subject: [PATCH] Update AppImage --- AppImage/public/favicon.ico | Bin 0 -> 15086 bytes AppImage/scripts/build_appimage.sh | 11 + AppImage/scripts/flask_server.py | 522 ++++++----------------------- 3 files changed, 114 insertions(+), 419 deletions(-) create mode 100644 AppImage/public/favicon.ico diff --git a/AppImage/public/favicon.ico b/AppImage/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..35feec340e3a49197d487e87535d6525e2792f4e GIT binary patch literal 15086 zcmeHOO>Y}j6urjOvp~Yxu|e1ikXTkipn{AYRgp*~#4al~U9#yvK-dxz?Aar>{0j^c z;yIb45@@ByzLqG#WzecRacjoiL{L*IJVYk2h#^ZQ2a z*T$Z2fmw-#2Q%HuiiYw{PFjx1RMHUOmM8zES(NvF97PtN6A$U26vh_6lF^NpPK zVR>ymcWrswtl`x|>qqhaVQY3hnNGh}oIl#SUH3n@cdGd7{gRZm(x~@*^!f>nggqFU z(HuIqeBL_6v+mLSHum^qIXfR($2d^a9%FGxL-OEi!Wc)a*2F9In0KjNh5zX2Xc(JM zshymh^qbBjb`CL(7;kJYrxw#f%{z~n7Und@`n#xUtx&AbBc`e6V|`nwJ<{54yr^DC z{rS)J2VI_jl*57f80PRc&4l!t=0f!lpX5U`Ir*55uH|scjOIX`%cbX-s|UU|s5w&O zcMlI=*BYsFp+3!(6Nh-4^3ZDP3)L~-6^3-W&UfWE#M8B3@J%L1uZ1+Xk%w*6c# z-w>S&eo6Gb;OG1TM{tpY>)B@Re7M1~*x;g9<71+^@UDnPg6Bj-!IIzm*4STCjRj{U zKjKcoIZraO(S_jM^=v8la5Z8I_FER~8d*mWI-H!9ycQj1>MdD^bG-$B)vpkXlIA=> ztTPgvJ*Gmis`xf6Zmz1OEQeJkIy9;((V=-&i6LC4LatX?x7Cd^S#zTRGhL$Gr#0r| zkdJ5SJ}vqEWy@Q6$oskwF`hTJt&jJ}@S$}Pqt-P-TO%|zcC8COt&3ReB1V7L2u+R9 z)Y!Ey__Qu!t&14_T_ZF#LQ`XkF8{A{rFqh3p8S8M)(JB)Zmo}8Dq5Y;TI(W)hUg=!I%RVsA!r(6iWv!|U~OZ9JsRdp#++6dxWB=Db=?4ty5ndlBIKE0F(RKloC5CzHcN z^lMC+wLN-X$F|Q~>wby7o>0!thSs5ZoyV-s#bWfQVvMUzEmben*G5bChWK*xnmZQf z@~6)2QyU(w2jq8+;$zpER!?>f{;sNrKULLT-do^J6mzU+Ww9ESg?ue~<$yo>HRvtI zgQBFt@SFy-H4WA?D$a+?i=Gwte8w9eBPz-vZ+G;Gd+Kct-r|t$jZsyt=De*T+Okh^ zz{i-6ZSPa$TyOas!PYLHCnaw4z~6iP%(a=7-jsRtc-*LY`lwmdJgC`uR=3 zjiH`F9P9ULxpS6F_BOx!mv>G1sYH(Hr$jei<=ThHV@@H3X6HRXL`el9|;eF-e Mbh8h8@zg{A0V>v4DF6Tf literal 0 HcmV?d00001 diff --git a/AppImage/scripts/build_appimage.sh b/AppImage/scripts/build_appimage.sh index e65f6ce..eaef42b 100644 --- a/AppImage/scripts/build_appimage.sh +++ b/AppImage/scripts/build_appimage.sh @@ -194,9 +194,20 @@ chmod +x "$APP_DIR/usr/bin/translate_cli.py" # Copy Next.js build echo "📋 Copying web dashboard..." if [ -d "$APPIMAGE_ROOT/.next" ]; then + mkdir -p "$APP_DIR/web" cp -r "$APPIMAGE_ROOT/.next" "$APP_DIR/web/" cp -r "$APPIMAGE_ROOT/public" "$APP_DIR/web/" cp "$APPIMAGE_ROOT/package.json" "$APP_DIR/web/" + + # Also try to create a static export if possible + cd "$APPIMAGE_ROOT" + if npm run export 2>/dev/null; then + echo "✅ Next.js static export created" + if [ -d "out" ]; then + cp -r "out" "$APP_DIR/web/" + fi + fi + echo "✅ Next.js build copied successfully" else echo "❌ Error: Next.js build not found even after building" diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py index 02a8564..122421f 100644 --- a/AppImage/scripts/flask_server.py +++ b/AppImage/scripts/flask_server.py @@ -21,419 +21,82 @@ CORS(app) # Enable CORS for Next.js frontend @app.route('/') def serve_dashboard(): - """Serve the main dashboard page""" + """Serve the main dashboard page from Next.js build""" try: - web_dir = os.path.join(os.path.dirname(__file__), '..', '.next', 'static') - index_file = os.path.join(os.path.dirname(__file__), '..', '.next', 'server', 'app', 'page.html') + next_dir = os.path.join(os.path.dirname(__file__), '..', 'web', '.next') + + # Try to serve the Next.js built index page + index_paths = [ + os.path.join(next_dir, 'server', 'app', 'page.html'), + os.path.join(next_dir, 'server', 'pages', 'index.html'), + os.path.join(os.path.dirname(__file__), '..', 'web', 'out', 'index.html'), + os.path.join(os.path.dirname(__file__), '..', 'web', 'dist', 'index.html') + ] + + for index_path in index_paths: + if os.path.exists(index_path): + return send_file(index_path) + + # If no Next.js build found, return error message + return ''' + + + ProxMenux Monitor - Build Error + +

🚨 ProxMenux Monitor - Build Error

+

Next.js application not found. The AppImage may not have been built correctly.

+

Expected paths checked:

+
    ''' + ''.join([f'
  • {path}
  • ' for path in index_paths]) + '''
+

API endpoints are still available:

+ + + + ''', 500 - if os.path.exists(index_file): - return send_file(index_file) - else: - return ''' - - - - ProxMenux Monitor - - - - - - - - - - - -
-
-
- -
-
ProxMenux Monitor
-
Proxmox System Dashboard
-
-
- 📊 -
-
proxmox-01
-
pve-node-01
-
-
-
-
-
✅ Healthy
-
Uptime: 15d 7h 23m
- - - -
-
-
- -
-
-
- - - - - -
-
- -
-
-
-
CPU Usage
- 🖥️ -
-
67.3%
-
-
-
-
↓ 2.1% from last hour
-
- -
-
-
Memory Usage
- 💾 -
-
15.8 GB
-
-
-
-
49.4% of 32 GB • ↑ 1.2 GB
-
- -
-
-
Temperature
- 🌡️ -
-
52°C
-
- Normal -
-
Max: 78°C • Avg: 48°C
-
- -
-
-
Active VMs
- 🖥️ -
-
12
-
- 8 Running - 4 Stopped -
-
Total: 16 VMs configured
-
-
- -
-
-
- 📈 - CPU Usage (24h) -
-
- CPU Usage Chart
- Real-time data from /api/system -
-
- -
-
- 💾 - Memory Usage (24h) -
-
- Memory Usage Chart
- Real-time data from /api/system -
-
-
- -
-
-
- 🖥️ - System Information -
-
- Hostname: - proxmox-01 -
-
- Version: - PVE 8.1.3 -
-
- Kernel: - 6.5.11-7-pve -
-
- Architecture: - x86_64 -
-
- -
-
- 👥 - Active Sessions -
-
- Web Console: - 3 active -
-
- SSH Sessions: - 1 active -
-
- API Calls: - 247/hour -
-
- -
-
- - Power & Performance -
-
- Power State: - Running -
-
- Load Average: - 1.23, 1.45, 1.67 -
-
- Boot Time: - 2.3s -
-
-
- - -
- - - - - ''' except Exception as e: print(f"Error serving dashboard: {e}") - return jsonify({'error': 'Dashboard not available'}), 500 + return jsonify({'error': f'Dashboard not available: {str(e)}'}), 500 @app.route('/manifest.json') def serve_manifest(): """Serve PWA manifest""" - return send_from_directory(os.path.join(os.path.dirname(__file__), '..', 'public'), 'manifest.json') + try: + manifest_paths = [ + os.path.join(os.path.dirname(__file__), '..', 'web', 'public', 'manifest.json'), + os.path.join(os.path.dirname(__file__), '..', 'public', 'manifest.json') + ] + + for manifest_path in manifest_paths: + if os.path.exists(manifest_path): + return send_file(manifest_path) + + # Return default manifest if not found + return jsonify({ + "name": "ProxMenux Monitor", + "short_name": "ProxMenux", + "description": "Proxmox System Monitoring Dashboard", + "start_url": "/", + "display": "standalone", + "background_color": "#0a0a0a", + "theme_color": "#4f46e5", + "icons": [ + { + "src": "/images/proxmenux-logo.png", + "sizes": "256x256", + "type": "image/png" + } + ] + }) + except Exception as e: + print(f"Error serving manifest: {e}") + return jsonify({}), 404 @app.route('/sw.js') def serve_sw(): @@ -463,19 +126,34 @@ def serve_sw(): }); ''', 200, {'Content-Type': 'application/javascript'} +@app.route('/_next/') +def serve_next_static(filename): + """Serve Next.js static files""" + try: + next_static_dir = os.path.join(os.path.dirname(__file__), '..', 'web', '.next', 'static') + if os.path.exists(os.path.join(next_static_dir, filename)): + return send_from_directory(next_static_dir, filename) + return '', 404 + except Exception as e: + print(f"Error serving Next.js static file {filename}: {e}") + return '', 404 + @app.route('/') def serve_static_files(filename): """Serve static files (icons, etc.)""" try: - # Try public directory first - public_dir = os.path.join(os.path.dirname(__file__), '..', 'public') - if os.path.exists(os.path.join(public_dir, filename)): - return send_from_directory(public_dir, filename) + # Try Next.js public directory first + public_paths = [ + os.path.join(os.path.dirname(__file__), '..', 'web', 'public'), + os.path.join(os.path.dirname(__file__), '..', 'public'), + os.path.join(os.path.dirname(__file__), '..', 'web', 'out'), + os.path.join(os.path.dirname(__file__), '..', 'web', '.next', 'static') + ] - # Try Next.js static directory - static_dir = os.path.join(os.path.dirname(__file__), '..', '.next', 'static') - if os.path.exists(os.path.join(static_dir, filename)): - return send_from_directory(static_dir, filename) + for public_dir in public_paths: + file_path = os.path.join(public_dir, filename) + if os.path.exists(file_path): + return send_from_directory(public_dir, filename) return '', 404 except Exception as e: @@ -486,12 +164,18 @@ def serve_static_files(filename): def serve_images(filename): """Serve image files""" try: - web_dir = os.path.join(os.path.dirname(__file__), '..', 'web', 'public', 'images') - if os.path.exists(os.path.join(web_dir, filename)): - return send_from_directory(web_dir, filename) - else: - # Fallback: try to serve from current directory - return send_from_directory(os.path.dirname(__file__), filename) + image_paths = [ + os.path.join(os.path.dirname(__file__), '..', 'web', 'public', 'images'), + os.path.join(os.path.dirname(__file__), '..', 'public', 'images'), + os.path.dirname(__file__) + ] + + for image_dir in image_paths: + file_path = os.path.join(image_dir, filename) + if os.path.exists(file_path): + return send_from_directory(image_dir, filename) + + return '', 404 except Exception as e: print(f"Error serving image {filename}: {e}") return '', 404