From acf501f0dea496be5b52fc787aed8cc7714874f9 Mon Sep 17 00:00:00 2001 From: kahenda Date: Mon, 6 Jul 2026 12:26:25 +0300 Subject: [PATCH] feat: implement interactive log viewer in dashboard --- app.go | 26 ++++++++++ frontend/src/App.jsx | 3 ++ frontend/src/LogViewer.jsx | 100 +++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 frontend/src/LogViewer.jsx diff --git a/app.go b/app.go index 9be3622..28508a6 100644 --- a/app.go +++ b/app.go @@ -1,6 +1,8 @@ package main import ( + "os" + "bufio" "context" "fmt" "math" @@ -254,3 +256,27 @@ func (a *App) GetLogs(limit int) (string, error) { return finalLogs, nil } + +// GetLogs reads the local cura.log file and returns the last 100 lines. +func (a *App) GetLogs() ([]string, error) { + file, err := os.Open("cura.log") + if err != nil { + if os.IsNotExist(err) { + return []string{"No logs recorded yet. Cura system active!"}, nil + } + return nil, err + } + defer file.Close() + + var logs []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + logs = append(logs, scanner.Text()) + } + + if len(logs) > 100 { + logs = logs[len(logs)-100:] + } + + return logs, scanner.Err() +} diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index a406f12..c1b7a58 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,3 +1,4 @@ +import LogViewer from "./LogViewer"; import React, { useState, useEffect } from 'react'; import './App.css'; @@ -149,6 +150,8 @@ function App() { )} + + ); } diff --git a/frontend/src/LogViewer.jsx b/frontend/src/LogViewer.jsx new file mode 100644 index 0000000..3d51b9b --- /dev/null +++ b/frontend/src/LogViewer.jsx @@ -0,0 +1,100 @@ +import React, { useState, useEffect } from 'react'; +import { GetLogs } from '../wailsjs/go/main/App'; + +export default function LogViewer() { + const [logs, setLogs] = useState([]); + const [loading, setLoading] = useState(true); + + const fetchLogs = () => { + GetLogs() + .then((data) => { + setLogs(data || ["No logs recorded yet. Cura system active!"]); + setLoading(false); + }) + .catch((err) => { + console.error("Failed to read logs:", err); + setLogs(["Error loading logs from system backend."]); + setLoading(false); + }); + }; + + useEffect(() => { + fetchLogs(); + const interval = setInterval(fetchLogs, 3000); + return () => clearInterval(interval); + }, []); + + return ( +
+
+ 🛡️ Cura System Events Log + +
+
+ {loading ? ( +

Streaming log buffer...

+ ) : ( + logs.map((log, index) => ( +
+ {index + 1} {log} +
+ )) + )} +
+
+ ); +} + +const styles = { + container: { + padding: '20px', + backgroundColor: '#1e1e1e', + borderRadius: '8px', + fontFamily: 'monospace', + color: '#d4d4d4', + margin: '20px 0', + }, + header: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: '15px', + }, + title: { + fontSize: '16px', + fontWeight: 'bold', + color: '#4fc1ff', + }, + button: { + padding: '5px 12px', + backgroundColor: '#0e639c', + color: '#fff', + border: 'none', + borderRadius: '4px', + cursor: 'pointer', + }, + console: { + backgroundColor: '#111', + padding: '15px', + borderRadius: '6px', + maxHeight: '300px', + overflowY: 'auto', + textAlign: 'left', + }, + logLine: { + fontSize: '13px', + lineHeight: '1.6', + whiteSpace: 'pre-wrap', + borderBottom: '1px solid #222', + padding: '4px 0', + }, + lineNumber: { + color: '#858585', + marginRight: '10px', + userSelect: 'none', + }, + loading: { + color: '#858585', + fontStyle: 'italic', + } +};