Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sort): allow sorting any column with top like navigation #2739

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions internal/ui/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ func initKeys() {
tcell.KeyNames[KeyHelp] = "?"
tcell.KeyNames[KeySlash] = "/"
tcell.KeyNames[KeySpace] = "space"
tcell.KeyNames[KeyLess] = "<"
tcell.KeyNames[KeyGreater] = ">"

initNumbKeys()
initStdKeys()
Expand Down Expand Up @@ -76,10 +78,12 @@ const (
KeyX
KeyY
KeyZ
KeyHelp = 63
KeySlash = 47
KeyColon = 58
KeySpace = 32
KeyHelp = 63
KeySlash = 47
KeyColon = 58
KeySpace = 32
KeyLess = 60
KeyGreater = 62
)

// Define Shift Keys.
Expand Down
84 changes: 77 additions & 7 deletions internal/ui/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,26 @@ func (t *Table) SetSortCol(name string, asc bool) {
t.setSortCol(model1.SortColumn{Name: name, ASC: asc})
}

func (t *Table) GetSortCol() (string, bool) {
return t.sortCol.Name, t.sortCol.ASC
}

func (t *Table) isVisible(h model1.HeaderColumn) bool {
if h.Name == "NAMESPACE" && !t.GetModel().ClusterWide() {
return false
}
if h.MX && !t.hasMetrics {
return false
}
if h.Wide && !t.wide {
return false
}
if h.VS && vul.ImgScanner == nil {
return false
}
return true
}

// Update table content.
func (t *Table) Update(data *model1.TableData, hasMetrics bool) *model1.TableData {
if t.decorateFn != nil {
Expand Down Expand Up @@ -321,6 +341,20 @@ func (t *Table) UpdateUI(cdata, data *model1.TableData) {
return true
})

colIndex, ok := cdata.Header().IndexOf(t.sortCol.Name, false)
if ok {
events := cdata.GetRowEvents()
events.Sort(
cdata.GetNamespace(),
colIndex,
t.sortCol.Name == "AGE",
data.Header().IsMetricsCol(colIndex),
t.sortCol.Name == "CAPACITY",
t.sortCol.ASC,
)
cdata.SetRowEvents(events)
}

t.updateSelection(true)
t.UpdateTitle()
}
Expand All @@ -343,13 +377,7 @@ func (t *Table) buildRow(r int, re, ore model1.RowEvent, h model1.Header, pads M
continue
}

if h[c].Name == "NAMESPACE" && !t.GetModel().ClusterWide() {
continue
}
if h[c].MX && !t.hasMetrics {
continue
}
if h[c].VS && vul.ImgScanner == nil {
if !t.isVisible(h[c]) {
continue
}

Expand Down Expand Up @@ -396,6 +424,48 @@ func (t *Table) SortColCmd(name string, asc bool) func(evt *tcell.EventKey) *tce
}
}

// SortColChange changes on which column to sort
func (t *Table) SortColChange(direction SortChange) func(evt *tcell.EventKey) *tcell.EventKey {
return func(evt *tcell.EventKey) *tcell.EventKey {
sortCol := t.sortCol.Name
sortColIdx := -1
newSortColIdx := -1
prevSortColIdx := -1
header := t.GetModel().Peek().GetHeader()

for i, h := range header {
if !t.isVisible(h) {
continue
}

if h.Name == sortCol {
sortColIdx = i
break
}

prevSortColIdx = i
}

if direction == SortPrevCol {
newSortColIdx = prevSortColIdx
} else {
for i := sortColIdx + 1; i < len(header); i++ {
if t.isVisible(header[i]) {
newSortColIdx = i
break
}
}
}

if newSortColIdx != -1 {
t.sortCol.Name = header[newSortColIdx].Name
t.Refresh()
}

return nil
}
}

// SortInvertCmd reverses sorting order.
func (t *Table) SortInvertCmd(evt *tcell.EventKey) *tcell.EventKey {
t.toggleSortCol()
Expand Down
10 changes: 10 additions & 0 deletions internal/ui/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)

type (
// SortChange changes the column on which to sort
SortChange bool
)

const (
SortNextCol SortChange = true
SortPrevCol SortChange = false
)

