diff --git a/Makefile b/Makefile
index b5e40477..e6b34759 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ PACKAGE := github.com/derailed/$(NAME)
GIT_REV ?= $(shell git rev-parse --short HEAD)
SOURCE_DATE_EPOCH ?= $(shell date +%s)
DATE ?= $(shell date -u -d @${SOURCE_DATE_EPOCH} +"%Y-%m-%dT%H:%M:%SZ")
-VERSION ?= v0.25.16
+VERSION ?= v0.25.17
IMG_NAME := derailed/k9s
IMAGE := ${IMG_NAME}:${VERSION}
diff --git a/change_logs/release_v0.25.17.md b/change_logs/release_v0.25.17.md
new file mode 100644
index 00000000..8e6c0e38
--- /dev/null
+++ b/change_logs/release_v0.25.17.md
@@ -0,0 +1,26 @@
+
+
+# Release v0.25.17
+
+## Notes
+
+Thank you to all that contributed with flushing out issues and enhancements for K9s! I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev and see if we're happier with some of the fixes! If you've filed an issue please help me verify and close. Your support, kindness and awesome suggestions to make K9s better are as ever very much noted and appreciated!
+
+If you feel K9s is helping your Kubernetes journey, please consider joining our [sponsorship program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer)
+
+On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM)
+
+---
+
+## Maintenance Release
+
+---
+
+## Resolved Issues
+
+* [Issue #1402](https://github.com/derailed/k9s/issues/1402) Sort functionality does not work properly on v0.25.16
+* [Issue #1401](https://github.com/derailed/k9s/issues/1401) Nothin selected when last item deleted
+
+---
+
+
© 2021 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
diff --git a/internal/model/table.go b/internal/model/table.go
index 4d8db08c..954a1c18 100644
--- a/internal/model/table.go
+++ b/internal/model/table.go
@@ -150,11 +150,16 @@ func (t *Table) ClusterWide() bool {
return client.IsClusterWide(t.namespace)
}
-// Empty return true if no model data.
+// Empty returns true if no model data.
func (t *Table) Empty() bool {
return len(t.data.RowEvents) == 0
}
+// Count returns the row count.
+func (t *Table) Count() int {
+ return len(t.data.RowEvents)
+}
+
// Peek returns model data.
func (t *Table) Peek() render.TableData {
t.mx.RLock()
diff --git a/internal/ui/select_table.go b/internal/ui/select_table.go
index bd9d746c..e59ac052 100644
--- a/internal/ui/select_table.go
+++ b/internal/ui/select_table.go
@@ -41,7 +41,10 @@ func (s *SelectTable) SelectFirstRow() {
// GetSelectedItems return currently marked or selected items names.
func (s *SelectTable) GetSelectedItems() []string {
if len(s.marks) == 0 {
- return []string{s.GetSelectedItem()}
+ if item := s.GetSelectedItem(); item != "" {
+ return []string{item}
+ }
+ return nil
}
items := make([]string, 0, len(s.marks))
@@ -100,6 +103,9 @@ func (s *SelectTable) SelectRow(r int, broadcast bool) {
if !broadcast {
s.SetSelectionChangedFunc(nil)
}
+ if r >= s.model.Count() {
+ r = s.model.Count()
+ }
defer s.SetSelectionChangedFunc(s.selectionChanged)
s.Select(r, 0)
}
diff --git a/internal/ui/table.go b/internal/ui/table.go
index 87f54421..bead0aed 100644
--- a/internal/ui/table.go
+++ b/internal/ui/table.go
@@ -193,7 +193,6 @@ func (t *Table) doUpdate(data render.TableData) {
t.actions[KeyShiftP] = NewKeyAction("Sort Namespace", t.SortColCmd("NAMESPACE", true), false)
t.sortCol.name = "NAMESPACE"
} else {
- t.sortCol.name = "NAME"
t.actions.Delete(KeyShiftP)
}
@@ -215,7 +214,7 @@ func (t *Table) doUpdate(data render.TableData) {
}
}
- if t.sortCol.name == "NAMESPACE" && !client.IsAllNamespaces(data.Namespace) && len(custData.Header) > 0 {
+ if t.sortCol.name == "" || (t.sortCol.name == "NAMESPACE" && !client.IsAllNamespaces(data.Namespace)) && len(custData.Header) > 0 {
if idx := custData.Header.IndexOf("NAME", false); idx >= 0 {
t.sortCol.name = custData.Header[idx].Name
} else {
diff --git a/internal/ui/table_test.go b/internal/ui/table_test.go
index e798f446..7c0657d8 100644
--- a/internal/ui/table_test.go
+++ b/internal/ui/table_test.go
@@ -64,6 +64,7 @@ var _ ui.Tabular = &mockModel{}
func (t *mockModel) SetInstance(string) {}
func (t *mockModel) SetLabelFilter(string) {}
func (t *mockModel) Empty() bool { return false }
+func (t *mockModel) Count() int { return 1 }
func (t *mockModel) HasMetrics() bool { return true }
func (t *mockModel) Peek() render.TableData { return makeTableData() }
func (t *mockModel) Refresh(context.Context) error { return nil }
diff --git a/internal/ui/types.go b/internal/ui/types.go
index 578cb00c..229497c9 100644
--- a/internal/ui/types.go
+++ b/internal/ui/types.go
@@ -55,6 +55,9 @@ type Tabular interface {
// Empty returns true if model has no data.
Empty() bool
+ // Count returns the model data count.
+ Count() int
+
// Peek returns current model data.
Peek() render.TableData
diff --git a/internal/view/alias_test.go b/internal/view/alias_test.go
index bccf38af..3b207e9f 100644
--- a/internal/view/alias_test.go
+++ b/internal/view/alias_test.go
@@ -110,6 +110,7 @@ func (t *mockModel) ClearSuggestions() {}
func (t *mockModel) SetInstance(string) {}
func (t *mockModel) SetLabelFilter(string) {}
func (t *mockModel) Empty() bool { return false }
+func (t *mockModel) Count() int { return 1 }
func (t *mockModel) HasMetrics() bool { return true }
func (t *mockModel) Peek() render.TableData { return makeTableData() }
func (t *mockModel) ClusterWide() bool { return false }
diff --git a/internal/view/table_int_test.go b/internal/view/table_int_test.go
index 7fde100b..54c40e6e 100644
--- a/internal/view/table_int_test.go
+++ b/internal/view/table_int_test.go
@@ -95,6 +95,7 @@ var _ ui.Tabular = (*mockTableModel)(nil)
func (t *mockTableModel) SetInstance(string) {}
func (t *mockTableModel) SetLabelFilter(string) {}
func (t *mockTableModel) Empty() bool { return false }
+func (t *mockTableModel) Count() int { return 1 }
func (t *mockTableModel) HasMetrics() bool { return true }
func (t *mockTableModel) Peek() render.TableData { return makeTableData() }
func (t *mockTableModel) Refresh(context.Context) error { return nil }