Skip to content
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
211 changes: 67 additions & 144 deletions rocketpool-cli/service/config/config-form.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,42 @@ type parameterizedFormItem struct {
item tview.FormItem
}

func (pfi *parameterizedFormItem) commit() {
switch pfi.item.(type) {
case *tview.Checkbox:
pfi.parameter.Value = pfi.item.(*tview.Checkbox).IsChecked()
case *tview.InputField:
var err error
inputField := pfi.item.(*tview.InputField)
switch pfi.parameter.Type {
case cfgtypes.ParameterType_Int:
pfi.parameter.Value, err = strconv.ParseInt(inputField.GetText(), 0, 0)
if err != nil {
// TODO: show error modal?
inputField.SetText("")
}
case cfgtypes.ParameterType_Uint:
pfi.parameter.Value, err = strconv.ParseUint(inputField.GetText(), 0, 0)
if err != nil {
// TODO: show error modal?
inputField.SetText("")
}
case cfgtypes.ParameterType_Uint16:
pfi.parameter.Value, err = strconv.ParseUint(inputField.GetText(), 0, 16)
if err != nil {
// TODO: show error modal?
inputField.SetText("")
}
case cfgtypes.ParameterType_String, cfgtypes.ParameterType_Float:
pfi.parameter.Value = strings.TrimSpace(inputField.GetText())
default:
panic(fmt.Sprintf("Unknown parameter type for text field %v", pfi.parameter.Type))
}
default:
panic(fmt.Sprintf("Unknown form item type %v", pfi.item))
}
}

// Create a list of form items based on a set of parameters
func createParameterizedFormItems(params []*cfgtypes.Parameter, descriptionBox *tview.TextView) []*parameterizedFormItem {
formItems := []*parameterizedFormItem{}
Expand All @@ -25,18 +61,12 @@ func createParameterizedFormItems(params []*cfgtypes.Parameter, descriptionBox *
switch param.Type {
case cfgtypes.ParameterType_Bool:
item = createParameterizedCheckbox(param)
case cfgtypes.ParameterType_Int:
case cfgtypes.ParameterType_Int, cfgtypes.ParameterType_Uint, cfgtypes.ParameterType_Uint16:
item = createParameterizedIntField(param)
case cfgtypes.ParameterType_Uint:
item = createParameterizedUintField(param)
case cfgtypes.ParameterType_Uint16:
item = createParameterizedUint16Field(param)
case cfgtypes.ParameterType_String:
case cfgtypes.ParameterType_String, cfgtypes.ParameterType_Float:
item = createParameterizedStringField(param)
case cfgtypes.ParameterType_Choice:
item = createParameterizedDropDown(param, descriptionBox)
case cfgtypes.ParameterType_Float:
item = createParameterizedStringField(param)
default:
panic(fmt.Sprintf("Unknown parameter type %v", param))
}
Expand All @@ -50,142 +80,56 @@ func createParameterizedFormItems(params []*cfgtypes.Parameter, descriptionBox *
func createParameterizedCheckbox(param *cfgtypes.Parameter) *parameterizedFormItem {
item := tview.NewCheckbox().
SetLabel(param.Name).
SetChecked(param.Value == true).
SetChangedFunc(func(checked bool) {
param.Value = checked
})
item.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
default:
return event
}
})

return &parameterizedFormItem{
SetChecked(param.Value == true)
out := &parameterizedFormItem{
parameter: param,
item: item,
}
}

// Create a standard int field
func createParameterizedIntField(param *cfgtypes.Parameter) *parameterizedFormItem {
item := tview.NewInputField().
SetLabel(param.Name).
SetAcceptanceFunc(tview.InputFieldInteger)
item.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEscape {
item.SetText("")
} else {
value, err := strconv.ParseInt(item.GetText(), 0, 0)
if err != nil {
// TODO: show error modal?
item.SetText("")
} else {
param.Value = int(value)
}
}
})
item.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
default:
return event
}
item.SetInputCapture(navCapture)
item.SetChangedFunc(func(checked bool) {
out.commit()
})

return &parameterizedFormItem{
parameter: param,
item: item,
return out
}

