fix: fix online mode after offline-first architecture changes

- Fix nil pointer dereference in PricingHandler alert methods
- Add automatic MariaDB connection on startup if settings exist
- Update setupRouter to accept mariaDB as parameter
- Fix offline mode checks: use h.db instead of h.alertService
- Update setup handler to show restart required message
- Add warning status support in setup.html UI

This ensures that after saving connection settings, the application
works correctly in online mode after restart. All repositories are
properly initialized with MariaDB connection on startup.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-02-03 10:50:07 +03:00
parent 2510d9e36e
commit 8d84484412
4 changed files with 101 additions and 26 deletions

View File

@@ -639,6 +639,18 @@ func (h *PricingHandler) RecalculateAll(c *gin.Context) {
}
func (h *PricingHandler) ListAlerts(c *gin.Context) {
// Check if we're in offline mode
if h.db == nil {
c.JSON(http.StatusOK, gin.H{
"alerts": []interface{}{},
"total": 0,
"page": 1,
"per_page": 20,
"offline": true,
})
return
}
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "20"))
@@ -664,6 +676,15 @@ func (h *PricingHandler) ListAlerts(c *gin.Context) {
}
func (h *PricingHandler) AcknowledgeAlert(c *gin.Context) {
// Check if we're in offline mode
if h.db == nil {
c.JSON(http.StatusServiceUnavailable, gin.H{
"error": "Управление алертами доступно только в онлайн режиме",
"offline": true,
})
return
}
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid alert id"})
@@ -679,6 +700,15 @@ func (h *PricingHandler) AcknowledgeAlert(c *gin.Context) {
}
func (h *PricingHandler) ResolveAlert(c *gin.Context) {
// Check if we're in offline mode
if h.db == nil {
c.JSON(http.StatusServiceUnavailable, gin.H{
"error": "Управление алертами доступно только в онлайн режиме",
"offline": true,
})
return
}
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid alert id"})
@@ -694,6 +724,15 @@ func (h *PricingHandler) ResolveAlert(c *gin.Context) {
}
func (h *PricingHandler) IgnoreAlert(c *gin.Context) {
// Check if we're in offline mode
if h.db == nil {
c.JSON(http.StatusServiceUnavailable, gin.H{
"error": "Управление алертами доступно только в онлайн режиме",
"offline": true,
})
return
}
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid alert id"})

View File

@@ -3,12 +3,14 @@ package handlers
import (
"fmt"
"html/template"
"log/slog"
"net/http"
"path/filepath"
"strconv"
"time"
"github.com/gin-gonic/gin"
"git.mchus.pro/mchus/quoteforge/internal/db"
"git.mchus.pro/mchus/quoteforge/internal/localdb"
"gorm.io/driver/mysql"
"gorm.io/gorm"
@@ -17,11 +19,12 @@ import (
type SetupHandler struct {
localDB *localdb.LocalDB
connMgr *db.ConnectionManager
templates map[string]*template.Template
restartSig chan struct{}
}
func NewSetupHandler(localDB *localdb.LocalDB, templatesPath string, restartSig chan struct{}) (*SetupHandler, error) {
func NewSetupHandler(localDB *localdb.LocalDB, connMgr *db.ConnectionManager, templatesPath string, restartSig chan struct{}) (*SetupHandler, error) {
funcMap := template.FuncMap{
"sub": func(a, b int) int { return a - b },
"add": func(a, b int) int { return a + b },
@@ -39,6 +42,7 @@ func NewSetupHandler(localDB *localdb.LocalDB, templatesPath string, restartSig
return &SetupHandler{
localDB: localDB,
connMgr: connMgr,
templates: templates,
restartSig: restartSig,
}, nil
@@ -181,12 +185,23 @@ func (h *SetupHandler) SaveConnection(c *gin.Context) {
return
}
// Try to connect immediately to verify settings
if h.connMgr != nil {
if err := h.connMgr.TryConnect(); err != nil {
slog.Warn("failed to connect after saving settings", "error", err)
} else {
slog.Info("successfully connected to database after saving settings")
}
}
// Always restart to properly initialize all services with the new connection
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "Settings saved. Restarting application...",
"message": "Settings saved. Please restart the application to apply changes.",
"restart_required": true,
})
// Signal restart after response is sent
// Signal restart after response is sent (if restart signal is configured)
if h.restartSig != nil {
go func() {
time.Sleep(500 * time.Millisecond) // Give time for response to be sent