Merge pull request #354 from bkmeneguello/mark
Allow to select multiple resources and add support to Delete/Kill all togethermine
commit
3d0de988ca
|
|
@ -99,6 +99,7 @@ type (
|
||||||
FgColor string `yaml:"fgColor"`
|
FgColor string `yaml:"fgColor"`
|
||||||
BgColor string `yaml:"bgColor"`
|
BgColor string `yaml:"bgColor"`
|
||||||
CursorColor string `yaml:"cursorColor"`
|
CursorColor string `yaml:"cursorColor"`
|
||||||
|
MarkColor string `yaml:"markColor"`
|
||||||
Header TableHeader `yaml:"header"`
|
Header TableHeader `yaml:"header"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,6 +216,7 @@ func newTable() Table {
|
||||||
FgColor: "aqua",
|
FgColor: "aqua",
|
||||||
BgColor: "black",
|
BgColor: "black",
|
||||||
CursorColor: "aqua",
|
CursorColor: "aqua",
|
||||||
|
MarkColor: "darkgoldenrod",
|
||||||
Header: newTableHeader(),
|
Header: newTableHeader(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,7 @@ const (
|
||||||
KeyHelp = 63
|
KeyHelp = 63
|
||||||
KeySlash = 47
|
KeySlash = 47
|
||||||
KeyColon = 58
|
KeyColon = 58
|
||||||
|
KeySpace = 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// Define Shift Keys
|
// Define Shift Keys
|
||||||
|
|
@ -253,6 +254,7 @@ var NumKeys = map[int]int32{
|
||||||
func initKeys() {
|
func initKeys() {
|
||||||
tcell.KeyNames[tcell.Key(KeyHelp)] = "?"
|
tcell.KeyNames[tcell.Key(KeyHelp)] = "?"
|
||||||
tcell.KeyNames[tcell.Key(KeySlash)] = "/"
|
tcell.KeyNames[tcell.Key(KeySlash)] = "/"
|
||||||
|
tcell.KeyNames[tcell.Key(KeySpace)] = "space"
|
||||||
|
|
||||||
initNumbKeys()
|
initNumbKeys()
|
||||||
initStdKeys()
|
initStdKeys()
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ type Table struct {
|
||||||
selectedRow int
|
selectedRow int
|
||||||
selectedFn func(string) string
|
selectedFn func(string) string
|
||||||
selListeners []SelectedRowFunc
|
selListeners []SelectedRowFunc
|
||||||
|
marks map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTable returns a new table view.
|
// NewTable returns a new table view.
|
||||||
|
|
@ -53,6 +54,7 @@ func NewTable(title string, styles *config.Styles) *Table {
|
||||||
cmdBuff: NewCmdBuff('/', FilterBuff),
|
cmdBuff: NewCmdBuff('/', FilterBuff),
|
||||||
baseTitle: title,
|
baseTitle: title,
|
||||||
sortCol: SortColumn{0, 0, true},
|
sortCol: SortColumn{0, 0, true},
|
||||||
|
marks: make(map[string]bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
v.SetFixed(1, 0)
|
v.SetFixed(1, 0)
|
||||||
|
|
@ -169,6 +171,20 @@ func (v *Table) GetSelectedItem() string {
|
||||||
return v.selectedItem
|
return v.selectedItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetSelectedItems return currently marked or selected items names.
|
||||||
|
func (v *Table) GetSelectedItems() []string {
|
||||||
|
if len(v.marks) > 0 {
|
||||||
|
var items []string
|
||||||
|
for item, marked := range v.marks {
|
||||||
|
if marked {
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
return []string{v.GetSelectedItem()}
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
func (v *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
key := evt.Key()
|
key := evt.Key()
|
||||||
if key == tcell.KeyRune {
|
if key == tcell.KeyRune {
|
||||||
|
|
@ -323,6 +339,7 @@ func (v *Table) buildRow(row int, data resource.TableData, sk string, pads MaxyP
|
||||||
if v.colorerFn != nil {
|
if v.colorerFn != nil {
|
||||||
f = v.colorerFn
|
f = v.colorerFn
|
||||||
}
|
}
|
||||||
|
m := v.isMarked(sk)
|
||||||
for col, field := range data.Rows[sk].Fields {
|
for col, field := range data.Rows[sk].Fields {
|
||||||
header := data.Header[col]
|
header := data.Header[col]
|
||||||
field, align := v.formatCell(data.NumCols[header], header, field+Deltas(data.Rows[sk].Deltas[col], field), pads[col])
|
field, align := v.formatCell(data.NumCols[header], header, field+Deltas(data.Rows[sk].Deltas[col], field), pads[col])
|
||||||
|
|
@ -331,6 +348,9 @@ func (v *Table) buildRow(row int, data resource.TableData, sk string, pads MaxyP
|
||||||
c.SetExpansion(1)
|
c.SetExpansion(1)
|
||||||
c.SetAlign(align)
|
c.SetAlign(align)
|
||||||
c.SetTextColor(f(data.Namespace, data.Rows[sk]))
|
c.SetTextColor(f(data.Namespace, data.Rows[sk]))
|
||||||
|
if m {
|
||||||
|
c.SetBackgroundColor(config.AsColor(v.styles.Table().MarkColor))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
v.SetCell(row, col, c)
|
v.SetCell(row, col, c)
|
||||||
}
|
}
|
||||||
|
|
@ -527,3 +547,12 @@ func (v *Table) SortInvertCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToggleMark toggles marked row
|
||||||
|
func (v *Table) ToggleMark() {
|
||||||
|
v.marks[v.GetSelectedItem()] = !v.marks[v.GetSelectedItem()]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Table) isMarked(item string) bool {
|
||||||
|
return v.marks[item]
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,15 +115,17 @@ func (v *podView) killCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
sel := v.masterPage().GetSelectedItem()
|
sel := v.masterPage().GetSelectedItems()
|
||||||
v.masterPage().ShowDeleted()
|
v.masterPage().ShowDeleted()
|
||||||
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), sel)
|
for _, res := range sel {
|
||||||
if err := v.list.Resource().Delete(sel, true, false); err != nil {
|
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), res)
|
||||||
v.app.Flash().Errf("Delete failed with %s", err)
|
if err := v.list.Resource().Delete(res, true, false); err != nil {
|
||||||
} else {
|
v.app.Flash().Errf("Delete failed with %s", err)
|
||||||
deletePortForward(v.app.forwarders, sel)
|
} else {
|
||||||
v.refresh()
|
deletePortForward(v.app.forwarders, res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
v.refresh()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,23 +192,45 @@ func (v *resourceView) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
return evt
|
return evt
|
||||||
}
|
}
|
||||||
|
|
||||||
sel := v.masterPage().GetSelectedItem()
|
sel := v.masterPage().GetSelectedItems()
|
||||||
msg := fmt.Sprintf("Delete %s %s?", v.list.GetName(), sel)
|
var msg string
|
||||||
|
if len(sel) > 1 {
|
||||||
|
msg = fmt.Sprintf("Delete %d selected %s?", len(sel), v.list.GetName())
|
||||||
|
} else {
|
||||||
|
msg = fmt.Sprintf("Delete %s %s?", v.list.GetName(), sel[0])
|
||||||
|
}
|
||||||
dialog.ShowDelete(v.Pages, msg, func(cascade, force bool) {
|
dialog.ShowDelete(v.Pages, msg, func(cascade, force bool) {
|
||||||
v.masterPage().ShowDeleted()
|
v.masterPage().ShowDeleted()
|
||||||
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), sel)
|
if len(sel) > 1 {
|
||||||
if err := v.list.Resource().Delete(sel, cascade, force); err != nil {
|
v.app.Flash().Infof("Delete %d selected %s", len(sel), v.list.GetName())
|
||||||
v.app.Flash().Errf("Delete failed with %s", err)
|
|
||||||
} else {
|
} else {
|
||||||
deletePortForward(v.app.forwarders, sel)
|
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), sel[0])
|
||||||
v.refresh()
|
|
||||||
}
|
}
|
||||||
|
for _, res := range sel {
|
||||||
|
if err := v.list.Resource().Delete(res, cascade, force); err != nil {
|
||||||
|
v.app.Flash().Errf("Delete failed with %s", err)
|
||||||
|
} else {
|
||||||
|
deletePortForward(v.app.forwarders, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v.refresh()
|
||||||
}, func() {
|
}, func() {
|
||||||
v.switchPage("master")
|
v.switchPage("master")
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *resourceView) markCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
if !v.masterPage().RowSelected() {
|
||||||
|
return evt
|
||||||
|
}
|
||||||
|
|
||||||
|
v.masterPage().ToggleMark()
|
||||||
|
v.refresh()
|
||||||
|
v.app.Draw()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func deletePortForward(ff map[string]forwarder, sel string) {
|
func deletePortForward(ff map[string]forwarder, sel string) {
|
||||||
for k, v := range ff {
|
for k, v := range ff {
|
||||||
tokens := strings.Split(k, ":")
|
tokens := strings.Split(k, ":")
|
||||||
|
|
@ -375,6 +397,7 @@ func (v *resourceView) refreshActions() {
|
||||||
tcell.KeyEnter: ui.NewKeyAction("Enter", v.enterCmd, false),
|
tcell.KeyEnter: ui.NewKeyAction("Enter", v.enterCmd, false),
|
||||||
tcell.KeyCtrlR: ui.NewKeyAction("Refresh", v.refreshCmd, false),
|
tcell.KeyCtrlR: ui.NewKeyAction("Refresh", v.refreshCmd, false),
|
||||||
}
|
}
|
||||||
|
aa[ui.KeySpace] = ui.NewKeyAction("Mark", v.markCmd, true)
|
||||||
v.namespaceActions(aa)
|
v.namespaceActions(aa)
|
||||||
v.defaultActions(aa)
|
v.defaultActions(aa)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ k9s:
|
||||||
fgColor: white
|
fgColor: white
|
||||||
bgColor: black
|
bgColor: black
|
||||||
cursorColor: white
|
cursorColor: white
|
||||||
|
markColor: darkgoldenrod
|
||||||
header:
|
header:
|
||||||
fgColor: darkgray
|
fgColor: darkgray
|
||||||
bgColor: black
|
bgColor: black
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ k9s:
|
||||||
fgColor: blue
|
fgColor: blue
|
||||||
bgColor: darkblue
|
bgColor: darkblue
|
||||||
cursorColor: aqua
|
cursorColor: aqua
|
||||||
|
markColor: mediumslateblue
|
||||||
header:
|
header:
|
||||||
fgColor: white
|
fgColor: white
|
||||||
bgColor: darkblue
|
bgColor: darkblue
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ k9s:
|
||||||
fgColor: blue
|
fgColor: blue
|
||||||
bgColor: black
|
bgColor: black
|
||||||
cursorColor: aqua
|
cursorColor: aqua
|
||||||
|
markColor: darkgoldenrod
|
||||||
header:
|
header:
|
||||||
fgColor: white
|
fgColor: white
|
||||||
bgColor: black
|
bgColor: black
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue