use tea model for showing server runnign and closing
This commit is contained in:
@@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/LazyBachelor/LazyPM/cmd/pm/tasks"
|
"github.com/LazyBachelor/LazyPM/cmd/pm/tasks"
|
||||||
@@ -19,11 +18,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
err := godotenv.Load(".env")
|
godotenv.Load(".env")
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Println("Error loading .env file")
|
|
||||||
}
|
|
||||||
|
|
||||||
models.BaseConfig = models.BaseConfig.LoadFromEnv()
|
models.BaseConfig = models.BaseConfig.LoadFromEnv()
|
||||||
|
|
||||||
|
|||||||
110
pkg/web/web.go
110
pkg/web/web.go
@@ -6,14 +6,19 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"charm.land/lipgloss/v2"
|
||||||
"github.com/LazyBachelor/LazyPM/internal/app"
|
"github.com/LazyBachelor/LazyPM/internal/app"
|
||||||
"github.com/LazyBachelor/LazyPM/internal/models"
|
"github.com/LazyBachelor/LazyPM/internal/models"
|
||||||
"github.com/LazyBachelor/LazyPM/internal/utils/browser"
|
"github.com/LazyBachelor/LazyPM/internal/utils/browser"
|
||||||
"github.com/LazyBachelor/LazyPM/pkg/web/handler"
|
"github.com/LazyBachelor/LazyPM/pkg/web/handler"
|
||||||
"github.com/LazyBachelor/LazyPM/pkg/web/server"
|
"github.com/LazyBachelor/LazyPM/pkg/web/server"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config = models.Config
|
type Config = models.Config
|
||||||
@@ -32,12 +37,50 @@ func New() *Web {
|
|||||||
//go:embed assets/*
|
//go:embed assets/*
|
||||||
var assets embed.FS
|
var assets embed.FS
|
||||||
|
|
||||||
|
type tuiModel struct {
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
address string
|
||||||
|
quitChan chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m tuiModel) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m tuiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
m.width = msg.Width
|
||||||
|
m.height = msg.Height
|
||||||
|
return m, nil
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch msg.String() {
|
||||||
|
case "q", "esc", "ctrl+c":
|
||||||
|
select {
|
||||||
|
case <-m.quitChan:
|
||||||
|
default:
|
||||||
|
close(m.quitChan)
|
||||||
|
}
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m tuiModel) View() string {
|
||||||
|
return lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, fmt.Sprintf(
|
||||||
|
"Web server running at %s\n\nPress q, esc, or Ctrl+C to stop the task and server.\n",
|
||||||
|
m.address,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Web) Run(ctx context.Context, config Config) error {
|
func (w *Web) Run(ctx context.Context, config Config) error {
|
||||||
app, cleanup, err := app.New(ctx, config)
|
app, cleanup, err := app.New(ctx, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
|
||||||
httpServer := server.NewServer(server.Server{
|
httpServer := server.NewServer(server.Server{
|
||||||
@@ -46,21 +89,39 @@ func (w *Web) Run(ctx context.Context, config Config) error {
|
|||||||
App: app,
|
App: app,
|
||||||
})
|
})
|
||||||
|
|
||||||
fmt.Printf("Starting web server on %s...\n", config.WebAddress)
|
|
||||||
|
|
||||||
address := config.WebAddress
|
address := config.WebAddress
|
||||||
if !strings.Contains(address, "http") {
|
if !strings.Contains(address, "http") {
|
||||||
address = "http://localhost" + address
|
address = "http://localhost" + address
|
||||||
}
|
}
|
||||||
|
|
||||||
err = browser.Open(address)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open browser: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
serverErr := make(chan error, 1)
|
serverErr := make(chan error, 1)
|
||||||
|
uiQuitChan := make(chan struct{})
|
||||||
|
|
||||||
|
screen := tea.NewProgram(
|
||||||
|
tuiModel{
|
||||||
|
address: address,
|
||||||
|
quitChan: uiQuitChan,
|
||||||
|
},
|
||||||
|
tea.WithAltScreen(),
|
||||||
|
)
|
||||||
|
|
||||||
|
screenDone := make(chan struct{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
defer close(screenDone)
|
||||||
|
|
||||||
|
if _, err := screen.Run(); err != nil {
|
||||||
|
fmt.Printf("failed to start terminal UI: %s\n", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||||
|
defer signal.Stop(sigChan)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := httpServer.ListenAndServe(); err != nil &&
|
||||||
|
!errors.Is(err, http.ErrServerClosed) {
|
||||||
serverErr <- err
|
serverErr <- err
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -77,17 +138,36 @@ func (w *Web) Run(ctx context.Context, config Config) error {
|
|||||||
handler.SetSubmitChan(w.submitChan)
|
handler.SetSubmitChan(w.submitChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := browser.Open(address); err != nil {
|
||||||
|
fmt.Printf("failed to open browser: %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var shutdownMsg string
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-w.quitChan:
|
case <-w.quitChan:
|
||||||
fmt.Println("Task completed! Shutting down server...")
|
shutdownMsg = "Task completed! Ending task and server..."
|
||||||
|
case <-uiQuitChan:
|
||||||
|
shutdownMsg = "Quit key pressed. Ending task and server..."
|
||||||
|
case sig := <-sigChan:
|
||||||
|
shutdownMsg = fmt.Sprintf("Received signal %s. Ending task and server...", sig)
|
||||||
|
case <-ctx.Done():
|
||||||
|
shutdownMsg = "Context cancelled. Ending task and server..."
|
||||||
|
case err := <-serverErr:
|
||||||
|
screen.Quit()
|
||||||
|
<-screenDone
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.Quit()
|
||||||
|
<-screenDone
|
||||||
|
|
||||||
|
fmt.Println(shutdownMsg)
|
||||||
|
|
||||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
return httpServer.Shutdown(shutdownCtx)
|
return httpServer.Shutdown(shutdownCtx)
|
||||||
case err := <-serverErr:
|
|
||||||
return err
|
|
||||||
case <-ctx.Done():
|
|
||||||
return httpServer.Shutdown(context.Background())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Web) SetChannels(feedbackChan chan ValidationFeedback, quitChan chan bool) {
|
func (w *Web) SetChannels(feedbackChan chan ValidationFeedback, quitChan chan bool) {
|
||||||
|
|||||||
Reference in New Issue
Block a user