Dialog boxes use dialog style (#2150)

mine
Alexandru Placinta 2025-01-12 18:27:49 +02:00 committed by GitHub
parent b3bd60b67f
commit 4642077975
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 134 additions and 207 deletions

View File

@ -68,13 +68,14 @@ func ShowConfirmAck(app *ui.App, pages *ui.Pages, acceptStr string, override boo
// ShowConfirm pops a confirmation dialog.
func ShowConfirm(styles config.Dialog, pages *ui.Pages, title, msg string, ack confirmFunc, cancel cancelFunc) {
f := tview.NewForm()
f.SetItemPadding(0)
f.SetButtonsAlign(tview.AlignCenter).
f := tview.NewForm().
SetItemPadding(0).
SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetButtonTextColor(styles.ButtonFgColor.Color()).
SetLabelColor(styles.LabelFgColor.Color()).
SetFieldTextColor(styles.FieldFgColor.Color())
SetFieldTextColor(styles.FieldFgColor.Color()).
SetFieldBackgroundColor(styles.BgColor.Color())
f.AddButton("Cancel", func() {
dismiss(pages)
cancel()

View File

@ -48,8 +48,7 @@ func (c *Context) renameCmd(evt *tcell.EventKey) *tcell.EventKey {
return evt
}
app := c.App()
c.showRenameModal(app, contextName, c.renameDialogCallback)
c.showRenameModal(contextName, c.renameDialogCallback)
return nil
}
@ -65,39 +64,42 @@ func (c *Context) renameDialogCallback(form *tview.Form, contextName string) err
return nil
}
func (c *Context) showRenameModal(a *App, name string, ok func(form *tview.Form, contextName string) error) {
p := a.Content.Pages
f := c.makeStyledForm()
func (c *Context) showRenameModal(name string, ok func(form *tview.Form, contextName string) error) {
app := c.App()
styles := app.Styles.Dialog()
f := tview.NewForm().
SetItemPadding(0).
SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetButtonTextColor(styles.ButtonFgColor.Color()).
SetLabelColor(styles.LabelFgColor.Color()).
SetFieldTextColor(styles.FieldFgColor.Color())
f.AddInputField(inputField, name, 0, nil, nil).
AddButton("OK", func() {
if err := ok(f, name); err != nil {
c.App().Flash().Err(err)
app.Flash().Err(err)
return
}
p.RemovePage(renamePage)
app.Content.Pages.RemovePage(renamePage)
}).
AddButton("Cancel", func() {
p.RemovePage(renamePage)
app.Content.Pages.RemovePage(renamePage)
})
m := tview.NewModalForm("<Rename>", f)
m.SetText(fmt.Sprintf("Rename context %q?", name))
m.SetDoneFunc(func(int, string) {
p.RemovePage(renamePage)
app.Content.Pages.RemovePage(renamePage)
})
p.AddPage(renamePage, m, false, false)
p.ShowPage(renamePage)
}
app.Content.Pages.AddPage(renamePage, m, false, false)
app.Content.Pages.ShowPage(renamePage)
func (c *Context) makeStyledForm() *tview.Form {
f := tview.NewForm()
f.SetItemPadding(0)
f.SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
SetButtonTextColor(tview.Styles.PrimaryTextColor).
SetLabelColor(tcell.ColorAqua).
SetFieldTextColor(tcell.ColorOrange)
return f
for i := 0; i < f.GetButtonCount(); i++ {
f.GetButton(i).
SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color()).
SetLabelColorActivated(styles.ButtonFocusFgColor.Color())
}
}
func (c *Context) useCtx(app *App, model ui.Tabular, gvr client.GVR, path string) {

View File

@ -111,90 +111,54 @@ func (c *CronJob) triggerCmd(evt *tcell.EventKey) *tcell.EventKey {
}
func (c *CronJob) toggleSuspendCmd(evt *tcell.EventKey) *tcell.EventKey {
sel := c.GetTable().GetSelectedItem()
table := c.GetTable()
sel := table.GetSelectedItem()
if sel == "" {
return evt
}
cell := table.GetCell(c.GetTable().GetSelectedRowIndex(), c.GetTable().NameColIndex()+2)
if cell == nil {
c.App().Flash().Errf("Unable to assert current status")
return nil
}
c.Stop()
defer c.Start()
c.showSuspendDialog(sel)
c.showSuspendDialog(cell, sel)
return nil
}
func (c *CronJob) showSuspendDialog(sel string) {
cell := c.GetTable().GetCell(c.GetTable().GetSelectedRowIndex(), c.GetTable().NameColIndex()+2)
if cell == nil {
c.App().Flash().Errf("Unable to assert current status")
return
}
suspended := strings.TrimSpace(cell.Text) == defaultSuspendStatus
func (c *CronJob) showSuspendDialog(cell *tview.TableCell, sel string) {
title := "Suspend"
if suspended {
if strings.TrimSpace(cell.Text) == defaultSuspendStatus {
title = "Resume"
}
confirm := tview.NewModalForm(fmt.Sprintf("<%s>", title), c.makeSuspendForm(sel, !suspended))
confirm.SetText(fmt.Sprintf("%s CronJob %s?", title, sel))
confirm.SetDoneFunc(func(int, string) {
c.dismissDialog()
})
c.App().Content.AddPage(suspendDialogKey, confirm, false, false)
c.App().Content.ShowPage(suspendDialogKey)
}
func (c *CronJob) makeSuspendForm(sel string, suspend bool) *tview.Form {
f := c.makeStyledForm()
action := "suspended"
if !suspend {
action = "resumed"
}
f.AddButton("Cancel", func() {
c.dismissDialog()
})
f.AddButton("OK", func() {
defer c.dismissDialog()
dialog.ShowConfirm(c.App().Styles.Dialog(), c.App().Content.Pages, title, sel, func() {
ctx, cancel := context.WithTimeout(context.Background(), c.App().Conn().Config().CallTimeout())
defer cancel()
if err := c.toggleSuspend(ctx, sel); err != nil {
log.Error().Err(err).Msgf("CronJob %s %s failed", sel, action)
c.App().Flash().Err(err)
} else {
c.App().Flash().Infof("CronJob %s %s successfully!", sel, action)
res, err := dao.AccessorFor(c.App().factory, c.GVR())
if err != nil {
c.App().Flash().Err(fmt.Errorf("no accessor for %q", c.GVR()))
return
}
})
return f
}
func (c *CronJob) toggleSuspend(ctx context.Context, path string) error {
res, err := dao.AccessorFor(c.App().factory, c.GVR())
if err != nil {
return err
}
cronJob, ok := res.(*dao.CronJob)
if !ok {
return fmt.Errorf("expecting a scalable resource for %q", c.GVR())
}
return cronJob.ToggleSuspend(ctx, path)
}
func (c *CronJob) makeStyledForm() *tview.Form {
f := tview.NewForm()
f.SetItemPadding(0)
f.SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
SetButtonTextColor(tview.Styles.PrimaryTextColor).
SetLabelColor(tcell.ColorAqua).
SetFieldTextColor(tcell.ColorOrange)
return f
}
func (c *CronJob) dismissDialog() {
c.App().Content.RemovePage(suspendDialogKey)
cronJob, ok := res.(*dao.CronJob)
if !ok {
c.App().Flash().Errf("expecting a cron job for %q", c.GVR())
return
}
if err := cronJob.ToggleSuspend(ctx, sel); err != nil {
c.App().Flash().Errf("Cronjob %s failed for %v", strings.ToLower(title), err)
return
}
}, func() {})
}

View File

@ -20,15 +20,16 @@ type DrainFunc func(v ResourceViewer, sels []string, opts dao.DrainOptions)
// ShowDrain pops a node drain dialog.
func ShowDrain(view ResourceViewer, sels []string, opts dao.DrainOptions, okFn DrainFunc) {
styles := view.App().Styles
styles := view.App().Styles.Dialog()
f := tview.NewForm()
f.SetItemPadding(0)
f.SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.BgColor()).
SetButtonTextColor(styles.FgColor()).
SetLabelColor(styles.K9s.Info.FgColor.Color()).
SetFieldTextColor(styles.K9s.Info.SectionColor.Color())
f := tview.NewForm().
SetItemPadding(0).
SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetButtonTextColor(styles.ButtonFgColor.Color()).
SetLabelColor(styles.LabelFgColor.Color()).
SetFieldTextColor(styles.FieldFgColor.Color()).
SetFieldBackgroundColor(styles.BgColor.Color())
f.AddInputField("GracePeriod:", strconv.Itoa(opts.GracePeriodSeconds), 0, nil, func(v string) {
a, err := asIntOpt(v)

View File

@ -95,11 +95,11 @@ func (s *ImageExtender) showImageDialog(path string) error {
}
func (s *ImageExtender) makeSetImageForm(sel string) (*tview.Form, error) {
f := s.makeStyledForm()
podSpec, err := s.getPodSpec(sel)
if err != nil {
return nil, err
}
formContainerLines := make([]*imageFormSpec, 0, len(podSpec.InitContainers)+len(podSpec.Containers))
for _, spec := range podSpec.InitContainers {
formContainerLines = append(formContainerLines, &imageFormSpec{init: true, name: spec.Name, dockerImage: spec.Image})
@ -107,6 +107,36 @@ func (s *ImageExtender) makeSetImageForm(sel string) (*tview.Form, error) {
for _, spec := range podSpec.Containers {
formContainerLines = append(formContainerLines, &imageFormSpec{name: spec.Name, dockerImage: spec.Image})
}
styles := s.App().Styles.Dialog()
f := tview.NewForm().
SetItemPadding(0).
SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetButtonTextColor(styles.ButtonFgColor.Color()).
SetLabelColor(styles.LabelFgColor.Color()).
SetFieldTextColor(styles.FieldFgColor.Color()).
AddButton("OK", func() {
defer s.dismissDialog()
var imageSpecsModified dao.ImageSpecs
for _, v := range formContainerLines {
if v.modified() {
imageSpecsModified = append(imageSpecsModified, v.imageSpec())
}
}
ctx, cancel := context.WithTimeout(context.Background(), s.App().Conn().Config().CallTimeout())
defer cancel()
if err := s.setImages(ctx, sel, imageSpecsModified); err != nil {
log.Error().Err(err).Msgf("PodSpec %s image update failed", sel)
s.App().Flash().Err(err)
return
}
s.App().Flash().Infof("Resource %s:%s image updated successfully", s.GVR(), sel)
}).
AddButton("Cancel", func() {
s.dismissDialog()
})
for i := range formContainerLines {
ctn := formContainerLines[i]
f.AddInputField(ctn.name, ctn.dockerImage, 0, nil, func(changed string) {
@ -114,26 +144,11 @@ func (s *ImageExtender) makeSetImageForm(sel string) (*tview.Form, error) {
})
}
f.AddButton("OK", func() {
defer s.dismissDialog()
var imageSpecsModified dao.ImageSpecs
for _, v := range formContainerLines {
if v.modified() {
imageSpecsModified = append(imageSpecsModified, v.imageSpec())
}
}
ctx, cancel := context.WithTimeout(context.Background(), s.App().Conn().Config().CallTimeout())
defer cancel()
if err := s.setImages(ctx, sel, imageSpecsModified); err != nil {
log.Error().Err(err).Msgf("PodSpec %s image update failed", sel)
s.App().Flash().Err(err)
return
}
s.App().Flash().Infof("Resource %s:%s image updated successfully", s.GVR(), sel)
})
f.AddButton("Cancel", func() {
s.dismissDialog()
})
for i := 0; i < f.GetButtonCount(); i++ {
f.GetButton(i).
SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color()).
SetLabelColorActivated(styles.ButtonFocusFgColor.Color())
}
return f, nil
}
@ -142,17 +157,6 @@ func (s *ImageExtender) dismissDialog() {
s.App().Content.RemovePage(imageKey)
}
func (s *ImageExtender) makeStyledForm() *tview.Form {
f := tview.NewForm()
f.SetItemPadding(0)
f.SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(tview.Styles.PrimitiveBackgroundColor).
SetButtonTextColor(tview.Styles.PrimaryTextColor).
SetLabelColor(tcell.ColorAqua).
SetFieldTextColor(tcell.ColorOrange)
return f
}
func (s *ImageExtender) getPodSpec(path string) (*corev1.PodSpec, error) {
res, err := dao.AccessorFor(s.App().factory, s.GVR())
if err != nil {

View File

@ -15,8 +15,8 @@ import (
"github.com/derailed/k9s/internal/model"
"github.com/derailed/k9s/internal/perf"
"github.com/derailed/k9s/internal/ui"
"github.com/derailed/k9s/internal/ui/dialog"
"github.com/derailed/tcell/v2"
"github.com/derailed/tview"
"github.com/rs/zerolog/log"
)
@ -165,16 +165,14 @@ func (p *PortForward) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
var msg string
if len(selections) > 1 {
msg = fmt.Sprintf("Delete %d marked %s?", len(selections), p.GVR())
} else if h, err := pfToHuman(selections[0]); err == nil {
msg = fmt.Sprintf("Delete %s %s?", p.GVR().R(), h)
} else {
h, err := pfToHuman(selections[0])
if err == nil {
msg = fmt.Sprintf("Delete %s %s?", p.GVR().R(), h)
} else {
p.App().Flash().Err(err)
return nil
}
p.App().Flash().Err(err)
return nil
}
showModal(p.App(), msg, func() {
dialog.ShowConfirm(p.App().Styles.Dialog(), p.App().Content.Pages, "Delete", msg, func() {
for _, s := range selections {
var pf dao.PortForward
pf.Init(p.App().factory, client.NewGVR("portforwards"))
@ -185,7 +183,7 @@ func (p *PortForward) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
}
p.App().Flash().Infof("Successfully deleted %d PortForward!", len(selections))
p.GetTable().Refresh()
})
}, func() {})
return nil
}
@ -203,26 +201,3 @@ func pfToHuman(s string) (string, error) {
return fmt.Sprintf("%s::%s %s->%s", mm[2], mm[3], mm[4], mm[5]), nil
}
func showModal(a *App, msg string, ok func()) {
p := a.Content.Pages
styles := a.Styles.Dialog()
m := tview.NewModal().
AddButtons([]string{"Cancel", "OK"}).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetTextColor(tcell.ColorFuchsia).
SetText(msg).
SetDoneFunc(func(_ int, b string) {
if b == "OK" {
ok()
}
dismissModal(p)
})
m.SetTitle("<Delete Benchmark>")
p.AddPage(promptPage, m, false, false)
p.ShowPage(promptPage)
}
func dismissModal(p *ui.Pages) {
p.RemovePage(promptPage)
}

View File

@ -9,8 +9,8 @@ import (
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/dao"
"github.com/derailed/k9s/internal/ui"
"github.com/derailed/k9s/internal/ui/dialog"
"github.com/derailed/tcell/v2"
"github.com/derailed/tview"
)
// ReplicaSet presents a replicaset viewer.
@ -59,12 +59,9 @@ func (r *ReplicaSet) rollbackCmd(evt *tcell.EventKey) *tcell.EventKey {
return evt
}
r.showModal(fmt.Sprintf("Rollback %s %s?", r.GVR(), path), func(_ int, button string) {
defer r.dismissModal()
msg := fmt.Sprintf("Rollback %s %s?", r.GVR(), path)
if button != "OK" {
return
}
dialog.ShowConfirm(r.App().Styles.Dialog(), r.App().Content.Pages, "Rollback", msg, func() {
r.App().Flash().Infof("Rolling back %s %s", r.GVR(), path)
var drs dao.ReplicaSet
drs.Init(r.App().factory, r.GVR())
@ -74,23 +71,7 @@ func (r *ReplicaSet) rollbackCmd(evt *tcell.EventKey) *tcell.EventKey {
r.App().Flash().Infof("%s successfully rolled back", path)
}
r.Refresh()
})
}, func() {})
return nil
}
func (r *ReplicaSet) dismissModal() {
r.App().Content.RemovePage("confirm")
}
func (r *ReplicaSet) showModal(msg string, done func(int, string)) {
styles := r.App().Styles.Dialog()
confirm := tview.NewModal().
AddButtons([]string{"Cancel", "OK"}).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetTextColor(tcell.ColorFuchsia).
SetText(msg).
SetDoneFunc(done)
r.App().Content.AddPage("confirm", confirm, false, false)
r.App().Content.ShowPage("confirm")
}

View File

@ -9,8 +9,6 @@ import (
"strconv"
"strings"
"github.com/derailed/k9s/internal/config"
"github.com/derailed/k9s/internal/dao"
"github.com/derailed/k9s/internal/ui"
"github.com/derailed/tcell/v2"
@ -84,9 +82,6 @@ func (s *ScaleExtender) valueOf(col string) (string, error) {
}
func (s *ScaleExtender) makeScaleForm(sels []string) (*tview.Form, error) {
styles := s.App().Styles.Dialog()
f := s.makeStyledForm(styles)
factor := "0"
if len(sels) == 1 {
replicas, err := s.valueOf("READY")
@ -99,6 +94,16 @@ func (s *ScaleExtender) makeScaleForm(sels []string) (*tview.Form, error) {
}
factor = strings.TrimRight(tokens[1], ui.DeltaSign)
}
styles := s.App().Styles.Dialog()
f := tview.NewForm().
SetItemPadding(0).
SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetButtonTextColor(styles.ButtonFgColor.Color()).
SetLabelColor(styles.LabelFgColor.Color()).
SetFieldTextColor(styles.FieldFgColor.Color())
f.AddInputField("Replicas:", factor, 4, func(textToCheck string, lastChar rune) bool {
_, err := strconv.Atoi(textToCheck)
return err == nil
@ -138,6 +143,12 @@ func (s *ScaleExtender) makeScaleForm(sels []string) (*tview.Form, error) {
}
}
for i := 0; i < f.GetButtonCount(); i++ {
f.GetButton(i).
SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color()).
SetLabelColorActivated(styles.ButtonFocusFgColor.Color())
}
return f, nil
}
@ -145,18 +156,6 @@ func (s *ScaleExtender) dismissDialog() {
s.App().Content.RemovePage(scaleDialogKey)
}
func (s *ScaleExtender) makeStyledForm(styles config.Dialog) *tview.Form {
f := tview.NewForm()
f.SetItemPadding(0)
f.SetButtonsAlign(tview.AlignCenter).
SetButtonBackgroundColor(styles.ButtonBgColor.Color()).
SetButtonTextColor(styles.ButtonBgColor.Color()).
SetLabelColor(styles.LabelFgColor.Color()).
SetFieldTextColor(styles.FieldFgColor.Color())
return f
}
func (s *ScaleExtender) scale(ctx context.Context, path string, replicas int) error {
res, err := dao.AccessorFor(s.App().factory, s.GVR())
if err != nil {