2
0
mirror of https://github.com/hibiken/asynq.git synced 2025-10-03 05:12:01 +08:00

(cli): Add modal

This commit is contained in:
Ken Hibino
2022-05-22 20:33:50 -07:00
parent 34926d3f69
commit 7757de4173
4 changed files with 112 additions and 0 deletions

View File

@@ -40,6 +40,7 @@ type State struct {
selectedQueue *asynq.QueueInfo // queue shown on queue details view
selectedGroup *asynq.GroupInfo
selectedTask *asynq.TaskInfo
pageNum int // pagination page number

View File

@@ -49,6 +49,7 @@ func (dd *dashDrawer) draw(state *State) {
drawTaskStateBreakdown(d, baseStyle, state)
d.NL()
drawTaskTable(d, state)
drawTaskModal(d, state)
case viewTypeServers:
d.Println("=== Servers ===", baseStyle.Bold(true))
d.NL()
@@ -439,3 +440,74 @@ func drawTaskStateBreakdown(d *ScreenDrawer, style tcell.Style, state *State) {
}
d.NL()
}
func drawTaskModal(d *ScreenDrawer, state *State) {
contents := []*rowContent{
{" === Task Summary ===", baseStyle.Bold(true)},
{"", baseStyle},
{" ID: xxxxx", baseStyle},
{" Type: xxxxx", baseStyle},
{" State: xxxx", baseStyle},
}
withModal(d, contents)
}
type rowContent struct {
s string // should not include newline
style tcell.Style
}
func withModal(d *ScreenDrawer, contents []*rowContent) {
modalStyle := baseStyle //.Background(tcell.ColorDarkMagenta)
w, h := d.Screen().Size()
var (
modalWidth = int(math.Floor(float64(w) * 0.6))
modalHeight = int(math.Floor(float64(h) * 0.6))
rowOffset = int(math.Floor(float64(h) * 0.2)) // 20% from the top
colOffset = int(math.Floor(float64(w) * 0.2)) // 20% from the left
)
if modalHeight < 3 {
return // no content can be shown
}
d.Goto(colOffset, rowOffset)
d.Print(string(tcell.RuneULCorner), modalStyle)
d.Print(strings.Repeat(string(tcell.RuneHLine), modalWidth-2), modalStyle)
d.Print(string(tcell.RuneURCorner), modalStyle)
d.NL()
for i := 1; i < modalHeight-1; i++ {
d.Goto(colOffset, rowOffset+i)
d.Print(string(tcell.RuneVLine), modalStyle)
cnt := &rowContent{strings.Repeat(" ", modalWidth-2), baseStyle}
if i <= len(contents) {
cnt = contents[i-1]
cnt.s = adjustWidth(cnt.s, modalWidth-2)
}
d.Print(truncate(cnt.s, modalWidth-2), cnt.style)
d.Print(string(tcell.RuneVLine), modalStyle)
d.NL()
}
d.Goto(colOffset, rowOffset+modalHeight-1)
d.Print(string(tcell.RuneLLCorner), modalStyle)
d.Print(strings.Repeat(string(tcell.RuneHLine), modalWidth-2), modalStyle)
d.Print(string(tcell.RuneLRCorner), modalStyle)
d.NL()
}
func adjustWidth(s string, width int) string {
sw := runewidth.StringWidth(s)
if sw > width {
return truncate(s, width)
}
var b strings.Builder
b.WriteString(s)
b.WriteString(strings.Repeat(" ", width-sw))
return b.String()
}
// truncates s if s exceeds max length.
func truncate(s string, max int) string {
if runewidth.StringWidth(s) <= max {
return s
}
return string([]rune(s)[:max-1]) + "…"
}

View File

@@ -0,0 +1,33 @@
// Copyright 2022 Kentaro Hibino. All rights reserved.
// Use of this source code is governed by a MIT license
// that can be found in the LICENSE file.
package dash
import "testing"
func TestTruncate(t *testing.T) {
tests := []struct {
s string
max int
want string
}{
{
s: "hello world!",
max: 15,
want: "hello world!",
},
{
s: "hello world!",
max: 6,
want: "hello…",
},
}
for _, tc := range tests {
got := truncate(tc.s, tc.max)
if tc.want != got {
t.Errorf("truncate(%q, %d) = %q, want %q", tc.s, tc.max, got, tc.want)
}
}
}

View File

@@ -57,6 +57,12 @@ func (d *ScreenDrawer) Screen() tcell.Screen {
return d.l.s
}
// Goto moves the screendrawer to the specified cell.
func (d *ScreenDrawer) Goto(x, y int) {
d.l.row = y
d.l.col = x
}
// Go to the bottom of the screen.
func (d *ScreenDrawer) GoToBottom() {
_, h := d.Screen().Size()