refactor: mover apps TUI de fn_operations/ a apps/
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>
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"docker-tui/views"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/lucasdataproyects/devfactory/tui"
|
||||
)
|
||||
|
||||
type View int
|
||||
|
||||
const (
|
||||
ViewContainers View = iota
|
||||
ViewImages
|
||||
ViewVolumes
|
||||
ViewNetworks
|
||||
ViewCompose
|
||||
)
|
||||
|
||||
var tabNames = []string{"Containers", "Images", "Volumes", "Networks", "Compose"}
|
||||
|
||||
type Model struct {
|
||||
tui.BaseModel
|
||||
activeTab int
|
||||
containers views.ContainersModel
|
||||
images views.ImagesModel
|
||||
volumes views.VolumesModel
|
||||
networks views.NetworksModel
|
||||
compose views.ComposeModel
|
||||
ready bool
|
||||
}
|
||||
|
||||
func New() Model {
|
||||
styles := tui.DefaultStyles()
|
||||
return Model{
|
||||
BaseModel: tui.NewBaseModel().WithStyles(styles),
|
||||
containers: views.NewContainersModel(styles),
|
||||
images: views.NewImagesModel(styles),
|
||||
volumes: views.NewVolumesModel(styles),
|
||||
networks: views.NewNetworksModel(styles),
|
||||
compose: views.NewComposeModel(styles),
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return m.containers.Init()
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case views.KeyQuit:
|
||||
return m, tea.Quit
|
||||
case "q", "0", "esc":
|
||||
updated, atBase := m.handleBack()
|
||||
if atBase {
|
||||
return updated, tea.Quit
|
||||
}
|
||||
return updated, nil
|
||||
case views.KeyTab:
|
||||
m.activeTab = (m.activeTab + 1) % len(tabNames)
|
||||
return m, m.initActiveView()
|
||||
case "shift+tab":
|
||||
m.activeTab = (m.activeTab - 1 + len(tabNames)) % len(tabNames)
|
||||
return m, m.initActiveView()
|
||||
}
|
||||
case tea.WindowSizeMsg:
|
||||
m.HandleWindowSize(msg)
|
||||
m.ready = true
|
||||
}
|
||||
|
||||
var cmd tea.Cmd
|
||||
switch View(m.activeTab) {
|
||||
case ViewContainers:
|
||||
m.containers, cmd = m.containers.Update(msg)
|
||||
case ViewImages:
|
||||
m.images, cmd = m.images.Update(msg)
|
||||
case ViewVolumes:
|
||||
m.volumes, cmd = m.volumes.Update(msg)
|
||||
case ViewNetworks:
|
||||
m.networks, cmd = m.networks.Update(msg)
|
||||
case ViewCompose:
|
||||
m.compose, cmd = m.compose.Update(msg)
|
||||
}
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
if !m.ready {
|
||||
return "Loading..."
|
||||
}
|
||||
|
||||
// Tab bar
|
||||
tabs := m.renderTabs()
|
||||
|
||||
// Active view content
|
||||
var content string
|
||||
switch View(m.activeTab) {
|
||||
case ViewContainers:
|
||||
content = m.containers.View()
|
||||
case ViewImages:
|
||||
content = m.images.View()
|
||||
case ViewVolumes:
|
||||
content = m.volumes.View()
|
||||
case ViewNetworks:
|
||||
content = m.networks.View()
|
||||
case ViewCompose:
|
||||
content = m.compose.View()
|
||||
}
|
||||
|
||||
// Status bar
|
||||
status := m.Styles.StatusBar.Render(" Tab: switch view │ Ctrl+C: quit │ Enter: action │ r: refresh")
|
||||
|
||||
return lipgloss.JoinVertical(lipgloss.Left,
|
||||
tabs,
|
||||
"",
|
||||
content,
|
||||
"",
|
||||
status,
|
||||
)
|
||||
}
|
||||
|
||||
func (m Model) renderTabs() string {
|
||||
var tabs []string
|
||||
for i, name := range tabNames {
|
||||
if i == m.activeTab {
|
||||
tabs = append(tabs, m.Styles.Selected.Render(" "+name+" "))
|
||||
} else {
|
||||
tabs = append(tabs, m.Styles.Muted.Render(" "+name+" "))
|
||||
}
|
||||
}
|
||||
row := lipgloss.JoinHorizontal(lipgloss.Top, tabs...)
|
||||
return m.Styles.Header.Render("Docker TUI") + " " + row
|
||||
}
|
||||
|
||||
// handleBack asks the active view to go back one level.
|
||||
// Returns the updated model and true if the view was already at base level (app should quit).
|
||||
func (m Model) handleBack() (Model, bool) {
|
||||
switch View(m.activeTab) {
|
||||
case ViewContainers:
|
||||
atBase := m.containers.HandleBack()
|
||||
return m, atBase
|
||||
case ViewImages:
|
||||
atBase := m.images.HandleBack()
|
||||
return m, atBase
|
||||
case ViewVolumes:
|
||||
atBase := m.volumes.HandleBack()
|
||||
return m, atBase
|
||||
case ViewNetworks:
|
||||
atBase := m.networks.HandleBack()
|
||||
return m, atBase
|
||||
case ViewCompose:
|
||||
atBase := m.compose.HandleBack()
|
||||
return m, atBase
|
||||
}
|
||||
return m, true
|
||||
}
|
||||
|
||||
func (m Model) initActiveView() tea.Cmd {
|
||||
switch View(m.activeTab) {
|
||||
case ViewContainers:
|
||||
return m.containers.Init()
|
||||
case ViewImages:
|
||||
return m.images.Init()
|
||||
case ViewVolumes:
|
||||
return m.volumes.Init()
|
||||
case ViewNetworks:
|
||||
return m.networks.Init()
|
||||
case ViewCompose:
|
||||
return m.compose.Init()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user