You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

172 lines
4.1 KiB
Go

package tui
import (
"fmt"
"log"
"strconv"
"time"
"github.com/rivo/tview"
_ "github.com/gdamore/tcell/v2"
)
// gonna start from scratch :/
type TUI struct {
*Display
*LocalView
*TUIClient
SelectedReactor <-chan uint32
Err chan error
}
func NewTUI(ip string, port int, ch chan error) *TUI {
r := make(map[uint32]*Reactor)
t := &TUI{}
l := new(LocalView)
l.Reactors = r
t.LocalView = l
c := make(chan uint32)
t.Display = NewDisplay(c)
t.SelectedReactor = c
t.Err = ch
client := NewTUIClient(ip, port)
t.TUIClient = client
return t
}
func (t *TUI) Start() {
// setup tview app and wait for user connection in standin modal
t.Display.Start()
t.Connect()
go t.Monitor()
go t.Listen()
//go t.Refresh()
}
func (t *TUI) Refresh() {
for {
//
}
}
func (t *TUI) Listen() {
for {
select {
case <-t.SelectedReactor:
//blah
}
}
}
func (t *TUI) Monitor() {
// orchestrates updates and grpc requests
timer := make(chan struct{})
go func(signal chan struct{}){
for {
signal <- struct{}{}
time.Sleep(1 * time.Second)
}
}(timer)
for {
select {
case reactor := <-t.SelectedReactor:
// reactor has been selected in tui, grabbing devs
go t.UpdateDevices(reactor)
//devs := t.GetReactorDevices(reactor)
//t.DisplayReactorDevices(devs)
case <-timer:
// time to ping for status
go t.UpdateReactors()
}
}
}
func (t *TUI) UpdateDevices(r uint32) {
// get devices for the reactor and update the tui
devs, err := t.TUIClient.GetReactorDevices(r)
if err != nil {
log.Fatal(err)
}
for a, d := range devs {
go t.LocalView.UpdateReactorDevices(r,a,d)
}
t.DisplayReactorDevices(devs)
}
func (t *TUI) UpdateReactors() {
// get all reactors and update the tui
reactors, err := t.TUIClient.GetReactors()
if err != nil {
log.Fatal(err)
}
for id, r := range reactors {
go t.LocalView.UpdateReactors(id, r)
}
t.DisplayReactors(reactors)
}
// display struct and logic
type Display struct {
App *tview.Application
Flex *tview.Flex
ReactorList *tview.List
DeviceList *tview.List
SelectedReactor chan<- uint32
}
func NewDisplay(ch chan uint32) *Display {
d := &Display{}
d.App = tview.NewApplication()
d.Flex = tview.NewFlex()
d.ReactorList = tview.NewList().ShowSecondaryText(false)
d.DeviceList = tview.NewList().ShowSecondaryText(false)
d.SelectedReactor = ch
d.ReactorList.SetSelectedFunc(d.SelectReactor)
return d
}
func (d *Display) Start() {
d.Flex.AddItem(d.ReactorList.SetBorder(true).SetTitle("Reactors"),0,1,true)
d.Flex.AddItem(d.DeviceList.SetBorder(true).SetTitle("Devices"),0,3,false)
if err := d.App.SetRoot(d.Flex, true).Run(); err != nil {
log.Fatal(err)
}
}
func (d *Display) DisplayReactors(r map[uint32]*Reactor) {
// function to display reactor list to table
for id, reactor := range r {
var status string
if reactor.Status {
status = "[green]ONLINE"
} else {
status = "[red]OFFLINE"
}
txt := fmt.Sprintf("Reactor %v is %v", id, status)
d.ReactorList.AddItem(txt,string(id),0,nil)
}
}
func (d *Display) SelectReactor(index int, main, id string, r rune) {
// called when reactor in list in selected
if id, err := strconv.Atoi(id); err != nil {
log.Fatal(err)
} else {
d.SelectedReactor <-uint32(id)
}
}
func (d *Display) DisplayReactorDevices(devs map[int]*Device) {
//Function that displays devices to the table
d.DeviceList.Clear()
for addr, dev := range devs {
var status string
if dev.Status == "ACTIVE" {
status = "[green]ACTIVE[white]"
} else if dev.Status == "KILLED" {
status = "[red]KILLED[white]"
}
txt := fmt.Sprintf("%v is %v at %x",dev.Type,status,addr)
d.DeviceList.AddItem(txt,"",0,nil)
}
}