// Namespaceable represents a namespaceable model.
type Namespaceable interface {
// ClusterWide returns true if the model represents resource in all namespaces.
Expand Down
2 changes: 1 addition & 1 deletion internal/view/alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func TestAliasNew(t *testing.T) {

assert.Nil(t, v.Init(makeContext()))
assert.Equal(t, "Aliases", v.Name())
assert.Equal(t, 6, len(v.Hints()))
assert.Equal(t, 9, len(v.Hints()))
}

func TestAliasSearch(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion internal/view/cm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestConfigMapNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "ConfigMaps", s.Name())
assert.Equal(t, 7, len(s.Hints()))
assert.Equal(t, 10, len(s.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestContainerNew(t *testing.T) {

assert.Nil(t, c.Init(makeCtx()))
assert.Equal(t, "Containers", c.Name())
assert.Equal(t, 19, len(c.Hints()))
assert.Equal(t, 22, len(c.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestContext(t *testing.T) {

assert.Nil(t, ctx.Init(makeCtx()))
assert.Equal(t, "Contexts", ctx.Name())
assert.Equal(t, 5, len(ctx.Hints()))
assert.Equal(t, 8, len(ctx.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/dir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ func TestDir(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "Directory", v.Name())
assert.Equal(t, 7, len(v.Hints()))
assert.Equal(t, 10, len(v.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/dp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestDeploy(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "Deployments", v.Name())
assert.Equal(t, 16, len(v.Hints()))
assert.Equal(t, 19, len(v.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/ds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestDaemonSet(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "DaemonSets", v.Name())
assert.Equal(t, 17, len(v.Hints()))
assert.Equal(t, 20, len(v.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestHelp(t *testing.T) {
v := view.NewHelp(app)

assert.Nil(t, v.Init(ctx))
assert.Equal(t, 29, v.GetRowCount())
assert.Equal(t, 32, v.GetRowCount())
assert.Equal(t, 8, v.GetColumnCount())
assert.Equal(t, "<a>", strings.TrimSpace(v.GetCell(1, 0).Text))
assert.Equal(t, "Attach", strings.TrimSpace(v.GetCell(1, 1).Text))
Expand Down
2 changes: 1 addition & 1 deletion internal/view/ns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestNSCleanser(t *testing.T) {

assert.Nil(t, ns.Init(makeCtx()))
assert.Equal(t, "Namespaces", ns.Name())
assert.Equal(t, 7, len(ns.Hints()))
assert.Equal(t, 10, len(ns.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/pf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestPortForwardNew(t *testing.T) {

assert.Nil(t, pf.Init(makeCtx()))
assert.Equal(t, "PortForwards", pf.Name())
assert.Equal(t, 10, len(pf.Hints()))
assert.Equal(t, 13, len(pf.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestPodNew(t *testing.T) {

assert.Nil(t, po.Init(makeCtx()))
assert.Equal(t, "Pods", po.Name())
assert.Equal(t, 28, len(po.Hints()))
assert.Equal(t, 31, len(po.Hints()))
}

// Helpers...
Expand Down
2 changes: 1 addition & 1 deletion internal/view/priorityclass_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestPriorityClassNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "PriorityClass", s.Name())
assert.Equal(t, 6, len(s.Hints()))
assert.Equal(t, 9, len(s.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/pvc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestPVCNew(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "PersistentVolumeClaims", v.Name())
assert.Equal(t, 11, len(v.Hints()))
assert.Equal(t, 14, len(v.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/rbac_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestRbacNew(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "Rbac", v.Name())
assert.Equal(t, 5, len(v.Hints()))
assert.Equal(t, 8, len(v.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/reference_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestReferenceNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "References", s.Name())
assert.Equal(t, 4, len(s.Hints()))
assert.Equal(t, 7, len(s.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/screen_dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestScreenDumpNew(t *testing.T) {

assert.Nil(t, po.Init(makeCtx()))
assert.Equal(t, "ScreenDumps", po.Name())
assert.Equal(t, 5, len(po.Hints()))
assert.Equal(t, 8, len(po.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestSecretNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "Secrets", s.Name())
assert.Equal(t, 8, len(s.Hints()))
assert.Equal(t, 11, len(s.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/sts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ func TestStatefulSetNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "StatefulSets", s.Name())
assert.Equal(t, 14, len(s.Hints()))
assert.Equal(t, 17, len(s.Hints()))
}
2 changes: 1 addition & 1 deletion internal/view/svc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,5 @@ func TestServiceNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "Services", s.Name())
assert.Equal(t, 12, len(s.Hints()))
assert.Equal(t, 15, len(s.Hints()))
}
3 changes: 3 additions & 0 deletions internal/view/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ func (t *Table) bindKeys() {
tcell.KeyCtrlW: ui.NewKeyAction("Toggle Wide", t.toggleWideCmd, false),
ui.KeyShiftN: ui.NewKeyAction("Sort Name", t.SortColCmd(nameCol, true), false),
ui.KeyShiftA: ui.NewKeyAction("Sort Age", t.SortColCmd(ageCol, true), false),
ui.KeyQ: ui.NewKeyAction("Reverse Sort Order", t.SortInvertCmd, false),
ui.KeyLess: ui.NewKeyAction("Sort Previous Column", t.SortColChange(ui.SortPrevCol), false),
ui.KeyGreater: ui.NewKeyAction("Sort Next Column", t.SortColChange(ui.SortNextCol), false),
})
}

Expand Down