5d3b56fe8e
Separa aplicaciones ejecutables (docker_tui, pipeline_launcher) de la librería fn_operations. La carpeta apps/ contiene módulos Go independientes, fn_operations/ queda como librería pura de models/store/operations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
129 lines
2.9 KiB
Go
129 lines
2.9 KiB
Go
package views
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/lucasdataproyects/devfactory/tui"
|
|
)
|
|
|
|
type networksState int
|
|
|
|
const (
|
|
networksLoading networksState = iota
|
|
networksList
|
|
networksAction
|
|
)
|
|
|
|
type networksLoadedMsg []DockerNetwork
|
|
type networksActionMsg struct{ output string; err error }
|
|
|
|
type NetworksModel struct {
|
|
state networksState
|
|
list tui.ListModel
|
|
spinner tui.SpinnerModel
|
|
styles tui.Styles
|
|
networks []DockerNetwork
|
|
err error
|
|
}
|
|
|
|
func NewNetworksModel(styles tui.Styles) NetworksModel {
|
|
return NetworksModel{
|
|
state: networksLoading,
|
|
list: tui.NewList(nil),
|
|
spinner: tui.NewSpinner("Loading networks..."),
|
|
styles: styles,
|
|
}
|
|
}
|
|
|
|
func (m NetworksModel) Init() tea.Cmd {
|
|
return tea.Batch(m.spinner.Init(), loadNetworks)
|
|
}
|
|
|
|
func loadNetworks() tea.Msg {
|
|
networks, err := ListNetworks()
|
|
if err != nil {
|
|
return networksLoadedMsg(nil)
|
|
}
|
|
return networksLoadedMsg(networks)
|
|
}
|
|
|
|
func (m NetworksModel) Update(msg tea.Msg) (NetworksModel, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case networksLoadedMsg:
|
|
m.networks = []DockerNetwork(msg)
|
|
items := make([]tui.ListItem, len(m.networks))
|
|
for i, n := range m.networks {
|
|
items[i] = tui.ListItem{
|
|
Title: n.Name,
|
|
Description: fmt.Sprintf("Driver: %s — Scope: %s", n.Driver, n.Scope),
|
|
Value: n,
|
|
}
|
|
}
|
|
m.list.SetItems(items)
|
|
m.state = networksList
|
|
return m, nil
|
|
|
|
case networksActionMsg:
|
|
if msg.err != nil {
|
|
m.err = msg.err
|
|
}
|
|
m.state = networksList
|
|
return m, loadNetworks
|
|
|
|
case tea.KeyMsg:
|
|
if m.state == networksList {
|
|
switch msg.String() {
|
|
case "r":
|
|
m.state = networksLoading
|
|
return m, tea.Batch(m.spinner.Init(), loadNetworks)
|
|
case "d", "delete":
|
|
if item := m.list.SelectedItem(); item != nil {
|
|
net := item.Value.(DockerNetwork)
|
|
m.state = networksAction
|
|
return m, func() tea.Msg {
|
|
err := RemoveNetwork(net.Name)
|
|
return networksActionMsg{output: "Removed", err: err}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
var cmd tea.Cmd
|
|
switch m.state {
|
|
case networksLoading, networksAction:
|
|
var model tea.Model
|
|
model, cmd = m.spinner.Update(msg)
|
|
m.spinner = model.(tui.SpinnerModel)
|
|
case networksList:
|
|
var model tea.Model
|
|
model, cmd = m.list.Update(msg)
|
|
m.list = model.(tui.ListModel)
|
|
}
|
|
return m, cmd
|
|
}
|
|
|
|
// HandleBack retrocede un nivel. Retorna true si ya estaba en estado base.
|
|
func (m *NetworksModel) HandleBack() bool {
|
|
return true
|
|
}
|
|
|
|
func (m NetworksModel) View() string {
|
|
switch m.state {
|
|
case networksLoading, networksAction:
|
|
return m.spinner.View()
|
|
case networksList:
|
|
if len(m.networks) == 0 {
|
|
return m.styles.Muted.Render("No networks found. Press 'r' to refresh.")
|
|
}
|
|
help := m.styles.Muted.Render(" d: remove │ r: refresh")
|
|
view := m.list.View() + "\n" + help
|
|
if m.err != nil {
|
|
view += "\n" + m.styles.Error.Render(fmt.Sprintf(" Error: %v", m.err))
|
|
}
|
|
return view
|
|
}
|
|
return ""
|
|
}
|