Skip to content

Commit

Permalink
Feature: Added ability to select visible namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
F1bonacc1 committed Jan 13, 2024
1 parent 1a4a1b4 commit f6f31e8
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 37 deletions.
5 changes: 5 additions & 0 deletions src/tui/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const (
ActionLogFindNext = ActionName("find_next")
ActionLogFindPrev = ActionName("find_prev")
ActionLogFindExit = ActionName("find_exit")
ActionNsFilter = ActionName("ns_filter")
)

var defaultShortcuts = map[ActionName]tcell.Key{
Expand All @@ -46,6 +47,7 @@ var defaultShortcuts = map[ActionName]tcell.Key{
ActionLogFindNext: tcell.KeyCtrlN,
ActionLogFindPrev: tcell.KeyCtrlP,
ActionLogFindExit: tcell.KeyEsc,
ActionNsFilter: tcell.KeyCtrlG,
}

type ShortCuts struct {
Expand Down Expand Up @@ -216,6 +218,9 @@ func getDefaultActions() ShortCuts {
ActionLogFindExit: {
Description: "Exit Search",
},
ActionNsFilter: {
Description: "Select Namespace",
},
},
}
for k, v := range sc.ShortCutKeys {
Expand Down
96 changes: 96 additions & 0 deletions src/tui/namespace-selector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package tui

import (
"github.com/rivo/tview"
"github.com/rs/zerolog/log"
"slices"
)

func (pv *pcView) showNsFilter() {
filter := pv.createNsFilterPrimitive()
_, _, w, h := filter.GetRect()
pv.pages.AddPage(PageDialog, createDialogPage(filter, w, h), true, true)
pv.appView.SetFocus(filter)
}

func (pv *pcView) createNsFilterPrimitive() tview.Primitive {
selectAllNsLbl := "Select all the namespaces"
list := tview.NewList().
AddItem("All", selectAllNsLbl, '0', func() {
pv.setSelectedNs(AllNS)
pv.pages.RemovePage(PageDialog)
})
nsList, err := pv.getSortedNsList()
if err != nil {
log.Err(err).Msg("failed to get sorted ns list")
}
maxLblLen := len(selectAllNsLbl)
const scList = "123456789abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
for i, ns := range nsList {
nsToAdd := ns
selectNsLbl := "Select " + ns
r := '0'
if i < len(scList) {
r = rune(scList[i])
}
list.AddItem(ns, selectNsLbl, r, func() {
pv.setSelectedNs(nsToAdd)
pv.pages.RemovePage(PageDialog)
})
if len(selectNsLbl) > maxLblLen {
maxLblLen = len(selectNsLbl)
}
}
list.AddItem("Cancel", "Select to close", 'x', func() {
pv.pages.RemovePage(PageDialog)
})
list.SetBorder(true).SetTitle("Namespaces")

flex := tview.NewFlex().
AddItem(nil, 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(list, (len(nsList)+3)*2, 1, true), maxLblLen+10, 1, true).
AddItem(nil, 0, 1, false)
return flex
}

func (pv *pcView) getSortedNsList() ([]string, error) {
states, err := pv.project.GetProcessesState()
if err != nil {
log.Err(err).Msg("failed to get processes state")
return []string{}, err
}
nsList := make(map[string]struct{})
for _, state := range states.States {
nsList[state.Namespace] = struct{}{}
}
var nsListSorted []string
for ns := range nsList {
nsListSorted = append(nsListSorted, ns)
}
slices.Sort(nsListSorted)
return nsListSorted, nil
}

func (pv *pcView) isNsSelected(ns string) bool {
pv.selectedNsMtx.Lock()
defer pv.selectedNsMtx.Unlock()
if pv.selectedNs == AllNS || pv.selectedNs == ns {
return true
}

return false
}

func (pv *pcView) setSelectedNs(ns string) {
pv.selectedNsMtx.Lock()
defer pv.selectedNsMtx.Unlock()
pv.selectedNsChanged.Store(pv.selectedNs != ns)
pv.selectedNs = ns
}

func (pv *pcView) getSelectedNs() string {
pv.selectedNsMtx.Lock()
defer pv.selectedNsMtx.Unlock()
return pv.selectedNs
}
39 changes: 27 additions & 12 deletions src/tui/proc-table.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,44 @@ func (pv *pcView) fillTableData() {
log.Err(err).Msg("failed to sort states")
return
}
for r, state := range states.States {
row := 1
for _, state := range states.States {
if !pv.isNsSelected(state.Namespace) {
pv.procTable.RemoveRow(row)
continue
}
icon, color := getIconForState(state)
pv.procTable.SetCell(r+1, int(ProcessStateIcon), tview.NewTableCell(icon).SetAlign(tview.AlignCenter).SetExpansion(0).SetTextColor(color))
pv.procTable.SetCell(r+1, int(ProcessStatePid), tview.NewTableCell(strconv.Itoa(state.Pid)).SetAlign(tview.AlignRight).SetExpansion(0).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateName), tview.NewTableCell(state.Name).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateNamespace), tview.NewTableCell(state.Namespace).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateStatus), tview.NewTableCell(state.Status).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateAge), tview.NewTableCell(state.SystemTime).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateHealth), tview.NewTableCell(state.Health).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateRestarts), tview.NewTableCell(strconv.Itoa(state.Restarts)).SetAlign(tview.AlignRight).SetExpansion(0).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(r+1, int(ProcessStateExit), tview.NewTableCell(strconv.Itoa(state.ExitCode)).SetAlign(tview.AlignRight).SetExpansion(0).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateIcon), tview.NewTableCell(icon).SetAlign(tview.AlignCenter).SetExpansion(0).SetTextColor(color))
pv.procTable.SetCell(row, int(ProcessStatePid), tview.NewTableCell(strconv.Itoa(state.Pid)).SetAlign(tview.AlignRight).SetExpansion(0).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateName), tview.NewTableCell(state.Name).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateNamespace), tview.NewTableCell(state.Namespace).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateStatus), tview.NewTableCell(state.Status).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateAge), tview.NewTableCell(state.SystemTime).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateHealth), tview.NewTableCell(state.Health).SetAlign(tview.AlignLeft).SetExpansion(1).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateRestarts), tview.NewTableCell(strconv.Itoa(state.Restarts)).SetAlign(tview.AlignRight).SetExpansion(0).SetTextColor(tcell.ColorLightSkyBlue))
pv.procTable.SetCell(row, int(ProcessStateExit), tview.NewTableCell(strconv.Itoa(state.ExitCode)).SetAlign(tview.AlignRight).SetExpansion(0).SetTextColor(tcell.ColorLightSkyBlue))
if state.IsRunning {
runningProcCount += 1
}
row += 1
}

