Compare commits
4 Commits
v0.1.0
...
47d3b0e68f
| Author | SHA1 | Date | |
|---|---|---|---|
|
47d3b0e68f
|
|||
|
8fd13fefbf
|
|||
|
974c4b61ea
|
|||
|
d50a5159d4
|
@@ -49,6 +49,7 @@ jobs:
|
||||
version: "~> v2"
|
||||
args: release --clean --release-notes=/tmp/release-notes.md
|
||||
env:
|
||||
GORELEASER_CURRENT_TAG: ${{ github.ref_name }}
|
||||
GORELEASER_FORCE_TOKEN: gitea
|
||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITEA_API_URL: http://gitea:3000/api/v1
|
||||
|
||||
+22
-10
@@ -17,6 +17,17 @@ func parseHex(hex string) (r, g, b uint8) {
|
||||
return
|
||||
}
|
||||
|
||||
func trueColorHex(c lipgloss.TerminalColor) string {
|
||||
switch v := c.(type) {
|
||||
case lipgloss.CompleteColor:
|
||||
return v.TrueColor
|
||||
case lipgloss.Color:
|
||||
return string(v)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func dimColor(hex string, brightness float64) lipgloss.Color {
|
||||
r, g, b := parseHex(hex)
|
||||
f := 0.3 + brightness*0.7
|
||||
@@ -27,35 +38,36 @@ func dimColor(hex string, brightness float64) lipgloss.Color {
|
||||
))
|
||||
}
|
||||
|
||||
func withBg(s lipgloss.Style, bg lipgloss.Color) lipgloss.Style {
|
||||
if bg != "" {
|
||||
func withBg(s lipgloss.Style, bg lipgloss.TerminalColor) lipgloss.Style {
|
||||
if bg != nil {
|
||||
return s.Background(bg)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (m Model) latencyStyle(ms int64, bg lipgloss.Color) lipgloss.Style {
|
||||
var hex string
|
||||
func (m Model) latencyStyle(ms int64, bg lipgloss.TerminalColor) lipgloss.Style {
|
||||
var base lipgloss.TerminalColor
|
||||
var t float64
|
||||
switch {
|
||||
case ms < 200:
|
||||
hex = m.st.sparkSuccess
|
||||
base = m.st.sparkSuccess
|
||||
t = float64(ms) / 200
|
||||
case ms < 500:
|
||||
hex = m.st.sparkWarning
|
||||
base = m.st.sparkWarning
|
||||
t = float64(ms-200) / 300
|
||||
default:
|
||||
hex = m.st.sparkDanger
|
||||
base = m.st.sparkDanger
|
||||
t = float64(ms-500) / 1500
|
||||
if t > 1 {
|
||||
t = 1
|
||||
}
|
||||
}
|
||||
hex := trueColorHex(base)
|
||||
s := lipgloss.NewStyle().Foreground(dimColor(hex, t))
|
||||
return withBg(s, bg)
|
||||
}
|
||||
|
||||
func (m Model) latencySparkline(latencies []time.Duration, statuses []bool, width int, bg lipgloss.Color) string {
|
||||
func (m Model) latencySparkline(latencies []time.Duration, statuses []bool, width int, bg lipgloss.TerminalColor) string {
|
||||
if len(latencies) == 0 {
|
||||
return withBg(m.st.subtleStyle, bg).Render(strings.Repeat("·", width))
|
||||
}
|
||||
@@ -103,7 +115,7 @@ func (m Model) latencySparkline(latencies []time.Duration, statuses []bool, widt
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (m Model) heartbeatSparkline(statuses []bool, width int, bg lipgloss.Color) string {
|
||||
func (m Model) heartbeatSparkline(statuses []bool, width int, bg lipgloss.TerminalColor) string {
|
||||
if len(statuses) == 0 {
|
||||
return withBg(m.st.subtleStyle, bg).Render(strings.Repeat("·", width))
|
||||
}
|
||||
@@ -143,7 +155,7 @@ func resolveSparklineIndex(x, sparkWidth, dataLen int) int {
|
||||
return offset + (x - padding)
|
||||
}
|
||||
|
||||
func (m Model) groupSparkline(groupID int, width int, bg lipgloss.Color) string {
|
||||
func (m Model) groupSparkline(groupID int, width int, bg lipgloss.TerminalColor) string {
|
||||
allSites := m.engine.GetAllSites()
|
||||
var childStatuses [][]bool
|
||||
for _, s := range allSites {
|
||||
|
||||
@@ -5,10 +5,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
func TestLatencySparkline_Empty(t *testing.T) {
|
||||
got := styledModel.latencySparkline(nil, nil, 10, "")
|
||||
got := styledModel.latencySparkline(nil, nil, 10, nil)
|
||||
if !strings.Contains(got, "··········") {
|
||||
t.Errorf("empty sparkline should be dots, got %q", got)
|
||||
}
|
||||
@@ -17,7 +19,7 @@ func TestLatencySparkline_Empty(t *testing.T) {
|
||||
func TestLatencySparkline_SingleValue(t *testing.T) {
|
||||
latencies := []time.Duration{100 * time.Millisecond}
|
||||
statuses := []bool{true}
|
||||
got := styledModel.latencySparkline(latencies, statuses, 5, "")
|
||||
got := styledModel.latencySparkline(latencies, statuses, 5, nil)
|
||||
if len(got) == 0 {
|
||||
t.Error("sparkline should not be empty")
|
||||
}
|
||||
@@ -33,7 +35,7 @@ func TestLatencySparkline_WidthTruncation(t *testing.T) {
|
||||
latencies[i] = time.Duration(i*50) * time.Millisecond
|
||||
statuses[i] = true
|
||||
}
|
||||
got := styledModel.latencySparkline(latencies, statuses, 5, "")
|
||||
got := styledModel.latencySparkline(latencies, statuses, 5, nil)
|
||||
if len(got) == 0 {
|
||||
t.Error("sparkline should not be empty")
|
||||
}
|
||||
@@ -45,7 +47,7 @@ func TestLatencySparkline_WidthTruncation(t *testing.T) {
|
||||
func TestLatencySparkline_RelativeHeight(t *testing.T) {
|
||||
latencies := []time.Duration{10 * time.Millisecond, 50 * time.Millisecond, 10 * time.Millisecond}
|
||||
statuses := []bool{true, true, true}
|
||||
out := stripANSI(styledModel.latencySparkline(latencies, statuses, 3, ""))
|
||||
out := stripANSI(styledModel.latencySparkline(latencies, statuses, 3, nil))
|
||||
runes := []rune(out)
|
||||
if len(runes) < 3 {
|
||||
t.Fatalf("expected 3 runes, got %d", len(runes))
|
||||
@@ -57,14 +59,14 @@ func TestLatencySparkline_RelativeHeight(t *testing.T) {
|
||||
|
||||
func TestLatencyStyle_BandsProduceDifferentColors(t *testing.T) {
|
||||
st := newStyles(themeFlexokiDark)
|
||||
st.sparkSuccess = "#00ff00"
|
||||
st.sparkWarning = "#ffff00"
|
||||
st.sparkDanger = "#ff0000"
|
||||
st.sparkSuccess = lipgloss.Color("#00ff00")
|
||||
st.sparkWarning = lipgloss.Color("#ffff00")
|
||||
st.sparkDanger = lipgloss.Color("#ff0000")
|
||||
m := Model{st: st}
|
||||
|
||||
green := m.latencyStyle(50, "")
|
||||
yellow := m.latencyStyle(300, "")
|
||||
red := m.latencyStyle(800, "")
|
||||
green := m.latencyStyle(50, nil)
|
||||
yellow := m.latencyStyle(300, nil)
|
||||
red := m.latencyStyle(800, nil)
|
||||
|
||||
gfg := green.GetForeground()
|
||||
yfg := yellow.GetForeground()
|
||||
@@ -77,11 +79,11 @@ func TestLatencyStyle_BandsProduceDifferentColors(t *testing.T) {
|
||||
|
||||
func TestLatencyStyle_BrightnessVariesWithinBand(t *testing.T) {
|
||||
st := newStyles(themeFlexokiDark)
|
||||
st.sparkSuccess = "#00ff00"
|
||||
st.sparkSuccess = lipgloss.Color("#00ff00")
|
||||
m := Model{st: st}
|
||||
|
||||
dim := m.latencyStyle(10, "")
|
||||
bright := m.latencyStyle(190, "")
|
||||
dim := m.latencyStyle(10, nil)
|
||||
bright := m.latencyStyle(190, nil)
|
||||
|
||||
if dim.GetForeground() == bright.GetForeground() {
|
||||
t.Error("10ms and 190ms should have different brightness within green band")
|
||||
@@ -91,7 +93,7 @@ func TestLatencyStyle_BrightnessVariesWithinBand(t *testing.T) {
|
||||
func TestLatencySparkline_OutputWidth(t *testing.T) {
|
||||
latencies := []time.Duration{100 * time.Millisecond, 200 * time.Millisecond, 300 * time.Millisecond}
|
||||
statuses := []bool{true, true, true}
|
||||
got := styledModel.latencySparkline(latencies, statuses, 5, "")
|
||||
got := styledModel.latencySparkline(latencies, statuses, 5, nil)
|
||||
count := utf8.RuneCountInString(stripANSI(got))
|
||||
if count != 5 {
|
||||
t.Errorf("expected 5 rune-width output, got %d from %q", count, got)
|
||||
@@ -116,7 +118,7 @@ func stripANSI(s string) string {
|
||||
}
|
||||
|
||||
func TestHeartbeatSparkline_Empty(t *testing.T) {
|
||||
got := styledModel.heartbeatSparkline(nil, 10, "")
|
||||
got := styledModel.heartbeatSparkline(nil, 10, nil)
|
||||
if !strings.Contains(got, "··········") {
|
||||
t.Errorf("empty heartbeat should be dots, got %q", got)
|
||||
}
|
||||
@@ -124,7 +126,7 @@ func TestHeartbeatSparkline_Empty(t *testing.T) {
|
||||
|
||||
func TestHeartbeatSparkline_Mixed(t *testing.T) {
|
||||
statuses := []bool{true, false, true, true, false}
|
||||
got := styledModel.heartbeatSparkline(statuses, 5, "")
|
||||
got := styledModel.heartbeatSparkline(statuses, 5, nil)
|
||||
if len(got) == 0 {
|
||||
t.Error("heartbeat sparkline should not be empty")
|
||||
}
|
||||
@@ -132,7 +134,7 @@ func TestHeartbeatSparkline_Mixed(t *testing.T) {
|
||||
|
||||
func TestHeartbeatSparkline_PaddedWidth(t *testing.T) {
|
||||
statuses := []bool{true, true}
|
||||
got := styledModel.heartbeatSparkline(statuses, 5, "")
|
||||
got := styledModel.heartbeatSparkline(statuses, 5, nil)
|
||||
if !strings.Contains(got, "···") {
|
||||
t.Errorf("should have dot padding for width > data, got %q", got)
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func (m Model) viewSitesTab() string {
|
||||
for i := start; i < end; i++ {
|
||||
site := m.sites[i]
|
||||
rowIdx := i - start
|
||||
var rowBg lipgloss.Color
|
||||
var rowBg lipgloss.TerminalColor
|
||||
if i == m.cursor {
|
||||
rowBg = m.theme.SelectedBg
|
||||
} else if rowIdx%2 == 1 {
|
||||
|
||||
+110
-102
@@ -5,35 +5,43 @@ import (
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
func cc(hex, ansi string) lipgloss.CompleteColor {
|
||||
return lipgloss.CompleteColor{
|
||||
TrueColor: hex,
|
||||
ANSI256: hex,
|
||||
ANSI: ansi,
|
||||
}
|
||||
}
|
||||
|
||||
type Theme struct {
|
||||
Name string
|
||||
|
||||
// Base layers
|
||||
Bg lipgloss.Color
|
||||
Surface lipgloss.Color
|
||||
Panel lipgloss.Color
|
||||
Border lipgloss.Color
|
||||
Bg lipgloss.TerminalColor
|
||||
Surface lipgloss.TerminalColor
|
||||
Panel lipgloss.TerminalColor
|
||||
Border lipgloss.TerminalColor
|
||||
|
||||
// Text
|
||||
Fg lipgloss.Color
|
||||
Muted lipgloss.Color
|
||||
Subtle lipgloss.Color
|
||||
Fg lipgloss.TerminalColor
|
||||
Muted lipgloss.TerminalColor
|
||||
Subtle lipgloss.TerminalColor
|
||||
|
||||
// Semantic
|
||||
Success lipgloss.Color
|
||||
Warning lipgloss.Color
|
||||
Stale lipgloss.Color
|
||||
Danger lipgloss.Color
|
||||
Info lipgloss.Color
|
||||
Accent lipgloss.Color
|
||||
Purple lipgloss.Color
|
||||
Success lipgloss.TerminalColor
|
||||
Warning lipgloss.TerminalColor
|
||||
Stale lipgloss.TerminalColor
|
||||
Danger lipgloss.TerminalColor
|
||||
Info lipgloss.TerminalColor
|
||||
Accent lipgloss.TerminalColor
|
||||
Purple lipgloss.TerminalColor
|
||||
|
||||
// Table
|
||||
ZebraBg lipgloss.Color
|
||||
ZebraBg lipgloss.TerminalColor
|
||||
|
||||
// Selection
|
||||
SelectedFg lipgloss.Color
|
||||
SelectedBg lipgloss.Color
|
||||
SelectedFg lipgloss.TerminalColor
|
||||
SelectedBg lipgloss.TerminalColor
|
||||
}
|
||||
|
||||
var themes = []Theme{
|
||||
@@ -46,107 +54,107 @@ var themes = []Theme{
|
||||
|
||||
var themeFlexokiDark = Theme{
|
||||
Name: "Flexoki Dark",
|
||||
Bg: "#1C1B1A",
|
||||
Surface: "#282726",
|
||||
Panel: "#343331",
|
||||
Border: "#575653",
|
||||
Fg: "#CECDC3",
|
||||
Muted: "#878580",
|
||||
Subtle: "#6F6E69",
|
||||
Success: "#879A39",
|
||||
Warning: "#D0A215",
|
||||
Stale: "#DA702C",
|
||||
Danger: "#D14D41",
|
||||
Info: "#4385BE",
|
||||
Accent: "#3AA99F",
|
||||
Purple: "#8B7EC8",
|
||||
ZebraBg: "#222120",
|
||||
SelectedFg: "#FFFCF0",
|
||||
SelectedBg: "#403E3C",
|
||||
Bg: cc("#1C1B1A", ""),
|
||||
Surface: cc("#282726", ""),
|
||||
Panel: cc("#343331", ""),
|
||||
Border: cc("#575653", "8"),
|
||||
Fg: cc("#CECDC3", "15"),
|
||||
Muted: cc("#878580", "7"),
|
||||
Subtle: cc("#6F6E69", "7"),
|
||||
Success: cc("#879A39", "10"),
|
||||
Warning: cc("#D0A215", "11"),
|
||||
Stale: cc("#DA702C", "3"),
|
||||
Danger: cc("#D14D41", "9"),
|
||||
Info: cc("#4385BE", "12"),
|
||||
Accent: cc("#3AA99F", "14"),
|
||||
Purple: cc("#8B7EC8", "13"),
|
||||
ZebraBg: cc("#222120", ""),
|
||||
SelectedFg: cc("#FFFCF0", "15"),
|
||||
SelectedBg: cc("#403E3C", "4"),
|
||||
}
|
||||
|
||||
var themeTokyoNight = Theme{
|
||||
Name: "Tokyo Night",
|
||||
Bg: "#1a1b26",
|
||||
Surface: "#24283b",
|
||||
Panel: "#292e42",
|
||||
Border: "#3b4261",
|
||||
Fg: "#c0caf5",
|
||||
Muted: "#a9b1d6",
|
||||
Subtle: "#565f89",
|
||||
Success: "#9ece6a",
|
||||
Warning: "#e0af68",
|
||||
Stale: "#ff9e64",
|
||||
Danger: "#f7768e",
|
||||
Info: "#7aa2f7",
|
||||
Accent: "#7dcfff",
|
||||
Purple: "#bb9af7",
|
||||
ZebraBg: "#1c1d28",
|
||||
SelectedFg: "#c0caf5",
|
||||
SelectedBg: "#292e42",
|
||||
Bg: cc("#1a1b26", ""),
|
||||
Surface: cc("#24283b", ""),
|
||||
Panel: cc("#292e42", ""),
|
||||
Border: cc("#3b4261", "8"),
|
||||
Fg: cc("#c0caf5", "15"),
|
||||
Muted: cc("#a9b1d6", "7"),
|
||||
Subtle: cc("#565f89", "7"),
|
||||
Success: cc("#9ece6a", "10"),
|
||||
Warning: cc("#e0af68", "11"),
|
||||
Stale: cc("#ff9e64", "3"),
|
||||
Danger: cc("#f7768e", "9"),
|
||||
Info: cc("#7aa2f7", "12"),
|
||||
Accent: cc("#7dcfff", "14"),
|
||||
Purple: cc("#bb9af7", "13"),
|
||||
ZebraBg: cc("#1c1d28", ""),
|
||||
SelectedFg: cc("#c0caf5", "15"),
|
||||
SelectedBg: cc("#292e42", "4"),
|
||||
}
|
||||
|
||||
var themeGruvbox = Theme{
|
||||
Name: "Gruvbox",
|
||||
Bg: "#282828",
|
||||
Surface: "#3c3836",
|
||||
Panel: "#504945",
|
||||
Border: "#665c54",
|
||||
Fg: "#ebdbb2",
|
||||
Muted: "#bdae93",
|
||||
Subtle: "#7c6f64",
|
||||
Success: "#b8bb26",
|
||||
Warning: "#fabd2f",
|
||||
Stale: "#fe8019",
|
||||
Danger: "#fb4934",
|
||||
Info: "#83a598",
|
||||
Accent: "#8ec07c",
|
||||
Purple: "#d3869b",
|
||||
ZebraBg: "#2a2a2a",
|
||||
SelectedFg: "#fbf1c7",
|
||||
SelectedBg: "#504945",
|
||||
Bg: cc("#282828", ""),
|
||||
Surface: cc("#3c3836", ""),
|
||||
Panel: cc("#504945", ""),
|
||||
Border: cc("#665c54", "8"),
|
||||
Fg: cc("#ebdbb2", "15"),
|
||||
Muted: cc("#bdae93", "7"),
|
||||
Subtle: cc("#7c6f64", "7"),
|
||||
Success: cc("#b8bb26", "10"),
|
||||
Warning: cc("#fabd2f", "11"),
|
||||
Stale: cc("#fe8019", "3"),
|
||||
Danger: cc("#fb4934", "9"),
|
||||
Info: cc("#83a598", "12"),
|
||||
Accent: cc("#8ec07c", "14"),
|
||||
Purple: cc("#d3869b", "13"),
|
||||
ZebraBg: cc("#2a2a2a", ""),
|
||||
SelectedFg: cc("#fbf1c7", "15"),
|
||||
SelectedBg: cc("#504945", "4"),
|
||||
}
|
||||
|
||||
var themeCatppuccinMocha = Theme{
|
||||
Name: "Catppuccin Mocha",
|
||||
Bg: "#1e1e2e",
|
||||
Surface: "#313244",
|
||||
Panel: "#45475a",
|
||||
Border: "#585b70",
|
||||
Fg: "#cdd6f4",
|
||||
Muted: "#a6adc8",
|
||||
Subtle: "#6c7086",
|
||||
Success: "#a6e3a1",
|
||||
Warning: "#f9e2af",
|
||||
Stale: "#fab387",
|
||||
Danger: "#f38ba8",
|
||||
Info: "#89b4fa",
|
||||
Accent: "#94e2d5",
|
||||
Purple: "#cba6f7",
|
||||
ZebraBg: "#232334",
|
||||
SelectedFg: "#cdd6f4",
|
||||
SelectedBg: "#45475a",
|
||||
Bg: cc("#1e1e2e", ""),
|
||||
Surface: cc("#313244", ""),
|
||||
Panel: cc("#45475a", ""),
|
||||
Border: cc("#585b70", "8"),
|
||||
Fg: cc("#cdd6f4", "15"),
|
||||
Muted: cc("#a6adc8", "7"),
|
||||
Subtle: cc("#6c7086", "7"),
|
||||
Success: cc("#a6e3a1", "10"),
|
||||
Warning: cc("#f9e2af", "11"),
|
||||
Stale: cc("#fab387", "3"),
|
||||
Danger: cc("#f38ba8", "9"),
|
||||
Info: cc("#89b4fa", "12"),
|
||||
Accent: cc("#94e2d5", "14"),
|
||||
Purple: cc("#cba6f7", "13"),
|
||||
ZebraBg: cc("#232334", ""),
|
||||
SelectedFg: cc("#cdd6f4", "15"),
|
||||
SelectedBg: cc("#45475a", "4"),
|
||||
}
|
||||
|
||||
var themeNord = Theme{
|
||||
Name: "Nord",
|
||||
Bg: "#2e3440",
|
||||
Surface: "#3b4252",
|
||||
Panel: "#434c5e",
|
||||
Border: "#4c566a",
|
||||
Fg: "#d8dee9",
|
||||
Muted: "#d8dee9",
|
||||
Subtle: "#4c566a",
|
||||
Success: "#a3be8c",
|
||||
Warning: "#ebcb8b",
|
||||
Stale: "#d08770",
|
||||
Danger: "#bf616a",
|
||||
Info: "#81a1c1",
|
||||
Accent: "#88c0d0",
|
||||
Purple: "#b48ead",
|
||||
ZebraBg: "#323845",
|
||||
SelectedFg: "#eceff4",
|
||||
SelectedBg: "#434c5e",
|
||||
Bg: cc("#2e3440", ""),
|
||||
Surface: cc("#3b4252", ""),
|
||||
Panel: cc("#434c5e", ""),
|
||||
Border: cc("#4c566a", "8"),
|
||||
Fg: cc("#d8dee9", "15"),
|
||||
Muted: cc("#d8dee9", "7"),
|
||||
Subtle: cc("#4c566a", "7"),
|
||||
Success: cc("#a3be8c", "10"),
|
||||
Warning: cc("#ebcb8b", "11"),
|
||||
Stale: cc("#d08770", "3"),
|
||||
Danger: cc("#bf616a", "9"),
|
||||
Info: cc("#81a1c1", "12"),
|
||||
Accent: cc("#88c0d0", "14"),
|
||||
Purple: cc("#b48ead", "13"),
|
||||
ZebraBg: cc("#323845", ""),
|
||||
SelectedFg: cc("#eceff4", "15"),
|
||||
SelectedBg: cc("#434c5e", "4"),
|
||||
}
|
||||
|
||||
func (t Theme) HuhTheme() *huh.Theme {
|
||||
|
||||
+12
-12
@@ -30,9 +30,9 @@ type styles struct {
|
||||
activeTab lipgloss.Style
|
||||
inactiveTab lipgloss.Style
|
||||
|
||||
sparkSuccess string
|
||||
sparkWarning string
|
||||
sparkDanger string
|
||||
sparkSuccess lipgloss.TerminalColor
|
||||
sparkWarning lipgloss.TerminalColor
|
||||
sparkDanger lipgloss.TerminalColor
|
||||
|
||||
tableHeaderStyle lipgloss.Style
|
||||
tableCellStyle lipgloss.Style
|
||||
@@ -46,23 +46,23 @@ type styles struct {
|
||||
|
||||
func newStyles(t Theme) *styles {
|
||||
return &styles{
|
||||
subtleStyle: lipgloss.NewStyle().Foreground(t.Subtle),
|
||||
subtleStyle: lipgloss.NewStyle().Foreground(t.Subtle).Faint(true),
|
||||
specialStyle: lipgloss.NewStyle().Foreground(t.Success),
|
||||
warnStyle: lipgloss.NewStyle().Foreground(t.Warning),
|
||||
staleStyle: lipgloss.NewStyle().Foreground(t.Stale),
|
||||
dangerStyle: lipgloss.NewStyle().Foreground(t.Danger),
|
||||
warnStyle: lipgloss.NewStyle().Foreground(t.Warning).Bold(true),
|
||||
staleStyle: lipgloss.NewStyle().Foreground(t.Stale).Faint(true),
|
||||
dangerStyle: lipgloss.NewStyle().Foreground(t.Danger).Bold(true),
|
||||
titleStyle: lipgloss.NewStyle().Foreground(t.Accent).Bold(true),
|
||||
activeTab: lipgloss.NewStyle().Background(t.Surface).Foreground(t.Accent).Bold(true).Padding(0, 1),
|
||||
inactiveTab: lipgloss.NewStyle().Padding(0, 1).Foreground(t.Muted),
|
||||
inactiveTab: lipgloss.NewStyle().Padding(0, 1).Foreground(t.Muted).Faint(true),
|
||||
|
||||
sparkSuccess: string(t.Success),
|
||||
sparkWarning: string(t.Warning),
|
||||
sparkDanger: string(t.Danger),
|
||||
sparkSuccess: t.Success,
|
||||
sparkWarning: t.Warning,
|
||||
sparkDanger: t.Danger,
|
||||
|
||||
tableHeaderStyle: lipgloss.NewStyle().Foreground(t.Accent).Bold(true).Padding(0, 1),
|
||||
tableCellStyle: lipgloss.NewStyle().Padding(0, 1),
|
||||
tableSelectedStyle: lipgloss.NewStyle().Padding(0, 1).Bold(true).Foreground(t.SelectedFg).Background(t.SelectedBg),
|
||||
tableBorderStyle: lipgloss.NewStyle().Foreground(t.Border),
|
||||
tableBorderStyle: lipgloss.NewStyle().Foreground(t.Border).Faint(true),
|
||||
tableZebraStyle: lipgloss.NewStyle().Padding(0, 1).Background(t.ZebraBg),
|
||||
|
||||
siteGroupStyle: lipgloss.NewStyle().Padding(0, 1).Bold(true).Foreground(t.Accent),
|
||||
|
||||
@@ -215,7 +215,7 @@ func (m Model) viewDetailPanel() string {
|
||||
|
||||
b.WriteString(m.divider() + "\n")
|
||||
if site.Type == "push" {
|
||||
b.WriteString(" " + m.zones.Mark("spark-heartbeat", m.heartbeatSparkline(hist.Statuses, detailSparkWidth, "")))
|
||||
b.WriteString(" " + m.zones.Mark("spark-heartbeat", m.heartbeatSparkline(hist.Statuses, detailSparkWidth, nil)))
|
||||
if len(hist.Statuses) > 0 {
|
||||
up := 0
|
||||
for _, s := range hist.Statuses {
|
||||
@@ -228,7 +228,7 @@ func (m Model) viewDetailPanel() string {
|
||||
up, len(hist.Statuses))
|
||||
}
|
||||
} else {
|
||||
b.WriteString(" " + m.zones.Mark("spark-latency", m.latencySparkline(hist.Latencies, hist.Statuses, detailSparkWidth, "")))
|
||||
b.WriteString(" " + m.zones.Mark("spark-latency", m.latencySparkline(hist.Latencies, hist.Statuses, detailSparkWidth, nil)))
|
||||
var minL, maxL, total time.Duration
|
||||
count := 0
|
||||
for i, l := range hist.Latencies {
|
||||
|
||||
Reference in New Issue
Block a user