From 068b7c008d932bb935346874d817e5e39fb2a4e6 Mon Sep 17 00:00:00 2001 From: Navid Yaghoobi Date: Sun, 26 Nov 2023 01:44:27 +1100 Subject: [PATCH] running golangci-lint on ui/system package Signed-off-by: Navid Yaghoobi --- .golangci.yml | 3 +- ui/system/command.go | 77 ++++++++++++++++++------ ui/system/data.go | 8 ++- ui/system/draw.go | 20 ++++++- ui/system/key.go | 14 ++++- ui/system/refresh.go | 11 ++-- ui/system/sysdialogs/add.go | 62 ++++++++++++++------ ui/system/sysdialogs/connect.go | 47 +++++++++------ ui/system/sysdialogs/df.go | 52 +++++++++------- ui/system/sysdialogs/event.go | 44 +++++++++----- ui/system/system.go | 101 ++++++++++++++++++++++---------- 11 files changed, 308 insertions(+), 131 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 900bb9eeb..7e602850e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,7 +8,6 @@ run: - ui/images - ui/networks - ui/pods - - ui/system linters: enable-all: true disable: @@ -35,6 +34,8 @@ linters: - exhaustivestruct - gomoddirectives linters-settings: +# typecheck: +# enabled: false errcheck: check-blank: false ignore: fmt:.* diff --git a/ui/system/command.go b/ui/system/command.go index c4a00739b..42ed94fd3 100644 --- a/ui/system/command.go +++ b/ui/system/command.go @@ -25,7 +25,7 @@ func (sys *System) runCommand(cmd string) { sys.events() case "info": sys.info() - case "prune": + case "prune": //nolint:goconst sys.cprune() case "remove connection": sys.cremove() @@ -46,28 +46,33 @@ func (sys *System) addConnection() { name, uri, identity := sys.connAddDialog.GetItems() sys.progressDialog.SetTitle("adding new connection") sys.progressDialog.Display() + go func() { err := sys.connectionAddFunc(name, uri, identity) sys.progressDialog.Hide() sys.UpdateConnectionsData() + if err != nil { sys.displayError("ADD NEW CONNECTION ERROR", err) + return } }() } func (sys *System) connect() { - connName, _, connURI, connIdentity := sys.getSelectedItem() + selectedItem := sys.getSelectedItem() // empty table - if connName == "" { + if selectedItem.name == "" { return } + dest := registry.Connection{ - Name: connName, - URI: connURI, - Identity: connIdentity, + Name: selectedItem.name, + URI: selectedItem.uri, + Identity: selectedItem.identity, } + sys.eventDialog.SetText("") sys.connectionConnectFunc(dest) sys.UpdateConnectionsData() @@ -83,20 +88,27 @@ func (sys *System) df() { if !sys.destIsSet() { return } + sys.progressDialog.SetTitle("podman disk usage in progress") sys.progressDialog.Display() + diskUsage := func() { response, err := sysinfo.DiskUsage() + sys.progressDialog.Hide() + if err != nil { sys.displayError("SYSTEM DISK USAGE ERROR", err) + return } + connName := registry.ConnectionName() sys.dfDialog.SetServiceName(connName) sys.dfDialog.UpdateDiskSummary(response) sys.dfDialog.Display() } + go diskUsage() } @@ -104,6 +116,7 @@ func (sys *System) events() { if !sys.destIsSet() { return } + connName := registry.ConnectionName() sys.eventDialog.SetServiceName(connName) sys.eventDialog.Display() @@ -113,9 +126,11 @@ func (sys *System) info() { if !sys.destIsSet() { return } + data, err := sysinfo.Info() if err != nil { sys.displayError("SYSTEM INFO ERROR", err) + return } @@ -130,10 +145,14 @@ func (sys *System) cprune() { if !sys.destIsSet() { return } + connName := registry.ConnectionName() + sys.confirmDialog.SetTitle("podman system prune") sys.confirmData = "prune" - confirmMsg := fmt.Sprintf("Are you sure you want to remove all unused pod, container, image and volume data on %s?", connName) + confirmMsg := fmt.Sprintf( + "Are you sure you want to remove all unused pod, container, image and volume data on %s?", + connName) sys.confirmDialog.SetText(confirmMsg) sys.confirmDialog.Display() } @@ -141,35 +160,46 @@ func (sys *System) cprune() { func (sys *System) prune() { sys.progressDialog.SetTitle("system purne in progress") sys.progressDialog.Display() + prune := func() { report, err := sysinfo.Prune() + sys.progressDialog.Hide() + if err != nil { sys.displayError("SYSTEM PRUNE ERROR", err) + return } + sys.messageDialog.SetTitle("PODMAN SYSTEM PRUNE") sys.messageDialog.SetText(dialogs.MessageSystemInfo, registry.ConnectionName(), report) sys.messageDialog.Display() } + go prune() } func (sys *System) cremove() { - connName, status, _, _ := sys.getSelectedItem() - if status != "" { - sys.displayError("SYSTEM CONNECTION REMOVE", fmt.Errorf("%q connection in progress, need to disconnect", connName)) + selectedItem := sys.getSelectedItem() + if selectedItem.status != "" { + sys.displayError( + "SYSTEM CONNECTION REMOVE", + fmt.Errorf("%w %q", ErrConnectionInprogres, selectedItem.name)) + return } - if connName == "" { + + if selectedItem.name == "" { return } + title := "podman system connection remove" sys.confirmDialog.SetTitle(title) sys.confirmData = "remove_conn" bgColor := style.GetColorHex(style.DialogBorderColor) fgColor := style.GetColorHex(style.DialogFgColor) - serviceItem := fmt.Sprintf("[%s:%s:b]SERVICE NAME:[:-:-] %s", fgColor, bgColor, connName) + serviceItem := fmt.Sprintf("[%s:%s:b]SERVICE NAME:[:-:-] %s", fgColor, bgColor, selectedItem.name) confirmMsg := fmt.Sprintf("%s\n\nAre you sure you want to remove the selected service connection ?", serviceItem) sys.confirmDialog.SetText(confirmMsg) @@ -177,28 +207,39 @@ func (sys *System) cremove() { } func (sys *System) remove() { - connName, _, _, _ := sys.getSelectedItem() + selectedItem := sys.getSelectedItem() sys.progressDialog.SetTitle("removing connection") sys.progressDialog.Display() + go func() { - sys.connectionRemoveFunc(connName) + err := sys.connectionRemoveFunc(selectedItem.name) sys.progressDialog.Hide() + + if err != nil { + sys.displayError("SYSTEM CONNECTION REMOVE ERROR", err) + + return + } + sys.UpdateConnectionsData() }() - } func (sys *System) setDefault() { - connName, _, _, _ := sys.getSelectedItem() + selectedItem := sys.getSelectedItem() setDefFunc := func() { sys.progressDialog.Hide() - if err := sys.connectionSetDefaultFunc(connName); err != nil { + + if err := sys.connectionSetDefaultFunc(selectedItem.name); err != nil { sys.displayError("SYSTEM CONNECTION SET DEFAULT ERROR", err) + return } } + sys.progressDialog.Display() + go setDefFunc() } @@ -206,7 +247,9 @@ func (sys *System) destIsSet() bool { if !registry.ConnectionIsSet() { sys.errorDialog.SetText("not connected to any podman service") sys.errorDialog.Display() + return false } + return true } diff --git a/ui/system/data.go b/ui/system/data.go index 3f6bbad71..d52cf8384 100644 --- a/ui/system/data.go +++ b/ui/system/data.go @@ -7,7 +7,7 @@ import ( "github.com/containers/podman-tui/ui/style" ) -// UpdateConnectionsData retrieves connections list data +// UpdateConnectionsData retrieves connections list data. func (sys *System) UpdateConnectionsData() { destinations := sys.connectionListFunc() sys.connectionList.mu.Lock() @@ -19,11 +19,14 @@ func (sys *System) UpdateConnectionsData() { func (sys *System) udpateConnectionDataStatus() { sys.connectionList.mu.Lock() defer sys.connectionList.mu.Unlock() + name := registry.ConnectionName() status := registry.ConnectionStatus() + for i := 0; i < len(sys.connectionList.report); i++ { if sys.connectionList.report[i].Name == name { sys.connectionList.report[i].Status = status + return } } @@ -33,6 +36,7 @@ func (sys *System) getConnectionsData() []registry.Connection { sys.connectionList.mu.Lock() destReport := sys.connectionList.report sys.connectionList.mu.Unlock() + return destReport } @@ -42,11 +46,13 @@ type connectionItemStatus struct { func (connStatus connectionItemStatus) StatusString() string { var status string + switch connStatus.status { case registry.ConnectionStatusConnected: status = fmt.Sprintf("%s %s", style.HeavyGreenCheckMark, "connected") case registry.ConnectionStatusConnectionError: status = fmt.Sprintf("%s %s", style.HeavyRedCrossMark, "connection error") } + return status } diff --git a/ui/system/draw.go b/ui/system/draw.go index c0927cb58..d6f709793 100644 --- a/ui/system/draw.go +++ b/ui/system/draw.go @@ -8,51 +8,67 @@ import ( func (sys *System) Draw(screen tcell.Screen) { sys.refresh() sys.Box.DrawForSubclass(screen, sys) + x, y, width, height := sys.GetInnerRect() + sys.connTable.SetRect(x, y, width, height) sys.connTable.Draw(screen) x, y, width, height = sys.connTable.GetInnerRect() + // error dialog if sys.errorDialog.IsDisplay() { sys.errorDialog.SetRect(x, y, width, height) sys.errorDialog.Draw(screen) + return } + // connection progress dialog if sys.connPrgDialog.IsDisplay() { sys.connPrgDialog.SetRect(x, y, width, height) sys.connPrgDialog.Draw(screen) + return } - // command dialog dialog + + // command dialog if sys.cmdDialog.IsDisplay() { sys.cmdDialog.SetRect(x, y, width, height) sys.cmdDialog.Draw(screen) + return } + // confirm dialog if sys.confirmDialog.IsDisplay() { sys.confirmDialog.SetRect(x, y, width, height) sys.confirmDialog.Draw(screen) + return } + // message dialog if sys.messageDialog.IsDisplay() { sys.messageDialog.SetRect(x, y, width, height) sys.messageDialog.Draw(screen) + return } + // disk usage dialog if sys.dfDialog.IsDisplay() { sys.dfDialog.SetRect(x, y, width, height) sys.dfDialog.Draw(screen) + return } + // progress dialog if sys.progressDialog.IsDisplay() { sys.progressDialog.SetRect(x, y, width, height) sys.progressDialog.Draw(screen) + return } @@ -60,8 +76,10 @@ func (sys *System) Draw(screen tcell.Screen) { if sys.connAddDialog.IsDisplay() { sys.connAddDialog.SetRect(x, y, width, height) sys.connAddDialog.Draw(screen) + return } + // event dialog if sys.eventDialog.IsDisplay() { sys.eventDialog.SetRect(x, y, width, height) diff --git a/ui/system/key.go b/ui/system/key.go index 3776b4304..786fe6e2b 100644 --- a/ui/system/key.go +++ b/ui/system/key.go @@ -8,42 +8,49 @@ import ( ) // InputHandler returns the handler for this primitive. -func (sys *System) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { +func (sys *System) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:gocognit,cyclop,lll return sys.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { log.Debug().Msgf("view: system event %v received", event) + if sys.progressDialog.IsDisplay() { return } + // command dialog handler if sys.cmdDialog.HasFocus() { if cmdHandler := sys.cmdDialog.InputHandler(); cmdHandler != nil { cmdHandler(event, setFocus) } } + // confirm dialog handler if sys.confirmDialog.HasFocus() { if confirmDialogHandler := sys.confirmDialog.InputHandler(); confirmDialogHandler != nil { confirmDialogHandler(event, setFocus) } } + // message dialog handler if sys.messageDialog.HasFocus() { if messageDialogHandler := sys.messageDialog.InputHandler(); messageDialogHandler != nil { messageDialogHandler(event, setFocus) } } + // disk usage dialog if sys.dfDialog.HasFocus() { if dfDialogHandler := sys.dfDialog.InputHandler(); dfDialogHandler != nil { dfDialogHandler(event, setFocus) } } + // error dialog handler if sys.errorDialog.HasFocus() { if errorDialogHandler := sys.errorDialog.InputHandler(); errorDialogHandler != nil { errorDialogHandler(event, setFocus) } } + // connection progress dialog handler if sys.connPrgDialog.HasFocus() { if connectionPrgDialog := sys.connPrgDialog.InputHandler(); connectionPrgDialog != nil { @@ -66,8 +73,8 @@ func (sys *System) InputHandler() func(event *tcell.EventKey, setFocus func(p tv } // table handlers - if sys.connTable.HasFocus() { - if event.Rune() == utils.CommandMenuKey.Rune() { + if sys.connTable.HasFocus() { //nolint:nestif + if event.Rune() == utils.CommandMenuKey.Rune() { //nolint:gocritic sys.cmdDialog.Display() } else if event.Key() == utils.DeleteKey.EventKey() { sys.cremove() @@ -77,6 +84,7 @@ func (sys *System) InputHandler() func(event *tcell.EventKey, setFocus func(p tv } } } + setFocus(sys) }) } diff --git a/ui/system/refresh.go b/ui/system/refresh.go index f978fac0e..12683716e 100644 --- a/ui/system/refresh.go +++ b/ui/system/refresh.go @@ -9,10 +9,10 @@ import ( ) func (sys *System) refresh() { - connections := sys.getConnectionsData() sys.connTable.Clear() sys.updateConnTableTitle(len(connections)) + expand := 1 alignment := tview.AlignLeft defaultAlignment := tview.AlignCenter @@ -22,6 +22,7 @@ func (sys *System) refresh() { if sys.connTableHeaders[i] == "default" { headerAlignment = defaultAlignment } + header := fmt.Sprintf("[::b]%s", strings.ToUpper(sys.connTableHeaders[i])) sys.connTable.SetCell(0, i, tview.NewTableCell(header). @@ -31,12 +32,14 @@ func (sys *System) refresh() { SetAlign(headerAlignment). SetSelectable(false)) } + rowIndex := 1 for i := 0; i < len(connections); i++ { isDefault := "" conn := connections[i] status := connectionItemStatus{conn.Status}.StatusString() + if conn.Default { isDefault = style.HeavyGreenCheckMark } @@ -54,19 +57,19 @@ func (sys *System) refresh() { SetAlign(defaultAlignment)) // status column - sys.connTable.SetCell(rowIndex, 2, + sys.connTable.SetCell(rowIndex, 2, //nolint:gomnd tview.NewTableCell(status). SetExpansion(expand). SetAlign(alignment)) // uri column - sys.connTable.SetCell(rowIndex, 3, + sys.connTable.SetCell(rowIndex, 3, //nolint:gomnd tview.NewTableCell(conn.URI). SetExpansion(expand). SetAlign(alignment)) // identity column - sys.connTable.SetCell(rowIndex, 4, + sys.connTable.SetCell(rowIndex, 4, //nolint:gomnd tview.NewTableCell(conn.Identity). SetExpansion(expand). SetAlign(alignment)) diff --git a/ui/system/sysdialogs/add.go b/ui/system/sysdialogs/add.go index 10638f56b..dafc8f66f 100644 --- a/ui/system/sysdialogs/add.go +++ b/ui/system/sysdialogs/add.go @@ -23,7 +23,7 @@ const ( connFormFocus ) -// AddConnectionDialog implements new connection create dialog +// AddConnectionDialog implements new connection create dialog. type AddConnectionDialog struct { *tview.Box layout *tview.Flex @@ -39,7 +39,6 @@ type AddConnectionDialog struct { // NewAddConnectionDialog returns a new connection create dialog primitive. func NewAddConnectionDialog() *AddConnectionDialog { - connDialog := AddConnectionDialog{ Box: tview.NewBox().SetBorder(false), layout: tview.NewFlex().SetDirection(tview.FlexRow), @@ -105,7 +104,7 @@ func NewAddConnectionDialog() *AddConnectionDialog { return &connDialog } -// Display displays this primitive +// Display displays this primitive. func (addDialog *AddConnectionDialog) Display() { addDialog.focusElement = 0 addDialog.connNameField.SetText("") @@ -114,31 +113,34 @@ func (addDialog *AddConnectionDialog) Display() { addDialog.display = true } -// IsDisplay returns true if primitive is shown +// IsDisplay returns true if primitive is shown. func (addDialog *AddConnectionDialog) IsDisplay() bool { return addDialog.display } -// Hide stops displaying this primitive +// Hide stops displaying this primitive. func (addDialog *AddConnectionDialog) Hide() { addDialog.display = false } -// HasFocus returns whether or not this primitive has focus +// HasFocus returns whether or not this primitive has focus. func (addDialog *AddConnectionDialog) HasFocus() bool { if addDialog.connNameField.HasFocus() || addDialog.connURIField.HasFocus() { return true } + if addDialog.identityField.HasFocus() || addDialog.layout.HasFocus() { return true } + if addDialog.layout.HasFocus() || addDialog.form.HasFocus() { return true } + return addDialog.Box.HasFocus() } -// Focus is called when this primitive receives focus +// Focus is called when this primitive receives focus. func (addDialog *AddConnectionDialog) Focus(delegate func(p tview.Primitive)) { switch addDialog.focusElement { case connNameFieldFocus: @@ -146,30 +148,39 @@ func (addDialog *AddConnectionDialog) Focus(delegate func(p tview.Primitive)) { if event.Key() == utils.SwitchFocusKey.EventKey() { addDialog.focusElement = connURIFieldFocus addDialog.Focus(delegate) + return nil } + return event }) + delegate(addDialog.connNameField) case connURIFieldFocus: addDialog.connURIField.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == utils.SwitchFocusKey.EventKey() { addDialog.focusElement = connIdentityFieldFocus addDialog.Focus(delegate) + return nil } + return event }) + delegate(addDialog.connURIField) case connIdentityFieldFocus: addDialog.identityField.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == utils.SwitchFocusKey.EventKey() { addDialog.focusElement = connFormFocus addDialog.Focus(delegate) + return nil } + return event }) + delegate(addDialog.identityField) case connFormFocus: button := addDialog.form.GetButton(addDialog.form.GetButtonCount() - 1) @@ -178,26 +189,31 @@ func (addDialog *AddConnectionDialog) Focus(delegate func(p tview.Primitive)) { addDialog.focusElement = connNameFieldFocus addDialog.Focus(delegate) addDialog.form.SetFocus(0) + return nil } + return event }) + delegate(addDialog.form) } } -// InputHandler returns input handler function for this primitive +// InputHandler returns input handler function for this primitive. func (addDialog *AddConnectionDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { return addDialog.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { log.Debug().Msgf("connection create dialog: event %v received", event) if event.Key() == utils.CloseDialogKey.EventKey() { addDialog.cancelHandler() + return } // connection name field if addDialog.connNameField.HasFocus() { if inputHandler := addDialog.connNameField.InputHandler(); inputHandler != nil { inputHandler(event, setFocus) + return } } @@ -205,6 +221,7 @@ func (addDialog *AddConnectionDialog) InputHandler() func(event *tcell.EventKey, if addDialog.connURIField.HasFocus() { if inputHandler := addDialog.connURIField.InputHandler(); inputHandler != nil { inputHandler(event, setFocus) + return } } @@ -212,6 +229,7 @@ func (addDialog *AddConnectionDialog) InputHandler() func(event *tcell.EventKey, if addDialog.identityField.HasFocus() { if inputHandler := addDialog.identityField.InputHandler(); inputHandler != nil { inputHandler(event, setFocus) + return } } @@ -219,25 +237,28 @@ func (addDialog *AddConnectionDialog) InputHandler() func(event *tcell.EventKey, if addDialog.form.HasFocus() { if formHandler := addDialog.form.InputHandler(); formHandler != nil { formHandler(event, setFocus) + return } } }) } -// SetAddFunc sets form add button selected function +// SetAddFunc sets form add button selected function. func (addDialog *AddConnectionDialog) SetAddFunc(handler func()) *AddConnectionDialog { addDialog.addConnectionHandler = handler addButton := addDialog.form.GetButton(addDialog.form.GetButtonCount() - 1) addButton.SetSelectedFunc(handler) + return addDialog } -// SetCancelFunc sets form cancel button selected function +// SetCancelFunc sets form cancel button selected function. func (addDialog *AddConnectionDialog) SetCancelFunc(handler func()) *AddConnectionDialog { addDialog.cancelHandler = handler - cancelButton := addDialog.form.GetButton(addDialog.form.GetButtonCount() - 2) + cancelButton := addDialog.form.GetButton(addDialog.form.GetButtonCount() - 2) //nolint:gomnd cancelButton.SetSelectedFunc(handler) + return addDialog } @@ -247,39 +268,46 @@ func (addDialog *AddConnectionDialog) SetRect(x, y, width, height int) { if width > connCreateDialogMaxWidth { dWidth = connCreateDialogMaxWidth } - dBWidth := dWidth - (2 * dialogs.DialogPadding) - widthEmptySpace := (width - dWidth) / 2 + + dBWidth := dWidth - (2 * dialogs.DialogPadding) //nolint:gomnd + + widthEmptySpace := (width - dWidth) / 2 //nolint:gomnd + x = x + widthEmptySpace + dialogs.DialogPadding dHeight := height if height > connCreateDialogMaxHeight { dHeight = connCreateDialogMaxHeight } - heightEmptySpace := (height - dHeight) / 2 - y = y + heightEmptySpace + + heightEmptySpace := (height - dHeight) / 2 //nolint:gomnd + y += heightEmptySpace addDialog.Box.SetRect(x, y, dBWidth, dHeight) + x, y, width, height = addDialog.Box.GetInnerRect() + addDialog.layout.SetRect(x, y, width, height) } // Draw draws this primitive onto the screen. func (addDialog *AddConnectionDialog) Draw(screen tcell.Screen) { - if !addDialog.display { return } + addDialog.Box.DrawForSubclass(screen, addDialog) addDialog.layout.Draw(screen) } -// GetItems returns new connection name, uri and identity +// GetItems returns new connection name, uri and identity. func (addDialog *AddConnectionDialog) GetItems() (string, string, string) { var ( name string uri string identity string ) + name = addDialog.connNameField.GetText() name = strings.TrimSpace(name) diff --git a/ui/system/sysdialogs/connect.go b/ui/system/sysdialogs/connect.go index 78fc9d2d2..30fa05a9b 100644 --- a/ui/system/sysdialogs/connect.go +++ b/ui/system/sysdialogs/connect.go @@ -16,7 +16,7 @@ const ( maxHeight = 12 ) -// ConnectDialog implements the Connection progress dialog primitive +// ConnectDialog implements the Connection progress dialog primitive. type ConnectDialog struct { *tview.Box layout *tview.Flex @@ -26,7 +26,7 @@ type ConnectDialog struct { cancelButton *tview.Button } -// NewConnectDialog returns connection progress dialog +// NewConnectDialog returns connection progress dialog. func NewConnectDialog() *ConnectDialog { conn := &ConnectDialog{ Box: tview.NewBox(), @@ -52,7 +52,7 @@ func NewConnectDialog() *ConnectDialog { cancelLayout := tview.NewFlex().SetDirection(tview.FlexColumn) cancelLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 0, 1, false) - cancelLayout.AddItem(conn.cancelButton, 10, 0, true) + cancelLayout.AddItem(conn.cancelButton, 10, 0, true) //nolint:gomnd cancelLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false) cancelLayout.SetBackgroundColor(style.DialogBgColor) @@ -70,70 +70,77 @@ func NewConnectDialog() *ConnectDialog { conn.layout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false) conn.display = false + return conn } -// Display displays this primitive +// Display displays this primitive. func (d *ConnectDialog) Display() { d.display = true } -// IsDisplay returns true if primitive is shown +// IsDisplay returns true if primitive is shown. func (d *ConnectDialog) IsDisplay() bool { return d.display } -// Hide stops displaying this primitive +// Hide stops displaying this primitive. func (d *ConnectDialog) Hide() { d.display = false + d.SetDestinationName("") d.reset() } -// SetMessage sets connection page error message +// SetMessage sets connection page error message. func (d *ConnectDialog) SetMessage(message string) { if message == "" { d.layout.ResizeItem(d.textview, 0, 0) } else { d.layout.ResizeItem(d.textview, 0, 1) } + d.textview.SetText(message) } -// HasFocus returns whether or not this primitive has focus +// HasFocus returns whether or not this primitive has focus. func (d *ConnectDialog) HasFocus() bool { return d.Box.HasFocus() || d.cancelButton.HasFocus() } -// Focus is called when this primitive receives focus +// Focus is called when this primitive receives focus. func (d *ConnectDialog) Focus(delegate func(p tview.Primitive)) { delegate(d.cancelButton) } -// SetRect sets a new position of the primitive +// SetRect sets a new position of the primitive. func (d *ConnectDialog) SetRect(x int, y int, width int, height int) { - emptyWidth := (width - maxWidth) / 2 - emptyHeight := (height - maxHeight) / 2 + emptyWidth := (width - maxWidth) / 2 //nolint:gomnd + emptyHeight := (height - maxHeight) / 2 //nolint:gomnd + if width > maxWidth { width = maxWidth - x = x + emptyWidth + x += emptyWidth } + if height > maxHeight { height = maxHeight - y = y + emptyHeight + y += emptyHeight } + if d.textview.GetText(true) == "" { - height = height - 5 + height -= 5 } + d.Box.SetRect(x, y, width, height) } // Draw draws this primitive onto the screen. func (d *ConnectDialog) Draw(screen tcell.Screen) { - if !d.display { return } + d.Box.DrawForSubclass(screen, d) x, y, width, height := d.Box.GetInnerRect() d.layout.SetRect(x, y, width, height) @@ -141,24 +148,26 @@ func (d *ConnectDialog) Draw(screen tcell.Screen) { d.layout.Draw(screen) } -// InputHandler returns input handler function for this primitive +// InputHandler returns input handler function for this primitive. func (d *ConnectDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { log.Debug().Msgf("connection progress dialog: event %v received", event) if cancelButtonHandler := d.cancelButton.InputHandler(); cancelButtonHandler != nil { cancelButtonHandler(event, setFocus) + return } }) } -// SetDestinationName sets progress bar title destination name +// SetDestinationName sets progress bar title destination name. func (d *ConnectDialog) SetDestinationName(name string) { title := fmt.Sprintf("connecting to %s", name) + d.layout.SetTitle(title) } -// SetCancelFunc sets progress bar cancel button function +// SetCancelFunc sets progress bar cancel button function. func (d *ConnectDialog) SetCancelFunc(cancel func()) { d.cancelButton.SetSelectedFunc(cancel) } diff --git a/ui/system/sysdialogs/df.go b/ui/system/sysdialogs/df.go index 934ada889..b67ecfc7a 100644 --- a/ui/system/sysdialogs/df.go +++ b/ui/system/sysdialogs/df.go @@ -17,7 +17,7 @@ const ( dfDialogMaxWidth = 60 ) -// DfDialog is a simple dialog with disk usage result table +// DfDialog is a simple dialog with disk usage result table. type DfDialog struct { *tview.Box layout *tview.Flex @@ -29,7 +29,7 @@ type DfDialog struct { cancelHandler func() } -// NewDfDialog returns new DfDialog primitive +// NewDfDialog returns new DfDialog primitive. func NewDfDialog() *DfDialog { dialog := &DfDialog{ Box: tview.NewBox(), @@ -40,6 +40,7 @@ func NewDfDialog() *DfDialog { // service name input field serviceNameLabel := "SERVICE NAME:" + dialog.serviceName.SetBackgroundColor(style.DialogBgColor) dialog.serviceName.SetLabel("[::b]" + serviceNameLabel) dialog.serviceName.SetLabelWidth(len(serviceNameLabel) + 1) @@ -49,8 +50,8 @@ func NewDfDialog() *DfDialog { Foreground(style.DialogFgColor)) // disk usage table - dialog.table = tview.NewTable() + dialog.table.SetBackgroundColor(style.DialogBgColor) dialog.table.SetBorder(true) dialog.table.SetBorderColor(style.DialogSubBoxBorderColor) @@ -59,6 +60,7 @@ func NewDfDialog() *DfDialog { dialog.form = tview.NewForm(). AddButton("Cancel", nil). SetButtonsAlign(tview.AlignRight) + dialog.form.SetBackgroundColor(style.DialogBgColor) dialog.form.SetButtonBackgroundColor(style.ButtonBgColor) @@ -69,6 +71,7 @@ func NewDfDialog() *DfDialog { dialog.layout.SetBackgroundColor(style.DialogBgColor) tableLayout := tview.NewFlex().SetDirection(tview.FlexColumn) + tableLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, true) tableLayout.AddItem(tview.NewFlex().SetDirection(tview.FlexRow). AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false). @@ -77,7 +80,7 @@ func NewDfDialog() *DfDialog { AddItem(dialog.table, 0, 1, true), 0, 1, true) tableLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, true) - dialog.layout.AddItem(tableLayout, 9, 0, true) + dialog.layout.AddItem(tableLayout, 9, 0, true) //nolint:gomnd dialog.layout.AddItem(dialog.form, dialogs.DialogFormHeight, 0, true) return dialog @@ -89,42 +92,45 @@ func (d *DfDialog) SetServiceName(name string) { d.serviceName.SetText(name) } -// Display displays this primitive +// Display displays this primitive. func (d *DfDialog) Display() { d.display = true } -// IsDisplay returns true if primitive is shown +// IsDisplay returns true if primitive is shown. func (d *DfDialog) IsDisplay() bool { return d.display } -// Hide stops displaying this primitive +// Hide stops displaying this primitive. func (d *DfDialog) Hide() { d.display = false } -// Focus is called when this primitive receives focus +// Focus is called when this primitive receives focus. func (d *DfDialog) Focus(delegate func(p tview.Primitive)) { delegate(d.form) } -// HasFocus returns true if this primitive has focus +// HasFocus returns true if this primitive has focus. func (d *DfDialog) HasFocus() bool { return d.form.HasFocus() || d.table.HasFocus() } -// InputHandler returns input handler function for this primitive +// InputHandler returns input handler function for this primitive. func (d *DfDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { log.Debug().Msgf("disk usage dialog: event %v received", event) if event.Key() == tcell.KeyEsc || event.Key() == tcell.KeyEnter { d.cancelHandler() + return } + // scroll between df items if tableHandler := d.table.InputHandler(); tableHandler != nil { tableHandler(event, setFocus) + return } }) @@ -134,26 +140,25 @@ func (d *DfDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tv func (d *DfDialog) SetRect(x, y, width, height int) { dX := x + dialogs.DialogPadding dY := y - dWidth := width - (2 * dialogs.DialogPadding) + dWidth := width - (2 * dialogs.DialogPadding) //nolint:gomnd + if dWidth > dfDialogMaxWidth { dWidth = dfDialogMaxWidth - emptySpace := (width - dWidth) / 2 + emptySpace := (width - dWidth) / 2 //nolint:gomnd dX = x + emptySpace } - dHeight := dialogs.DialogFormHeight + 11 + dHeight := dialogs.DialogFormHeight + 11 //nolint:gomnd if height > dHeight { - dY = y + ((height - dHeight) / 2) + dY = y + ((height - dHeight) / 2) //nolint:gomnd height = dHeight } d.Box.SetRect(dX, dY, dWidth, height) - } // Draw draws this primitive onto the screen. func (d *DfDialog) Draw(screen tcell.Screen) { - if !d.display { return } @@ -164,9 +169,10 @@ func (d *DfDialog) Draw(screen tcell.Screen) { d.layout.Draw(screen) } -// SetCancelFunc sets form cancel button selected function +// SetCancelFunc sets form cancel button selected function. func (d *DfDialog) SetCancelFunc(handler func()) *DfDialog { d.cancelHandler = handler + return d } @@ -177,6 +183,7 @@ func (d *DfDialog) initTable() { d.table.Clear() d.table.SetFixed(1, 1) d.table.SetSelectable(true, false) + // add headers for i := 0; i < len(d.tableHeaders); i++ { d.table.SetCell(0, i, @@ -187,11 +194,12 @@ func (d *DfDialog) initTable() { SetAlign(tview.AlignLeft). SetSelectable(false)) } + d.table.SetFixed(1, 1) d.table.SetSelectable(true, false) } -// UpdateDiskSummary updates disk summary table result +// UpdateDiskSummary updates disk summary table result. func (d *DfDialog) UpdateDiskSummary(sum []*sysinfo.DfSummary) { // add summaries rowIndex := 1 @@ -204,21 +212,21 @@ func (d *DfDialog) UpdateDiskSummary(sum []*sysinfo.DfSummary) { tview.NewTableCell(dfReport.Total()). SetExpansion(1). SetAlign(tview.AlignLeft)) - d.table.SetCell(rowIndex, 2, + d.table.SetCell(rowIndex, 2, //nolint:gomnd tview.NewTableCell(dfReport.Active()). SetExpansion(1). SetAlign(tview.AlignLeft)) - d.table.SetCell(rowIndex, 3, + d.table.SetCell(rowIndex, 3, //nolint:gomnd tview.NewTableCell(dfReport.Size()). SetExpansion(1). SetAlign(tview.AlignLeft)) - d.table.SetCell(rowIndex, 4, + d.table.SetCell(rowIndex, 4, //nolint:gomnd tview.NewTableCell(dfReport.Reclaimable()). SetExpansion(1). SetAlign(tview.AlignLeft)) - rowIndex = rowIndex + 1 + rowIndex++ } } diff --git a/ui/system/sysdialogs/event.go b/ui/system/sysdialogs/event.go index 7ccb981c9..8d403b111 100644 --- a/ui/system/sysdialogs/event.go +++ b/ui/system/sysdialogs/event.go @@ -14,7 +14,7 @@ const ( textviewHasFocus ) -// EventsDialog implements system events view dialog primitive +// EventsDialog implements system events view dialog primitive. type EventsDialog struct { *tview.Box layout *tview.Flex @@ -26,7 +26,7 @@ type EventsDialog struct { focusElement int } -// NewEventDialog returns new EventsDialog primitive +// NewEventDialog returns new EventsDialog primitive. func NewEventDialog() *EventsDialog { eventsDialog := EventsDialog{ Box: tview.NewBox(), @@ -36,6 +36,7 @@ func NewEventDialog() *EventsDialog { // service name input field serviceNameLabel := "SERVICE NAME:" + eventsDialog.serviceName.SetBackgroundColor(style.DialogBgColor) eventsDialog.serviceName.SetLabel("[::b]" + serviceNameLabel) eventsDialog.serviceName.SetLabelWidth(len(serviceNameLabel) + 1) @@ -87,17 +88,17 @@ func NewEventDialog() *EventsDialog { return &eventsDialog } -// Display displays this primitive +// Display displays this primitive. func (d *EventsDialog) Display() { d.display = true } -// IsDisplay returns true if primitive is shown +// IsDisplay returns true if primitive is shown. func (d *EventsDialog) IsDisplay() bool { return d.display } -// Hide stops displaying this primitive +// Hide stops displaying this primitive. func (d *EventsDialog) Hide() { d.display = false } @@ -108,14 +109,14 @@ func (d *EventsDialog) SetServiceName(name string) { d.serviceName.SetText(name) } -// SetText sets message dialog text messages +// SetText sets message dialog text messages. func (d *EventsDialog) SetText(message string) { d.textview.Clear() d.textview.SetText(message) d.textview.ScrollToEnd() } -// Focus is called when this primitive receives focus +// Focus is called when this primitive receives focus. func (d *EventsDialog) Focus(delegate func(p tview.Primitive)) { switch d.focusElement { // text screen field focus @@ -124,8 +125,10 @@ func (d *EventsDialog) Focus(delegate func(p tview.Primitive)) { if event.Key() == utils.SwitchFocusKey.EventKey() { d.focusElement = formFieldHasFocus d.Focus(delegate) + return nil } + return event }) delegate(d.textview) @@ -136,45 +139,49 @@ func (d *EventsDialog) Focus(delegate func(p tview.Primitive)) { if event.Key() == utils.SwitchFocusKey.EventKey() { d.focusElement = textviewHasFocus d.Focus(delegate) + return nil } + if event.Key() == tcell.KeyEnter { d.cancelHandler() + return nil } + return event }) + delegate(d.form) } } -// HasFocus returns whether or not this primitive has focus +// HasFocus returns whether or not this primitive has focus. func (d *EventsDialog) HasFocus() bool { return d.form.HasFocus() || d.textview.HasFocus() } // SetRect set rects for this primitive. func (d *EventsDialog) SetRect(x, y, width, height int) { - - dWidth := width - (2 * dialogs.DialogPadding) + dWidth := width - (2 * dialogs.DialogPadding) //nolint:gomnd if dWidth < 0 { dWidth = 0 } + dX := x + dialogs.DialogPadding - dHeight := height - (2 * dialogs.DialogPadding) + dHeight := height - (2 * dialogs.DialogPadding) //nolint:gomnd if dHeight < 0 { dHeight = 0 } + dY := y + dialogs.DialogPadding d.Box.SetRect(dX, dY, dWidth, dHeight) - } // Draw draws this primitive onto the screen. func (d *EventsDialog) Draw(screen tcell.Screen) { - if !d.display { return } @@ -185,35 +192,42 @@ func (d *EventsDialog) Draw(screen tcell.Screen) { d.layout.Draw(screen) } -// InputHandler returns input handler function for this primitive +// InputHandler returns input handler function for this primitive. func (d *EventsDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { log.Debug().Msgf("events dialog: event %v received", event) + if event.Key() == utils.CloseDialogKey.EventKey() { d.cancelHandler() + return } + // textview field if d.textview.HasFocus() { if textviewHandler := d.textview.InputHandler(); textviewHandler != nil { textviewHandler(event, setFocus) + return } } + // form primitive if d.form.HasFocus() { if formHandler := d.form.InputHandler(); formHandler != nil { formHandler(event, setFocus) + return } } }) } -// SetCancelFunc sets form cancel button selected function +// SetCancelFunc sets form cancel button selected function. func (d *EventsDialog) SetCancelFunc(handler func()) *EventsDialog { d.cancelHandler = handler cancelButton := d.form.GetButton(d.form.GetButtonCount() - 1) cancelButton.SetSelectedFunc(handler) + return d } diff --git a/ui/system/system.go b/ui/system/system.go index 12d7aea31..5908954bd 100644 --- a/ui/system/system.go +++ b/ui/system/system.go @@ -1,6 +1,7 @@ package system import ( + "errors" "fmt" "strings" "sync" @@ -12,7 +13,9 @@ import ( "github.com/rivo/tview" ) -// System implemnents the system information page primitive +var ErrConnectionInprogres = errors.New("connection is in progress, need to disconnect") + +// System implemnents the system information page primitive. type System struct { *tview.Box title string @@ -42,7 +45,14 @@ type connectionListReport struct { report []registry.Connection } -// NewSystem returns new system page view +type sysSelectedItem struct { + name string + status string + uri string + identity string +} + +// NewSystem returns new system page view. func NewSystem() *System { sys := &System{ Box: tview.NewBox(), @@ -91,15 +101,17 @@ func NewSystem() *System { {"set default", "set selected destination as a default service"}, }) - // set command dialog functions + // set command dialog functions. sys.cmdDialog.SetSelectedFunc(func() { sys.cmdDialog.Hide() sys.runCommand(sys.cmdDialog.GetSelectedItem()) }) + sys.cmdDialog.SetCancelFunc(func() { sys.cmdDialog.Hide() }) - // set confirm dialogs functions + + // set confirm dialogs functions. sys.confirmDialog.SetSelectedFunc(func() { sys.confirmDialog.Hide() switch sys.confirmData { @@ -109,6 +121,7 @@ func NewSystem() *System { sys.remove() } }) + sys.confirmDialog.SetCancelFunc(func() { sys.confirmDialog.Hide() }) @@ -135,21 +148,23 @@ func NewSystem() *System { sys.eventDialog.SetText("") sys.UpdateConnectionsData() }) + // set connection create dialog functions sys.connAddDialog.SetCancelFunc(sys.connAddDialog.Hide) sys.connAddDialog.SetAddFunc(func() { sys.addConnection() }) + return sys } -// GetTitle returns primitive title +// GetTitle returns primitive title. func (sys *System) GetTitle() string { return sys.title } -// HasFocus returns whether or not this primitive has focus -func (sys *System) HasFocus() bool { +// HasFocus returns whether or not this primitive has focus. +func (sys *System) HasFocus() bool { //nolint:cyclop if sys.cmdDialog.HasFocus() || sys.confirmDialog.HasFocus() { return true } @@ -157,94 +172,118 @@ func (sys *System) HasFocus() bool { if sys.progressDialog.HasFocus() || sys.errorDialog.HasFocus() { return true } + if sys.eventDialog.HasFocus() || sys.dfDialog.HasFocus() { return true } + if sys.messageDialog.HasFocus() || sys.connTable.HasFocus() { return true } + if sys.connPrgDialog.HasFocus() || sys.connAddDialog.HasFocus() { return true } + return sys.Box.HasFocus() } // SubDialogHasFocus returns true if there is an active dialog -// displayed on the front screen +// displayed on the front screen. func (sys *System) SubDialogHasFocus() bool { if sys.cmdDialog.HasFocus() || sys.confirmDialog.HasFocus() { return true } + if sys.progressDialog.HasFocus() || sys.errorDialog.HasFocus() { return true } + if sys.dfDialog.HasFocus() || sys.messageDialog.HasFocus() { return true } + if sys.eventDialog.HasFocus() || sys.connAddDialog.HasFocus() { return true } + return false } -// Focus is called when this primitive receives focus +// Focus is called when this primitive receives focus. func (sys *System) Focus(delegate func(p tview.Primitive)) { // error dialog if sys.errorDialog.IsDisplay() { delegate(sys.errorDialog) + return } + // message dialog if sys.messageDialog.IsDisplay() { delegate(sys.messageDialog) + return } + // command dialog if sys.cmdDialog.IsDisplay() { delegate(sys.cmdDialog) + return } + // confirm dialog if sys.confirmDialog.IsDisplay() { delegate(sys.confirmDialog) + return } + // disk usage dialog if sys.dfDialog.IsDisplay() { delegate(sys.dfDialog) + return } + // connection progress dialog if sys.connPrgDialog.IsDisplay() { delegate(sys.connPrgDialog) + return } + // event dialog if sys.eventDialog.IsDisplay() { delegate(sys.eventDialog) + return } + // connection create dialog if sys.connAddDialog.IsDisplay() { delegate(sys.connAddDialog) + return } + delegate(sys.connTable) } -// SetEventMessage appends podman events to textview +// SetEventMessage appends podman events to textview. func (sys *System) SetEventMessage(messages []string) { msg := strings.Join(messages, "\n") sys.eventDialog.SetText(msg) } -// SetConnectionProgressMessage sets connection progressbar error message +// SetConnectionProgressMessage sets connection progressbar error message. func (sys *System) SetConnectionProgressMessage(message string) { sys.connPrgDialog.SetMessage(message) } // SetConnectionProgressDestName sets connection -// progressbar title destination name +// progressbar title destination name. func (sys *System) SetConnectionProgressDestName(name string) { sys.connPrgDialog.SetDestinationName(name) } @@ -254,27 +293,27 @@ func (sys *System) ConnectionProgressDisplay(display bool) { if display { sys.hideAllDialogs() sys.connPrgDialog.Display() + return } + sys.connPrgDialog.Hide() } -func (sys *System) getSelectedItem() (string, string, string, string) { - var ( - name string - uri string - status string - identity string - ) +func (sys *System) getSelectedItem() *sysSelectedItem { + selectedItem := sysSelectedItem{} + if sys.connTable.GetRowCount() <= 1 { - return name, status, uri, identity + return &selectedItem } + row, _ := sys.connTable.GetSelection() - name = sys.connTable.GetCell(row, 0).Text - status = sys.connTable.GetCell(row, 2).Text - uri = sys.connTable.GetCell(row, 3).Text - identity = sys.connTable.GetCell(row, 4).Text - return name, status, uri, identity + selectedItem.name = sys.connTable.GetCell(row, 0).Text + selectedItem.status = sys.connTable.GetCell(row, 2).Text //nolint:gomnd + selectedItem.uri = sys.connTable.GetCell(row, 3).Text //nolint:gomnd + selectedItem.identity = sys.connTable.GetCell(row, 4).Text //nolint:gomnd + + return &selectedItem } func (sys *System) hideAllDialogs() { @@ -288,32 +327,32 @@ func (sys *System) hideAllDialogs() { sys.connAddDialog.Hide() } -// SetConnectionListFunc sets list destination function +// SetConnectionListFunc sets list destination function. func (sys *System) SetConnectionListFunc(list func() []registry.Connection) { sys.connectionListFunc = list } -// SetConnectionSetDefaultFunc sets set destination default function +// SetConnectionSetDefaultFunc sets set destination default function. func (sys *System) SetConnectionSetDefaultFunc(setDefault func(dest string) error) { sys.connectionSetDefaultFunc = setDefault } -// SetConnectionConnectFunc sets system connect function +// SetConnectionConnectFunc sets system connect function. func (sys *System) SetConnectionConnectFunc(connect func(dest registry.Connection)) { sys.connectionConnectFunc = connect } -// SetConnectionDisconnectFunc sets system disconnect function +// SetConnectionDisconnectFunc sets system disconnect function. func (sys *System) SetConnectionDisconnectFunc(disconnect func()) { sys.connectionDisconnectFunc = disconnect } -// SetConnectionAddFunc sets system add new connection function +// SetConnectionAddFunc sets system add new connection function. func (sys *System) SetConnectionAddFunc(add func(name string, uri string, identity string) error) { sys.connectionAddFunc = add } -// SetConnectionRemoveFunc sets system remove connection function +// SetConnectionRemoveFunc sets system remove connection function. func (sys *System) SetConnectionRemoveFunc(remove func(name string) error) { sys.connectionRemoveFunc = remove }