// remove unnecessary rows, don't forget the title row (-1)
if pv.procTable.GetRowCount()-1 > len(states.States) {
if pv.procTable.GetRowCount()-1 > row {
for i := len(states.States); i < pv.procTable.GetRowCount()-1; i++ {
pv.procTable.RemoveRow(i)
}
}
if pv.selectedNsChanged.Swap(false) {
pv.procTable.Select(1, 1)
}

if pv.procCountCell != nil {
pv.procCountCell.SetText(fmt.Sprintf("%d/%d", runningProcCount, len(pv.procNames)))
nsLbl := ""
if !pv.isNsSelected(AllNS) {
nsLbl = " (" + pv.getSelectedNs() + ")"
}
pv.procCountCell.SetText(fmt.Sprintf("%d/%d%s", runningProcCount, len(pv.procNames), nsLbl))
}
}

Expand Down
58 changes: 33 additions & 25 deletions src/tui/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"os/signal"
"strconv"
"sync"
"sync/atomic"
"syscall"
"time"

Expand All @@ -30,37 +31,41 @@ const (
const (
PageMain = "main"
PageDialog = "dialog"
AllNS = "PC_ALL_NS_FILTER"
)

const shutDownAfterSec = 10

var pcv *pcView = nil

type pcView struct {
procTable *tview.Table
statTable *tview.Table
appView *tview.Application
logsText *LogView
statusText *tview.TextView
helpText *tview.TextView
pages *tview.Pages
procNames []string
logFollow bool
logSelect bool
fullScrState FullScrState
loggedProc string
shortcuts ShortCuts
procCountCell *tview.TableCell
mainGrid *tview.Grid
logsTextArea *tview.TextArea
project app.IProject
sortMtx sync.Mutex
stateSorter StateSorter
procColumns map[ColumnID]string
refreshRate time.Duration
cancelFn context.CancelFunc
cancelLogFn context.CancelFunc
cancelSigFn context.CancelFunc
procTable *tview.Table
statTable *tview.Table
appView *tview.Application
logsText *LogView
statusText *tview.TextView
helpText *tview.TextView
pages *tview.Pages
procNames []string
logFollow bool
logSelect bool
fullScrState FullScrState
loggedProc string
shortcuts ShortCuts
procCountCell *tview.TableCell
mainGrid *tview.Grid
logsTextArea *tview.TextArea
project app.IProject
sortMtx sync.Mutex
stateSorter StateSorter
procColumns map[ColumnID]string
refreshRate time.Duration
cancelFn context.CancelFunc
cancelLogFn context.CancelFunc
cancelSigFn context.CancelFunc
selectedNsMtx sync.Mutex
selectedNs string
selectedNsChanged atomic.Bool
}

func newPcView(project app.IProject) *pcView {
Expand All @@ -85,6 +90,7 @@ func newPcView(project app.IProject) *pcView {
isAsc: true,
},
procColumns: map[ColumnID]string{},
selectedNs: AllNS,
}
pv.statTable = pv.createStatTable()
go pv.loadProcNames()
Expand Down Expand Up @@ -174,7 +180,8 @@ func (pv *pcView) onAppKey(event *tcell.EventKey) *tcell.EventKey {
pv.logsText.SetTitle(pv.getLogTitle(pv.getSelectedProcName()))
case pv.shortcuts.ShortCutKeys[ActionLogFindExit].key:
pv.exitSearch()

case pv.shortcuts.ShortCutKeys[ActionNsFilter].key:
pv.showNsFilter()
default:
return event
}
Expand Down Expand Up @@ -343,6 +350,7 @@ func (pv *pcView) updateHelpTextView() {
pv.shortcuts.ShortCutKeys[ActionProcessScreen].writeToggleButton(pv.helpText, procScrBool)
pv.shortcuts.ShortCutKeys[ActionProcessStop].writeButton(pv.helpText)
pv.shortcuts.ShortCutKeys[ActionProcessRestart].writeButton(pv.helpText)
pv.shortcuts.ShortCutKeys[ActionNsFilter].writeButton(pv.helpText)
pv.shortcuts.ShortCutKeys[ActionQuit].writeButton(pv.helpText)
}

Expand Down

0 comments on commit f6f31e8

Please sign in to comment.