func navCapture(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
}
return event
}

// Create a standard uint field
func createParameterizedUintField(param *cfgtypes.Parameter) *parameterizedFormItem {
// Create a standard int field
func createParameterizedIntField(param *cfgtypes.Parameter) *parameterizedFormItem {
item := tview.NewInputField().
SetLabel(param.Name).
SetAcceptanceFunc(tview.InputFieldInteger)
item.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEscape {
item.SetText("")
} else {
value, err := strconv.ParseUint(item.GetText(), 0, 0)
if err != nil {
// TODO: show error modal?
item.SetText("")
} else {
param.Value = int(value)
}
}
})
item.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
default:
return event
}
})

return &parameterizedFormItem{
out := &parameterizedFormItem{
parameter: param,
item: item,
}
}

// Create a standard uint16 field
func createParameterizedUint16Field(param *cfgtypes.Parameter) *parameterizedFormItem {
item := tview.NewInputField().
SetLabel(param.Name).
SetAcceptanceFunc(tview.InputFieldInteger)
item.SetInputCapture(navCapture)
item.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEscape {
item.SetText("")
} else {
value, err := strconv.ParseUint(item.GetText(), 0, 16)
if err != nil {
// TODO: show error modal?
item.SetText("")
} else {
param.Value = int(value)
}
}
})
item.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
default:
return event
}
out.commit()
})

return &parameterizedFormItem{
parameter: param,
item: item,
}
return out
}

// Create a standard string field
func createParameterizedStringField(param *cfgtypes.Parameter) *parameterizedFormItem {
item := tview.NewInputField().
SetLabel(param.Name)
out := &parameterizedFormItem{
parameter: param,
item: item,
}
item.SetDoneFunc(func(key tcell.Key) {
if key == tcell.KeyEscape {
item.SetText("")
} else {
param.Value = strings.TrimSpace(item.GetText())
}
out.commit()
})
item.SetAcceptanceFunc(func(textToCheck string, lastChar rune) bool {
if param.MaxLength > 0 {
Expand All @@ -196,21 +140,9 @@ func createParameterizedStringField(param *cfgtypes.Parameter) *parameterizedFor
// TODO: regex support
return true
})
item.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
default:
return event
}
})
item.SetInputCapture(navCapture)

return &parameterizedFormItem{
parameter: param,
item: item,
}
return out
}

