From 80953a0148cfc1d899ca3cef4cdbcdc29288d1bf Mon Sep 17 00:00:00 2001 From: MacRimi Date: Sat, 11 Oct 2025 16:25:22 +0200 Subject: [PATCH] Update AppImage --- AppImage/components/system-logs.tsx | 62 ++++++++++++++-------------- AppImage/scripts/flask_server.py | 63 ++++++++++++++++++++++++++--- 2 files changed, 89 insertions(+), 36 deletions(-) diff --git a/AppImage/components/system-logs.tsx b/AppImage/components/system-logs.tsx index 2799b78..0f6b576 100644 --- a/AppImage/components/system-logs.tsx +++ b/AppImage/components/system-logs.tsx @@ -23,7 +23,6 @@ import { RefreshCw, Bell, Mail, - Eye, } from "lucide-react" import { useState, useEffect } from "react" @@ -510,14 +509,13 @@ export function SystemLogs() {
-
{log.service}
-
- -
{log.timestamp}
+
{log.service}
+
+ {log.timestamp}
{log.message}
-
+
Source: {log.source} {log.pid && ` • PID: ${log.pid}`} {log.hostname && ` • Host: ${log.hostname}`} @@ -550,27 +548,24 @@ export function SystemLogs() { }} >
- + {getLevelIcon(event.level)} - {event.status} + {event.status}
-
-
+
+
{event.type} {event.vmid && ` (VM/CT ${event.vmid})`}
-
- -
{event.duration}
-
+
{event.duration}
-
+
Node: {event.node} • User: {event.user}
-
Started: {event.starttime}
+
{event.starttime}
))} @@ -624,8 +619,8 @@ export function SystemLogs() {
-
-
+
+
{getBackupTypeLabel(backup.volid)} @@ -633,14 +628,17 @@ export function SystemLogs() { {getBackupStorageLabel(backup.volid)}
- + {backup.size_human}
-
Storage: {backup.storage}
+
Storage: {backup.storage}
- - {backup.created} + + {backup.created}
@@ -673,13 +671,15 @@ export function SystemLogs() {
-
+
{notification.type}
-
{notification.timestamp}
+
+ {notification.timestamp} +
-
{notification.message}
-
+
{notification.message}
+
Service: {notification.service} • Source: {notification.source}
@@ -845,16 +845,18 @@ export function SystemLogs() {
Storage
{selectedBackup.storage}
+
+
Size
+ + {selectedBackup.size_human} + +
{selectedBackup.vmid && (
VM/CT ID
{selectedBackup.vmid}
)} -
-
Size
-
{selectedBackup.size_human}
-
Created
{selectedBackup.created}
diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py index 96174a9..2ab2d55 100644 --- a/AppImage/scripts/flask_server.py +++ b/AppImage/scripts/flask_server.py @@ -3403,23 +3403,33 @@ def api_logs(): def api_logs_download(): """Download system logs as a text file""" try: - log_type = request.args.get('type', 'system') # system, kernel, auth - lines = request.args.get('lines', '1000') + log_type = request.args.get('type', 'system') + hours = int(request.args.get('hours', '48')) # Changed from lines to hours, default 48h + level = request.args.get('level', 'all') # Added level filter + service = request.args.get('service', 'all') # Added service filter + + cmd = ['journalctl', '--since', f'{hours} hours ago', '--no-pager'] if log_type == 'kernel': - cmd = ['journalctl', '-k', '-n', lines, '--no-pager'] + cmd.extend(['-k']) filename = 'kernel.log' elif log_type == 'auth': - cmd = ['journalctl', '-u', 'ssh', '-u', 'sshd', '-n', lines, '--no-pager'] + cmd.extend(['-u', 'ssh', '-u', 'sshd']) filename = 'auth.log' else: - cmd = ['journalctl', '-n', lines, '--no-pager'] filename = 'system.log' + # Apply level filter + if level != 'all': + cmd.extend(['-p', level]) + + # Apply service filter + if service != 'all': + cmd.extend(['-u', service]) + result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) if result.returncode == 0: - # Create a temporary file import tempfile with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.log') as f: f.write(result.stdout) @@ -3550,6 +3560,47 @@ def api_notifications(): 'total': 0 }) +@app.route('/api/notifications/download', methods=['GET']) +def api_notifications_download(): + """Download complete log for a specific notification""" + try: + timestamp = request.args.get('timestamp', '') + + if not timestamp: + return jsonify({'error': 'Timestamp parameter required'}), 400 + + # Get logs around the notification timestamp (1 hour before and after) + cmd = [ + 'journalctl', + '--since', f'{timestamp}', + '--until', f'{timestamp}', + '-n', '1000', + '--no-pager' + ] + + result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) + + if result.returncode == 0: + import tempfile + with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.log') as f: + f.write(f"Notification Log - {timestamp}\n") + f.write("=" * 80 + "\n\n") + f.write(result.stdout) + temp_path = f.name + + return send_file( + temp_path, + mimetype='text/plain', + as_attachment=True, + download_name=f'notification_{timestamp.replace(":", "_").replace(" ", "_")}.log' + ) + else: + return jsonify({'error': 'Failed to generate notification log'}), 500 + + except Exception as e: + print(f"Error downloading notification log: {e}") + return jsonify({'error': str(e)}), 500 + @app.route('/api/backups', methods=['GET']) def api_backups(): """Get list of all backup files from Proxmox storage"""