Add app detail/info pages with optional config support
- New route: GET /apps/{slug} renders info page with use cases, setup guide, prerequisites
- New API: POST /api/stacks/{name}/optional-config for updating optional env vars
- New structs: AppInfo, OptionalConfigGroup, OptionalConfigField in metadata.go
- UpdateOptionalConfig saves to app.yaml and restarts deployed stacks with new env vars
- Info page template with hero section, screenshots, info cards, optional config form
- Navigation: stack cards now link to /apps/{slug}, deploy page has "Részletek" link
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -165,6 +165,16 @@ func (s *Server) loadTemplates() {
|
||||
}
|
||||
return r
|
||||
},
|
||||
"screenshotURL": func(slug string, index int) string {
|
||||
return s.cfg.AppScreenshotURL(slug, index)
|
||||
},
|
||||
"seq": func(n int) []int {
|
||||
result := make([]int, n)
|
||||
for i := range result {
|
||||
result[i] = i + 1
|
||||
}
|
||||
return result
|
||||
},
|
||||
}
|
||||
|
||||
s.tmpl = template.Must(template.New("").Funcs(funcMap).Parse(allTemplates))
|
||||
@@ -475,16 +485,37 @@ func (s *Server) serveAsset(w http.ResponseWriter, r *http.Request, filename str
|
||||
http.ServeFile(w, r, path)
|
||||
}
|
||||
|
||||
func (s *Server) appDetailHandler(w http.ResponseWriter, r *http.Request, slug string) {
|
||||
func (s *Server) appDetailHandler(w http.ResponseWriter, _ *http.Request, slug string) {
|
||||
var found *stacks.Stack
|
||||
for _, stack := range s.stackMgr.GetStacks() {
|
||||
if stack.Meta.Slug == slug {
|
||||
// Always redirect to deploy page — it has a read-only mode for
|
||||
// deployed apps showing current settings, plus the external link
|
||||
http.Redirect(w, r, "/stacks/"+stack.Name+"/deploy", http.StatusFound)
|
||||
return
|
||||
found = &stack
|
||||
break
|
||||
}
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
if found == nil {
|
||||
http.NotFound(w, nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Load current optional config values from app.yaml
|
||||
currentValues := make(map[string]string)
|
||||
if appCfg := s.stackMgr.LoadAppConfigByName(found.Name); appCfg != nil {
|
||||
for k, v := range appCfg.Env {
|
||||
currentValues[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
data := s.baseData("stacks", found.Meta.DisplayName)
|
||||
data["Stack"] = found
|
||||
data["Meta"] = found.Meta
|
||||
data["AppInfo"] = found.Meta.AppInfo
|
||||
data["OptionalConfig"] = found.Meta.OptionalConfig
|
||||
data["CurrentValues"] = currentValues
|
||||
data["HasAppInfo"] = found.Meta.HasAppInfo()
|
||||
data["HasOptionalConfig"] = found.Meta.HasOptionalConfig()
|
||||
|
||||
s.render(w, "app_info", data)
|
||||
}
|
||||
|
||||
func (s *Server) renderLogin(w http.ResponseWriter, errorMsg string) {
|
||||
|
||||
Reference in New Issue
Block a user