// Create a standard choice field
Expand All @@ -233,16 +165,7 @@ func createParameterizedDropDown(param *cfgtypes.Parameter, descriptionBox *tvie
descriptionBox.SetText(descriptions[index])
})
item.SetTextOptions(" ", " ", "", "", "")
item.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyDown, tcell.KeyTab:
return tcell.NewEventKey(tcell.KeyTab, 0, 0)
case tcell.KeyUp, tcell.KeyBacktab:
return tcell.NewEventKey(tcell.KeyBacktab, 0, 0)
default:
return event
}
})
item.SetInputCapture(navCapture)
list := item.GetList()
list.SetSelectedBackgroundColor(tcell.Color46)
list.SetSelectedTextColor(tcell.ColorBlack)
Expand Down
12 changes: 6 additions & 6 deletions rocketpool-cli/service/config/settings-metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ func (configPage *MetricsConfigPage) createContent() {
// Set up the form items
configPage.enableMetricsBox = createParameterizedCheckbox(&configPage.masterConfig.EnableMetrics)
configPage.enableOdaoMetricsBox = createParameterizedCheckbox(&configPage.masterConfig.EnableODaoMetrics)
configPage.ecMetricsPortBox = createParameterizedUint16Field(&configPage.masterConfig.EcMetricsPort)
configPage.bnMetricsPortBox = createParameterizedUint16Field(&configPage.masterConfig.BnMetricsPort)
configPage.vcMetricsPortBox = createParameterizedUint16Field(&configPage.masterConfig.VcMetricsPort)
configPage.nodeMetricsPortBox = createParameterizedUint16Field(&configPage.masterConfig.NodeMetricsPort)
configPage.exporterMetricsPortBox = createParameterizedUint16Field(&configPage.masterConfig.ExporterMetricsPort)
configPage.watchtowerMetricsPortBox = createParameterizedUint16Field(&configPage.masterConfig.WatchtowerMetricsPort)
configPage.ecMetricsPortBox = createParameterizedIntField(&configPage.masterConfig.EcMetricsPort)
configPage.bnMetricsPortBox = createParameterizedIntField(&configPage.masterConfig.BnMetricsPort)
configPage.vcMetricsPortBox = createParameterizedIntField(&configPage.masterConfig.VcMetricsPort)
configPage.nodeMetricsPortBox = createParameterizedIntField(&configPage.masterConfig.NodeMetricsPort)
configPage.exporterMetricsPortBox = createParameterizedIntField(&configPage.masterConfig.ExporterMetricsPort)
configPage.watchtowerMetricsPortBox = createParameterizedIntField(&configPage.masterConfig.WatchtowerMetricsPort)
configPage.grafanaItems = createParameterizedFormItems(configPage.masterConfig.Grafana.GetParameters(), configPage.layout.descriptionBox)
configPage.prometheusItems = createParameterizedFormItems(configPage.masterConfig.Prometheus.GetParameters(), configPage.layout.descriptionBox)
configPage.exporterItems = createParameterizedFormItems(configPage.masterConfig.Exporter.GetParameters(), configPage.layout.descriptionBox)
Expand Down
20 changes: 1 addition & 19 deletions rocketpool-cli/service/config/settings-smartnode.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package config

import (
"github.com/gdamore/tcell/v2"

"github.com/rocket-pool/smartnode/shared/services/config"
cfgtypes "github.com/rocket-pool/smartnode/shared/types/config"
)
Expand Down Expand Up @@ -49,23 +47,7 @@ func (configPage *SmartnodeConfigPage) createContent() {
layout.createForm(&masterConfig.Smartnode.Network, "Smart Node and TX Fee Settings")

// Return to the home page after pressing Escape
layout.form.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEsc {
// Close all dropdowns and break if one was open
for _, param := range configPage.layout.parameters {
dropDown, ok := param.item.(*DropDown)
if ok && dropDown.open {
dropDown.CloseList(configPage.home.md.app)
return nil
}
}

// Return to the home page
configPage.home.md.setPage(configPage.home.homePage)
return nil
}
return event
})
layout.form.SetInputCapture(layout.getInputCapture(configPage.home.md, configPage.home.homePage))

// Set up the form items
params := append(masterConfig.Smartnode.GetParameters(), &masterConfig.EnableIPv6, &masterConfig.Alertmanager.ShowAlertsOnCLI)
Expand Down
33 changes: 25 additions & 8 deletions rocketpool-cli/service/config/standard-layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,22 +210,39 @@ func (layout *standardLayout) mapParameterizedFormItems(params ...*parameterized
}
}

// Sets up a handler to return to the specified homePage when the user presses escape on the layout.
func (layout *standardLayout) setupEscapeReturnHomeHandler(md *MainDisplay, homePage *page) {
layout.grid.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
// Return to the home page
func (layout *standardLayout) getInputCapture(md *MainDisplay, prev *page) func(event *tcell.EventKey) *tcell.EventKey {
return func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEsc {
// Close all dropdowns and break if one was open
// Save the current modifications to text parameters
for _, param := range layout.parameters {
dropDown, ok := param.item.(*DropDown)
if ok && dropDown.open {
formItem := param.item
if !formItem.HasFocus() {
continue
}

// Close the dropdown if this field is one and it is open
if dropDown, ok := param.item.(*DropDown); ok && dropDown.open {
dropDown.CloseList(md.app)
return nil
}

// Save the text if this field is one
if _, ok := param.item.(*tview.InputField); ok {
param.commit()
// Exit the loop to return to the home page
break
}
}
md.setPage(homePage)

md.setPage(prev)
return nil
}
return event
})
}
}

// Sets up a handler to return to the specified homePage when the user presses escape on the layout.
func (layout *standardLayout) setupEscapeReturnHomeHandler(md *MainDisplay, homePage *page) {
layout.grid.SetInputCapture(layout.getInputCapture(md, homePage))
}
Loading