feat(hub): Configuration page, asset seedOrUpdate, English UI
- Add Configuration page with "Refresh Assets" button - Replace seedIfEmpty with seedOrUpdate (SHA-256 compare on startup) - Translate all Hungarian text on Apps pages to English - Add Configuration tab to all template navigation - Expand isAssetFile to match favicon patterns - Add felhom-logo.svg to website assets for the pipeline Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/assets"
|
||||
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
@@ -38,6 +39,7 @@ type Server struct {
|
||||
staleThreshold time.Duration
|
||||
versionChecker *VersionChecker
|
||||
templateFetcher *TemplateFetcher
|
||||
assetsMgr *assets.Manager
|
||||
|
||||
sessions map[string]*hubSession
|
||||
sessionsMu sync.RWMutex
|
||||
@@ -113,6 +115,11 @@ func (s *Server) SetTemplateFetcher(tf *TemplateFetcher) {
|
||||
s.templateFetcher = tf
|
||||
}
|
||||
|
||||
// SetAssetManager sets the asset manager for the Configuration page (optional).
|
||||
func (s *Server) SetAssetManager(am *assets.Manager) {
|
||||
s.assetsMgr = am
|
||||
}
|
||||
|
||||
// ServeHTTP routes web requests.
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Path
|
||||
@@ -138,6 +145,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/javascript")
|
||||
w.Header().Set("Cache-Control", "public, max-age=86400")
|
||||
w.Write(chartJS)
|
||||
case path == "/configuration":
|
||||
if r.Method == http.MethodPost {
|
||||
s.handleConfigurationAction(w, r)
|
||||
} else {
|
||||
s.handleConfiguration(w, r)
|
||||
}
|
||||
case path == "/apps" || path == "/apps/":
|
||||
s.handleApps(w, r)
|
||||
case strings.HasPrefix(path, "/apps/") && strings.HasSuffix(path, "/reset-telemetry"):
|
||||
@@ -606,3 +619,48 @@ func statusColor(status string) string {
|
||||
func statusIcon(status string) string {
|
||||
return "●"
|
||||
}
|
||||
|
||||
// handleConfiguration renders the Configuration page.
|
||||
func (s *Server) handleConfiguration(w http.ResponseWriter, r *http.Request) {
|
||||
csrfToken := s.getCSRFToken(r)
|
||||
|
||||
assetCount := 0
|
||||
assetLastSync := ""
|
||||
if s.assetsMgr != nil {
|
||||
assetCount = s.assetsMgr.FileCount()
|
||||
if m := s.assetsMgr.GetManifest(); m != nil {
|
||||
assetLastSync = m.Generated
|
||||
}
|
||||
}
|
||||
|
||||
data := map[string]interface{}{
|
||||
"CSRFToken": csrfToken,
|
||||
"AssetCount": assetCount,
|
||||
"AssetLastSync": assetLastSync,
|
||||
"Flash": r.URL.Query().Get("flash"),
|
||||
}
|
||||
if err := s.templates.ExecuteTemplate(w, "configuration.html", data); err != nil {
|
||||
s.logger.Printf("[ERROR] configuration.html template: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// handleConfigurationAction handles POST actions on the Configuration page.
|
||||
func (s *Server) handleConfigurationAction(w http.ResponseWriter, r *http.Request) {
|
||||
action := r.FormValue("action")
|
||||
switch action {
|
||||
case "refresh_assets":
|
||||
if s.assetsMgr == nil {
|
||||
http.Redirect(w, r, "/configuration?flash=assets_not_configured", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
if err := s.assetsMgr.ReSeed(); err != nil {
|
||||
s.logger.Printf("[ERROR] Asset re-seed failed: %v", err)
|
||||
http.Redirect(w, r, "/configuration?flash=assets_error", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
s.logger.Printf("[INFO] Manual asset re-seed completed")
|
||||
http.Redirect(w, r, "/configuration?flash=assets_refreshed", http.StatusSeeOther)
|
||||
default:
|
||||
http.Redirect(w, r, "/configuration", http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user