feat(tui): compact log sidebar with severity icons
Replace full viewLogsTab with compact sidebar renderer for the 70/30 monitors split. Single-char severity icons (▼▲◆●·), truncated messages, no header chrome. Renders directly from engine logs without viewport.
This commit is contained in:
@@ -107,23 +107,3 @@ func (m *Model) refreshLogContent() {
|
||||
m.logShown = shown
|
||||
m.logViewport.SetContent(strings.Join(rendered, "\n"))
|
||||
}
|
||||
|
||||
func (m Model) viewLogsTab() string {
|
||||
if m.logTotal == 0 {
|
||||
return m.emptyState("No log entries yet.", "Logs appear as monitors run checks")
|
||||
}
|
||||
|
||||
filterLabel := "All"
|
||||
if m.logFilterImportant {
|
||||
filterLabel = "Important"
|
||||
}
|
||||
|
||||
header := m.st.subtleStyle.Render(fmt.Sprintf(
|
||||
" %d entries Filter: %s", m.logShown, filterLabel))
|
||||
|
||||
if m.logFilterImportant && m.logShown < m.logTotal {
|
||||
header += m.st.subtleStyle.Render(fmt.Sprintf(" (%d hidden)", m.logTotal-m.logShown))
|
||||
}
|
||||
|
||||
return "\n" + header + "\n\n" + m.logViewport.View()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (m Model) renderCompactLogLine(line string, maxW int) string {
|
||||
sev := classifyLog(line)
|
||||
|
||||
var tag string
|
||||
switch sev {
|
||||
case severityDown:
|
||||
tag = m.st.dangerStyle.Render("▼")
|
||||
case severityUp:
|
||||
tag = m.st.specialStyle.Render("▲")
|
||||
case severityWarn:
|
||||
tag = m.st.warnStyle.Render("◆")
|
||||
case severitySystem:
|
||||
tag = m.st.titleStyle.Render("●")
|
||||
default:
|
||||
tag = m.st.subtleStyle.Render("·")
|
||||
}
|
||||
|
||||
ts := ""
|
||||
msg := line
|
||||
if len(line) > 10 && line[0] == '[' {
|
||||
if idx := strings.Index(line, "]"); idx > 0 && idx < 12 {
|
||||
ts = line[1:idx]
|
||||
msg = strings.TrimSpace(line[idx+1:])
|
||||
}
|
||||
}
|
||||
|
||||
msgW := maxW - 10
|
||||
if msgW < 10 {
|
||||
msgW = 10
|
||||
}
|
||||
msg = limitStr(msg, msgW)
|
||||
|
||||
if ts != "" {
|
||||
return fmt.Sprintf(" %s %s %s", m.st.subtleStyle.Render(ts), tag, msg)
|
||||
}
|
||||
return fmt.Sprintf(" %s %s", tag, msg)
|
||||
}
|
||||
|
||||
func (m Model) viewLogsSidebar(width int) string {
|
||||
logs := m.engine.GetLogs()
|
||||
if len(logs) == 0 {
|
||||
return m.st.subtleStyle.Render(" No logs yet")
|
||||
}
|
||||
|
||||
var lines []string
|
||||
for _, line := range logs {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
continue
|
||||
}
|
||||
if m.logFilterImportant && !isImportantLog(classifyLog(line)) {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, m.renderCompactLogLine(line, width))
|
||||
}
|
||||
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
@@ -158,7 +158,8 @@ func (m Model) viewDashboard() string {
|
||||
leftW := availW * 70 / 100
|
||||
rightW := availW - leftW
|
||||
left := lipgloss.NewStyle().Width(leftW).Render(monitors)
|
||||
right := lipgloss.NewStyle().Width(rightW).Render(m.viewLogsTab())
|
||||
sidebar := m.viewLogsSidebar(rightW)
|
||||
right := lipgloss.NewStyle().Width(rightW).Render(sidebar)
|
||||
content = lipgloss.JoinHorizontal(lipgloss.Top, left, right)
|
||||
} else {
|
||||
content = monitors
|
||||
|
||||
Reference in New Issue
Block a user