allow to mark multiple resources to act upon
parent
23f61320cb
commit
42e5793438
|
|
@ -99,6 +99,7 @@ type (
|
|||
FgColor string `yaml:"fgColor"`
|
||||
BgColor string `yaml:"bgColor"`
|
||||
CursorColor string `yaml:"cursorColor"`
|
||||
MarkColor string `yaml:"markColor"`
|
||||
Header TableHeader `yaml:"header"`
|
||||
}
|
||||
|
||||
|
|
@ -215,6 +216,7 @@ func newTable() Table {
|
|||
FgColor: "aqua",
|
||||
BgColor: "black",
|
||||
CursorColor: "aqua",
|
||||
MarkColor: "darkgoldenrod",
|
||||
Header: newTableHeader(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ type (
|
|||
Rows RowEvents
|
||||
NumCols map[string]bool
|
||||
Namespace string
|
||||
Marks []string
|
||||
}
|
||||
|
||||
// List protocol to display and update a collection of resources
|
||||
|
|
@ -84,6 +85,7 @@ type (
|
|||
SetFieldSelector(string)
|
||||
SetLabelSelector(string)
|
||||
HasSelectors() bool
|
||||
ToggleMark(sk string)
|
||||
}
|
||||
|
||||
// Columnar tracks resources that can be diplayed in a tabular fashion.
|
||||
|
|
@ -127,9 +129,20 @@ type (
|
|||
verbs int
|
||||
resource Resource
|
||||
cache RowEvents
|
||||
marks []string
|
||||
}
|
||||
)
|
||||
|
||||
// IsMarked checks if key is marked.
|
||||
func (t *TableData) IsMarked(sk string) bool {
|
||||
for _, mark := range t.Marks {
|
||||
if mark == sk {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func newRowEvent(a watch.EventType, f, d Row) *RowEvent {
|
||||
return &RowEvent{Action: a, Fields: f, Deltas: d}
|
||||
}
|
||||
|
|
@ -232,6 +245,7 @@ func (l *list) Data() TableData {
|
|||
Rows: l.cache,
|
||||
NumCols: l.resource.NumCols(l.namespace),
|
||||
Namespace: l.namespace,
|
||||
Marks: l.marks,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -343,10 +357,29 @@ func (l *list) ensureDeletes(kk []string) {
|
|||
}
|
||||
if !found {
|
||||
delete(l.cache, k)
|
||||
l.removeMark(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *list) removeMark(sk string) {
|
||||
for index, mark := range l.marks {
|
||||
if mark == sk {
|
||||
l.marks = append(l.marks[:index], l.marks[index+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *list) ToggleMark(sk string) {
|
||||
for index, mark := range l.marks {
|
||||
if mark == sk {
|
||||
l.marks = append(l.marks[:index], l.marks[index+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
l.marks = append(l.marks, sk)
|
||||
}
|
||||
|
||||
// Helpers...
|
||||
|
||||
func computeDeltas(evt *RowEvent, newRow, deltas Row) watch.EventType {
|
||||
|
|
|
|||
|
|
@ -169,6 +169,16 @@ func (v *Table) GetSelectedItem() string {
|
|||
return v.selectedItem
|
||||
}
|
||||
|
||||
// GetSelectedItems return currently marked or selected items names.
|
||||
func (v *Table) GetSelectedItems() []string {
|
||||
if len(v.data.Marks) > 0 {
|
||||
items := make([]string, len(v.data.Marks))
|
||||
copy(items, v.data.Marks)
|
||||
return items
|
||||
}
|
||||
return []string{v.GetSelectedItem()}
|
||||
}
|
||||
|
||||
func (v *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||
key := evt.Key()
|
||||
if key == tcell.KeyRune {
|
||||
|
|
@ -318,6 +328,7 @@ func (v *Table) buildRow(row int, data resource.TableData, sk string, pads MaxyP
|
|||
if v.colorerFn != nil {
|
||||
f = v.colorerFn
|
||||
}
|
||||
m := data.IsMarked(sk)
|
||||
for col, field := range data.Rows[sk].Fields {
|
||||
header := data.Header[col]
|
||||
field, align := v.formatCell(data.NumCols[header], header, field+Deltas(data.Rows[sk].Deltas[col], field), pads[col])
|
||||
|
|
@ -326,6 +337,9 @@ func (v *Table) buildRow(row int, data resource.TableData, sk string, pads MaxyP
|
|||
c.SetExpansion(1)
|
||||
c.SetAlign(align)
|
||||
c.SetTextColor(f(data.Namespace, data.Rows[sk]))
|
||||
if m {
|
||||
c.SetBackgroundColor(config.AsColor(v.styles.Table().MarkColor))
|
||||
}
|
||||
}
|
||||
v.SetCell(row, col, c)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,15 +115,17 @@ func (v *podView) killCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return evt
|
||||
}
|
||||
|
||||
sel := v.masterPage().GetSelectedItem()
|
||||
sel := v.masterPage().GetSelectedItems()
|
||||
v.masterPage().ShowDeleted()
|
||||
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), sel)
|
||||
if err := v.list.Resource().Delete(sel, true, false); err != nil {
|
||||
v.app.Flash().Errf("Delete failed with %s", err)
|
||||
} else {
|
||||
deletePortForward(v.app.forwarders, sel)
|
||||
v.refresh()
|
||||
for _, res := range sel {
|
||||
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), res)
|
||||
if err := v.list.Resource().Delete(res, true, false); err != nil {
|
||||
v.app.Flash().Errf("Delete failed with %s", err)
|
||||
} else {
|
||||
deletePortForward(v.app.forwarders, res)
|
||||
}
|
||||
}
|
||||
v.refresh()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -192,23 +192,42 @@ func (v *resourceView) deleteCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
return evt
|
||||
}
|
||||
|
||||
sel := v.masterPage().GetSelectedItem()
|
||||
msg := fmt.Sprintf("Delete %s %s?", v.list.GetName(), sel)
|
||||
sel := v.masterPage().GetSelectedItems()
|
||||
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)
|
||||
}
|
||||
dialog.ShowDelete(v.Pages, msg, func(cascade, force bool) {
|
||||
v.masterPage().ShowDeleted()
|
||||
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), sel)
|
||||
if err := v.list.Resource().Delete(sel, cascade, force); err != nil {
|
||||
v.app.Flash().Errf("Delete failed with %s", err)
|
||||
} else {
|
||||
deletePortForward(v.app.forwarders, sel)
|
||||
v.refresh()
|
||||
for _, res := range sel {
|
||||
v.app.Flash().Infof("Delete resource %s %s", v.list.GetName(), res)
|
||||
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() {
|
||||
v.switchPage("master")
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *resourceView) markCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if !v.masterPage().RowSelected() {
|
||||
return evt
|
||||
}
|
||||
|
||||
sel := v.masterPage().GetSelectedItem()
|
||||
v.list.ToggleMark(sel)
|
||||
v.refresh()
|
||||
v.app.Draw()
|
||||
return nil
|
||||
}
|
||||
|
||||
func deletePortForward(ff map[string]forwarder, sel string) {
|
||||
for k, v := range ff {
|
||||
tokens := strings.Split(k, ":")
|
||||
|
|
@ -371,6 +390,7 @@ func (v *resourceView) refreshActions() {
|
|||
tcell.KeyEnter: ui.NewKeyAction("Enter", v.enterCmd, false),
|
||||
tcell.KeyCtrlR: ui.NewKeyAction("Refresh", v.refreshCmd, false),
|
||||
}
|
||||
aa[tcell.KeyCtrlSpace] = ui.NewKeyAction("Mark", v.markCmd, true)
|
||||
v.namespaceActions(aa)
|
||||
v.defaultActions(aa)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ k9s:
|
|||
fgColor: white
|
||||
bgColor: black
|
||||
cursorColor: white
|
||||
markColor: darkgoldenrod
|
||||
header:
|
||||
fgColor: darkgray
|
||||
bgColor: black
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ k9s:
|
|||
fgColor: blue
|
||||
bgColor: darkblue
|
||||
cursorColor: aqua
|
||||
markColor: mediumslateblue
|
||||
header:
|
||||
fgColor: white
|
||||
bgColor: darkblue
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ k9s:
|
|||
fgColor: blue
|
||||
bgColor: black
|
||||
cursorColor: aqua
|
||||
markColor: darkgoldenrod
|
||||
header:
|
||||
fgColor: white
|
||||
bgColor: black
|
||||
|
|
|
|||
Loading…
Reference in New Issue