Embed assets and fix offline/sync/pricing issues

This commit is contained in:
2026-02-03 21:58:02 +03:00
parent 8d84484412
commit 20056f3593
9 changed files with 170 additions and 67 deletions

View File

@@ -4,13 +4,15 @@ import (
"html/template"
"log/slog"
"net/http"
"os"
"path/filepath"
"time"
"github.com/gin-gonic/gin"
qfassets "git.mchus.pro/mchus/quoteforge"
"git.mchus.pro/mchus/quoteforge/internal/db"
"git.mchus.pro/mchus/quoteforge/internal/localdb"
"git.mchus.pro/mchus/quoteforge/internal/services/sync"
"github.com/gin-gonic/gin"
)
// SyncHandler handles sync API endpoints
@@ -25,7 +27,13 @@ type SyncHandler struct {
func NewSyncHandler(localDB *localdb.LocalDB, syncService *sync.Service, connMgr *db.ConnectionManager, templatesPath string) (*SyncHandler, error) {
// Load sync_status partial template
partialPath := filepath.Join(templatesPath, "partials", "sync_status.html")
tmpl, err := template.ParseFiles(partialPath)
var tmpl *template.Template
var err error
if stat, statErr := os.Stat(templatesPath); statErr == nil && stat.IsDir() {
tmpl, err = template.ParseFiles(partialPath)
} else {
tmpl, err = template.ParseFS(qfassets.TemplatesFS, "web/templates/partials/sync_status.html")
}
if err != nil {
return nil, err
}
@@ -40,14 +48,14 @@ func NewSyncHandler(localDB *localdb.LocalDB, syncService *sync.Service, connMgr
// SyncStatusResponse represents the sync status
type SyncStatusResponse struct {
LastComponentSync *time.Time `json:"last_component_sync"`
LastPricelistSync *time.Time `json:"last_pricelist_sync"`
IsOnline bool `json:"is_online"`
ComponentsCount int64 `json:"components_count"`
PricelistsCount int64 `json:"pricelists_count"`
ServerPricelists int `json:"server_pricelists"`
NeedComponentSync bool `json:"need_component_sync"`
NeedPricelistSync bool `json:"need_pricelist_sync"`
LastComponentSync *time.Time `json:"last_component_sync"`
LastPricelistSync *time.Time `json:"last_pricelist_sync"`
IsOnline bool `json:"is_online"`
ComponentsCount int64 `json:"components_count"`
PricelistsCount int64 `json:"pricelists_count"`
ServerPricelists int `json:"server_pricelists"`
NeedComponentSync bool `json:"need_component_sync"`
NeedPricelistSync bool `json:"need_pricelist_sync"`
}
// GetStatus returns current sync status
@@ -79,14 +87,14 @@ func (h *SyncHandler) GetStatus(c *gin.Context) {
needComponentSync := h.localDB.NeedComponentSync(24)
c.JSON(http.StatusOK, SyncStatusResponse{
LastComponentSync: lastComponentSync,
LastPricelistSync: lastPricelistSync,
IsOnline: isOnline,
ComponentsCount: componentsCount,
PricelistsCount: pricelistsCount,
ServerPricelists: serverPricelists,
NeedComponentSync: needComponentSync,
NeedPricelistSync: needPricelistSync,
LastComponentSync: lastComponentSync,
LastPricelistSync: lastPricelistSync,
IsOnline: isOnline,
ComponentsCount: componentsCount,
PricelistsCount: pricelistsCount,
ServerPricelists: serverPricelists,
NeedComponentSync: needComponentSync,
NeedPricelistSync: needPricelistSync,
})
}
@@ -169,11 +177,11 @@ func (h *SyncHandler) SyncPricelists(c *gin.Context) {
// SyncAllResponse represents result of full sync
type SyncAllResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
ComponentsSynced int `json:"components_synced"`
PricelistsSynced int `json:"pricelists_synced"`
Duration string `json:"duration"`
Success bool `json:"success"`
Message string `json:"message"`
ComponentsSynced int `json:"components_synced"`
PricelistsSynced int `json:"pricelists_synced"`
Duration string `json:"duration"`
}
// SyncAll syncs both components and pricelists
@@ -216,8 +224,8 @@ func (h *SyncHandler) SyncAll(c *gin.Context) {
if err != nil {
slog.Error("pricelist sync failed during full sync", "error", err)
c.JSON(http.StatusInternalServerError, gin.H{
"success": false,
"error": "Pricelist sync failed: " + err.Error(),
"success": false,
"error": "Pricelist sync failed: " + err.Error(),
"components_synced": componentsSynced,
})
return
@@ -294,9 +302,9 @@ func (h *SyncHandler) GetPendingChanges(c *gin.Context) {
// SyncInfoResponse represents sync information
type SyncInfoResponse struct {
LastSyncAt *time.Time `json:"last_sync_at"`
IsOnline bool `json:"is_online"`
ErrorCount int `json:"error_count"`
LastSyncAt *time.Time `json:"last_sync_at"`
IsOnline bool `json:"is_online"`
ErrorCount int `json:"error_count"`
Errors []SyncError `json:"errors,omitempty"`
}