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: change sort col using two fixed keys #1256

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
29 changes: 23 additions & 6 deletions internal/render/row.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"time"

"github.com/fvbommel/sortorder"
"github.com/rs/zerolog/log"
"k8s.io/apimachinery/pkg/api/resource"
)

// Fields represents a collection of row fields.
Expand Down Expand Up @@ -162,10 +164,10 @@ func (rr Rows) Sort(col int, asc, isNum, isDur bool) {

// RowSorter sorts rows.
type RowSorter struct {
Rows Rows
Index int
IsNumber, IsDuration bool
Asc bool
Rows Rows
Index int
IsNumber, IsDuration, IsQuantity bool
Asc bool
}

func (s RowSorter) Len() int {
Expand All @@ -177,7 +179,7 @@ func (s RowSorter) Swap(i, j int) {
}

func (s RowSorter) Less(i, j int) bool {
return Less(s.Asc, s.IsNumber, s.IsDuration, s.Rows[i].Fields[s.Index], s.Rows[j].Fields[s.Index])
return Less(s.Asc, s.IsNumber, s.IsDuration, s.IsQuantity, s.Rows[i].Fields[s.Index], s.Rows[j].Fields[s.Index])
}

// ----------------------------------------------------------------------------
Expand All @@ -193,7 +195,22 @@ func toAgeDuration(dur string) string {
}

// Less return true if c1 < c2.
func Less(asc, isNumber, isDuration bool, c1, c2 string) bool {
func Less(asc, isNumber, isDuration, isQuantity bool, c1, c2 string) bool {
if isQuantity {
q1, errQ1 := resource.ParseQuantity(c1)
q2, errQ2 := resource.ParseQuantity(c2)
if errQ1 == nil && errQ2 == nil {
cmp := q1.Cmp(q2)
b := cmp == -1
if asc {
return b
}
return !b
} else {
log.Debug().Msgf("Failed to parse quantities: %s - %s", c1, c2)
// Use default comparison even if it might be incorrect
}
}
if isNumber {
c1, c2 = strings.Replace(c1, ",", "", -1), strings.Replace(c2, ",", "", -1)
}
Expand Down
6 changes: 4 additions & 2 deletions internal/render/row_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ func (r RowEvents) FindIndex(id string) (int, bool) {
}

// Sort rows based on column index and order.
func (r RowEvents) Sort(ns string, sortCol int, ageCol, numCol, asc bool) {
func (r RowEvents) Sort(ns string, sortCol int, ageCol, numCol, qtyCol, asc bool) {
if sortCol == -1 {
return
}
Expand All @@ -208,6 +208,7 @@ func (r RowEvents) Sort(ns string, sortCol int, ageCol, numCol, asc bool) {
Asc: asc,
IsNumber: numCol,
IsDuration: ageCol,
IsQuantity: qtyCol,
}
sort.Sort(t)

Expand Down Expand Up @@ -239,6 +240,7 @@ type RowEventSorter struct {
NS string
IsNumber bool
IsDuration bool
IsQuantity bool
Asc bool
}

Expand All @@ -252,7 +254,7 @@ func (r RowEventSorter) Swap(i, j int) {

func (r RowEventSorter) Less(i, j int) bool {
f1, f2 := r.Events[i].Row.Fields, r.Events[j].Row.Fields
return Less(r.Asc, r.IsNumber, r.IsDuration, f1[r.Index], f2[r.Index])
return Less(r.Asc, r.IsNumber, r.IsDuration, r.IsQuantity, f1[r.Index], f2[r.Index])
}

// ----------------------------------------------------------------------------
Expand Down
42 changes: 37 additions & 5 deletions internal/render/row_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,10 @@ func TestRowEventsDelete(t *testing.T) {

func TestRowEventsSort(t *testing.T) {
uu := map[string]struct {
re render.RowEvents
col int
age, num, asc bool
e render.RowEvents
re render.RowEvents
col int
age, num, qty, asc bool
e render.RowEvents
}{
"age_time": {
re: render.RowEvents{
Expand Down Expand Up @@ -444,6 +444,38 @@ func TestRowEventsSort(t *testing.T) {
{Row: render.Row{ID: "A", Fields: render.Fields{"1", "2", "32d"}}},
},
},
"qty": {
re: render.RowEvents{
{Row: render.Row{ID: "B", Fields: render.Fields{"0", "2", "900Mi"}}},
{Row: render.Row{ID: "C", Fields: render.Fields{"10", "2", "100Mi"}}},
{Row: render.Row{ID: "A", Fields: render.Fields{"1", "2", "8Gi"}}},
},

col: 2,
asc: true,
qty: true,
e: render.RowEvents{
{Row: render.Row{ID: "C", Fields: render.Fields{"10", "2", "100Mi"}}},
{Row: render.Row{ID: "B", Fields: render.Fields{"0", "2", "900Mi"}}},
{Row: render.Row{ID: "A", Fields: render.Fields{"1", "2", "8Gi"}}},
},
},
"qty_desc": {
re: render.RowEvents{
{Row: render.Row{ID: "B", Fields: render.Fields{"0", "2", "900Mi"}}},
{Row: render.Row{ID: "C", Fields: render.Fields{"10", "2", "100Mi"}}},
{Row: render.Row{ID: "A", Fields: render.Fields{"1", "2", "8Gi"}}},
},

col: 2,
asc: false,
qty: true,
e: render.RowEvents{
{Row: render.Row{ID: "A", Fields: render.Fields{"1", "2", "8Gi"}}},
{Row: render.Row{ID: "B", Fields: render.Fields{"0", "2", "900Mi"}}},
{Row: render.Row{ID: "C", Fields: render.Fields{"10", "2", "100Mi"}}},
},
},
"col0": {
re: render.RowEvents{
{Row: render.Row{ID: "A", Fields: render.Fields{"1", "2", "3"}}},
Expand Down Expand Up @@ -483,7 +515,7 @@ func TestRowEventsSort(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
u.re.Sort("", u.col, u.age, u.num, u.asc)
u.re.Sort("", u.col, u.age, u.num, u.qty, u.asc)
assert.Equal(t, u.e, u.re)
})
}
Expand Down
12 changes: 8 additions & 4 deletions internal/ui/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ func initKeys() {
tcell.KeyNames[tcell.Key(KeyHelp)] = "?"
tcell.KeyNames[tcell.Key(KeySlash)] = "/"
tcell.KeyNames[tcell.Key(KeySpace)] = "space"
tcell.KeyNames[tcell.Key(KeyLess)] = "<"
tcell.KeyNames[tcell.Key(KeyGreater)] = ">"

initNumbKeys()
initStdKeys()
Expand Down Expand Up @@ -73,10 +75,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
68 changes: 60 additions & 8 deletions internal/ui/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,23 @@ func (t *Table) SetSortCol(name string, asc bool) {
t.sortCol.name, t.sortCol.asc = name, asc
}

func (t *Table) GetSortCol() (string, bool) {
return t.sortCol.name, t.sortCol.asc
}

func (t *Table) isVisible(h render.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
}
return true
}

// Update table content.
func (t *Table) Update(data render.TableData, hasMetrics bool) {
t.header = data.Header
Expand Down Expand Up @@ -219,10 +236,7 @@ func (t *Table) doUpdate(data render.TableData) {

var col int
for _, h := range custData.Header {
if h.Name == "NAMESPACE" && !t.GetModel().ClusterWide() {
continue
}
if h.MX && !t.hasMetrics {
if !t.isVisible(h) {
continue
}
t.AddHeaderCell(col, h)
Expand All @@ -237,6 +251,7 @@ func (t *Table) doUpdate(data render.TableData) {
colIndex,
t.sortCol.name == "AGE",
data.Header.IsMetricsCol(colIndex),
t.sortCol.name == "CAPACITY",
t.sortCol.asc,
)

Expand All @@ -263,10 +278,7 @@ func (t *Table) buildRow(r int, re, ore render.RowEvent, h render.Header, pads M
continue
}

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

Expand Down Expand Up @@ -310,6 +322,46 @@ 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
for i := range t.header {
if direction == SortPrevCol {
i = len(t.header) - i - 1
}
h := t.header[i]

if !t.isVisible(h) {
continue
}
if newSortColIdx == -1 {
// This is the wrap around value, also default value if current sort col name is not found
newSortColIdx = i
}
if sortColIdx != -1 {
// Next match after finding the col name is the target sort column
newSortColIdx = i
break
}
if h.Name == sortCol {
sortColIdx = i
}
}
log.Debug().Msgf("Currently sorting on col %s with index %d", t.sortCol.name, sortColIdx)
// sortColIdx equals -1 is a possible outcome, don't check for it
if newSortColIdx != -1 {
t.sortCol.name = t.header[newSortColIdx].Name
log.Debug().Msgf("New sort col is %s with index %d", t.sortCol.name, newSortColIdx)
// Leave sort order as is
}
t.Refresh()
return nil
}
}

// SortInvertCmd reverses sorting order.
func (t *Table) SortInvertCmd(evt *tcell.EventKey) *tcell.EventKey {
t.sortCol.asc = !t.sortCol.asc
Expand Down
8 changes: 8 additions & 0 deletions internal/ui/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ type (
name string
asc bool
}

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

const (
SortNextCol SortChange = true
SortPrevCol SortChange = false
)

// Namespaceable represents a namespaceable model.
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 @@ -23,7 +23,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 @@ -13,5 +13,5 @@ func TestConfigMapNew(t *testing.T) {

assert.Nil(t, s.Init(makeCtx()))
assert.Equal(t, "ConfigMaps", s.Name())
assert.Equal(t, 6, len(s.Hints()))
assert.Equal(t, 9, 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 @@ -13,5 +13,5 @@ func TestContainerNew(t *testing.T) {

assert.Nil(t, c.Init(makeCtx()))
assert.Equal(t, "Containers", c.Name())
assert.Equal(t, 18, len(c.Hints()))
assert.Equal(t, 21, 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 @@ -13,5 +13,5 @@ func TestContext(t *testing.T) {

assert.Nil(t, ctx.Init(makeCtx()))
assert.Equal(t, "Contexts", ctx.Name())
assert.Equal(t, 4, len(ctx.Hints()))
assert.Equal(t, 7, 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 @@ -12,5 +12,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 @@ -13,5 +13,5 @@ func TestDeploy(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "Deployments", v.Name())
assert.Equal(t, 14, len(v.Hints()))
assert.Equal(t, 17, 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 @@ -13,5 +13,5 @@ func TestDaemonSet(t *testing.T) {

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "DaemonSets", v.Name())
assert.Equal(t, 15, len(v.Hints()))
assert.Equal(t, 18, 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 @@ -21,7 +21,7 @@ func TestHelp(t *testing.T) {
v := view.NewHelp(app)

assert.Nil(t, v.Init(ctx))
assert.Equal(t, 25, v.GetRowCount())
assert.Equal(t, 28, v.GetRowCount())
assert.Equal(t, 6, 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 @@ -13,5 +13,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 @@ -13,5 +13,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 @@ -16,7 +16,7 @@ func TestPodNew(t *testing.T) {

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

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

assert.Nil(t, v.Init(makeCtx()))
assert.Equal(t, "PersistentVolumeClaims", v.Name())
assert.Equal(t, 10, len(v.Hints()))
assert.Equal(t, 13, 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 @@ -13,5 +13,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()))
}
Loading