199 lines
7.3 KiB
Go
199 lines
7.3 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
var (
|
|
titleStyle = lipgloss.NewStyle().
|
|
Bold(true).
|
|
Foreground(lipgloss.Color("#FFFFFF")).
|
|
Background(lipgloss.Color("#900C3F")).
|
|
Padding(0, 1)
|
|
|
|
headerBgStyle = lipgloss.NewStyle().
|
|
Bold(true).
|
|
Foreground(lipgloss.Color("#FFFFFF")).
|
|
Background(lipgloss.Color("#1F618D"))
|
|
|
|
localHeaderBgStyle = lipgloss.NewStyle().
|
|
Bold(true).
|
|
Foreground(lipgloss.Color("#FFFFFF")).
|
|
Background(lipgloss.Color("#B7950B"))
|
|
|
|
selectedRowStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#FFFFFF")).
|
|
Background(lipgloss.Color("#2980B9")).
|
|
Bold(true)
|
|
|
|
normalProjectStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#F4D03F")).
|
|
Bold(true)
|
|
|
|
normalImageStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#D5D8DC"))
|
|
|
|
fullNameStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#00FFFF")).
|
|
Bold(true)
|
|
|
|
footerKeyStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#000000")).
|
|
Background(lipgloss.Color("#F4D03F")).
|
|
Bold(true)
|
|
|
|
footerDescStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#FFFFFF")).
|
|
Background(lipgloss.Color("#2C3E50"))
|
|
|
|
errorBoxStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#FF5F56")).
|
|
Bold(true)
|
|
|
|
successStyle = lipgloss.NewStyle().
|
|
Foreground(lipgloss.Color("#2ECC71")).
|
|
Bold(true)
|
|
)
|
|
|
|
func (m Model) View() string {
|
|
if m.state == StateRegistryDown {
|
|
return m.viewRegistryDown()
|
|
}
|
|
|
|
switch m.state {
|
|
case StateLoading:
|
|
modeText := "del Registro Docker"
|
|
if m.mode == ModeLocal {
|
|
modeText = "Locales de Docker"
|
|
}
|
|
return fmt.Sprintf("\n Cargando imágenes %s...\n", modeText)
|
|
|
|
case StateError:
|
|
return fmt.Sprintf("\n %s\n\n [Presiona 'q' para salir / 'r' o 'l' para cambiar de modo]\n", errorBoxStyle.Render("Error: "+m.err.Error()))
|
|
|
|
case StateMainTable:
|
|
s := ""
|
|
modeStr := "REGISTRY"
|
|
styleHeader := headerBgStyle
|
|
if m.mode == ModeLocal {
|
|
modeStr = "LOCAL"
|
|
styleHeader = localHeaderBgStyle
|
|
}
|
|
|
|
titleBar := fmt.Sprintf(" REGISTRY-TUI v%s [%s] ", m.version, modeStr)
|
|
s += styleHeader.Width(70).Render(titleBar) + "\n"
|
|
|
|
s += "┌───────────────────────┬──────────────────────────────────────────┐\n"
|
|
s += fmt.Sprintf("│ %-21s │ %-40s │\n", "PROYECTO / RUTA", "IMAGEN : VERSION")
|
|
s += "├───────────────────────┼──────────────────────────────────────────┤\n"
|
|
|
|
if len(m.rows) == 0 {
|
|
msgEmpty := "No hay imágenes en el registro"
|
|
if m.mode == ModeLocal {
|
|
msgEmpty = "No se encontraron imágenes locales"
|
|
}
|
|
s += fmt.Sprintf("│ %-21s │ %-40s │\n", "", msgEmpty)
|
|
s += "└───────────────────────┴──────────────────────────────────────────┘\n"
|
|
} else {
|
|
for i, row := range m.rows {
|
|
displayProj := row.Project
|
|
if displayProj == "(raíz)" {
|
|
displayProj = ""
|
|
}
|
|
|
|
imageVersion := fmt.Sprintf("%s:%s", row.ImageName, row.Tag)
|
|
isSelected := (m.cursor == i)
|
|
|
|
var lineContent string
|
|
if isSelected {
|
|
projFormatted := fmt.Sprintf(" %-21s ", displayProj)
|
|
imgFormatted := fmt.Sprintf(" %-40s ", imageVersion)
|
|
|
|
renderedProj := selectedRowStyle.Render(projFormatted)
|
|
renderedImg := selectedRowStyle.Render(imgFormatted)
|
|
|
|
lineContent = fmt.Sprintf("│%s│%s│", renderedProj, renderedImg)
|
|
} else {
|
|
projFormatted := normalProjectStyle.Render(fmt.Sprintf("%-21s", displayProj))
|
|
imgFormatted := normalImageStyle.Render(fmt.Sprintf("%-40s", imageVersion))
|
|
|
|
lineContent = fmt.Sprintf("│ %s │ %s │", projFormatted, imgFormatted)
|
|
}
|
|
|
|
s += lineContent + "\n"
|
|
|
|
if i < len(m.rows)-1 {
|
|
s += "├───────────────────────┼──────────────────────────────────────────┤\n"
|
|
}
|
|
}
|
|
s += "└───────────────────────┴──────────────────────────────────────────┘\n"
|
|
}
|
|
|
|
// Ruta completa seleccionada
|
|
if len(m.rows) > 0 {
|
|
selected := m.rows[m.cursor]
|
|
fullRef := fmt.Sprintf("%s:%s", selected.RepoName, selected.Tag)
|
|
s += fmt.Sprintf(" Ruta completa: %s\n", fullNameStyle.Render(fullRef))
|
|
} else {
|
|
s += "\n"
|
|
}
|
|
|
|
total := len(m.rows)
|
|
statusInfo := fmt.Sprintf(" Total: %d imágenes (%s)", total, modeStr)
|
|
if m.statusMsg != "" {
|
|
statusInfo = " " + successStyle.Render("✔ "+m.statusMsg)
|
|
}
|
|
s += fmt.Sprintf("%-70s\n\n", statusInfo)
|
|
|
|
// Barra de botones inferior estilo MC uniforme para ambos modos
|
|
btnR := footerKeyStyle.Render(" R ") + footerDescStyle.Render(" Registry ")
|
|
btnL := footerKeyStyle.Render(" L ") + footerDescStyle.Render(" Local ")
|
|
btnT := footerKeyStyle.Render(" t ") + footerDescStyle.Render(" Tagear ")
|
|
btnD := footerKeyStyle.Render(" d ") + footerDescStyle.Render(" Borrar ")
|
|
btnP := footerKeyStyle.Render(" p ") + footerDescStyle.Render(" Push ")
|
|
btnQ := footerKeyStyle.Render(" q ") + footerDescStyle.Render(" Salir ")
|
|
|
|
if m.mode == ModeLocal {
|
|
s += fmt.Sprintf(" %s %s %s %s %s %s\n", btnR, btnL, btnP, btnT, btnD, btnQ)
|
|
} else {
|
|
s += fmt.Sprintf(" %s %s %s %s %s\n", btnR, btnL, btnT, btnD, btnQ)
|
|
}
|
|
|
|
return s
|
|
|
|
case StateConfirmDelete:
|
|
selectedRow := m.rows[m.cursor]
|
|
s := headerBgStyle.Width(50).Render(" Confirmar Borrado ") + "\n\n"
|
|
s += fmt.Sprintf(" ¿Estás seguro de que deseas borrar la imagen:\n -> %s:%s?\n\n", selectedRow.RepoName, selectedRow.Tag)
|
|
if m.mode == ModeLocal {
|
|
s += errorBoxStyle.Render(" ¡Esta acción eliminará la imagen de tu sistema local!\n\n")
|
|
} else {
|
|
s += errorBoxStyle.Render(" ¡Esta acción eliminará el manifest permanentemente del registro!\n\n")
|
|
}
|
|
s += footerKeyStyle.Render(" y ") + footerDescStyle.Render(" Sí, borrar ") + " " + footerKeyStyle.Render(" n ") + footerDescStyle.Render(" Cancelar ")
|
|
return s
|
|
|
|
case StateNewTag:
|
|
selectedRow := m.rows[m.cursor]
|
|
s := headerBgStyle.Width(50).Render(" Reestructurar / Tagear Imagen ") + "\n\n"
|
|
s += fmt.Sprintf(" Origen: %s:%s\n\n", selectedRow.RepoName, selectedRow.Tag)
|
|
s += " Introduce la ruta completa de destino\n (ej: proyecto-web/alpine:v1.0):\n\n"
|
|
s += " " + m.textInput.View() + "\n\n"
|
|
s += footerKeyStyle.Render(" Enter ") + footerDescStyle.Render(" Confirmar ") + " " + footerKeyStyle.Render(" Esc ") + footerDescStyle.Render(" Cancelar ")
|
|
return s
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (m Model) viewRegistryDown() string {
|
|
s := titleStyle.Render(" ⚠️ ADVERTENCIA DE CONEXIÓN - REGISTRY-TUI ") + "\n\n"
|
|
s += fmt.Sprintf(" No se puede conectar al Registry local:\n %s\n\n", m.statusMsg)
|
|
s += " ─────────────────────────────────────────────────────────\n"
|
|
s += " [ENTER / L] Cambiar directamente al modo LOCAL\n"
|
|
s += " [ q ] Salir de la aplicación\n"
|
|
return lipgloss.NewStyle().Margin(2, 4).Render(s)
|
|
}
|