diff --git a/hub/internal/web/configs.go b/hub/internal/web/configs.go index b3d3c82..07022f0 100644 --- a/hub/internal/web/configs.go +++ b/hub/internal/web/configs.go @@ -421,25 +421,43 @@ func (s *Server) handleCustomerUnified(w http.ResponseWriter, r *http.Request, c } } +// configFormView is the render model of the customer config form — consumed by the standalone +// config_form.html chrome AND embedded in the customer page's Edit tab as .ConfigForm +// (v0.48.0 edit-a; the hostDetailData/host_detail_body pattern). +type configFormView struct { + IsNew bool + Config *store.CustomerConfig + Overrides map[string]interface{} + ActiveNav string + Error string + CSRFField template.HTML + PBSDR pbsDRView +} + +// configFormData assembles the config form's view model. overrides carries SUBMITTED form values +// for the validation-error re-render (typed values must survive — B3); pass nil to fall back to +// the STORED cfg.ConfigJSON (the normal read path). +func (s *Server) configFormData(r *http.Request, isNew bool, cfg *store.CustomerConfig, overrides map[string]interface{}, errMsg string) configFormView { + if overrides == nil { + json.Unmarshal([]byte(cfg.ConfigJSON), &overrides) + } + if overrides == nil { + overrides = make(map[string]interface{}) + } + return configFormView{ + IsNew: isNew, + Config: cfg, + Overrides: overrides, + ActiveNav: "configs", + Error: errMsg, + CSRFField: s.csrfField(r), + PBSDR: s.pbsDRViewFor(cfg.CustomerID), + } +} + // handleConfigNewForm shows the form to create a new customer config. func (s *Server) handleConfigNewForm(w http.ResponseWriter, r *http.Request) { - data := struct { - IsNew bool - Config *store.CustomerConfig - Overrides map[string]interface{} - ActiveNav string - Error string - CSRFField template.HTML - PBSDR pbsDRView - }{ - IsNew: true, - Config: &store.CustomerConfig{}, - Overrides: make(map[string]interface{}), - ActiveNav: "configs", - CSRFField: s.csrfField(r), - PBSDR: s.pbsDRViewFor(""), - } - s.templates.ExecuteTemplate(w, "config_form.html", data) + s.renderConfigForm(w, r, true, &store.CustomerConfig{}, nil, "") } // handleConfigCreate processes the form submission to create a new config. @@ -528,26 +546,7 @@ func (s *Server) handleConfigEditForm(w http.ResponseWriter, r *http.Request, cu return } - var overrides map[string]interface{} - json.Unmarshal([]byte(cfg.ConfigJSON), &overrides) - - data := struct { - IsNew bool - Config *store.CustomerConfig - Overrides map[string]interface{} - ActiveNav string - Error string - CSRFField template.HTML - PBSDR pbsDRView - }{ - IsNew: false, - Config: cfg, - Overrides: overrides, - ActiveNav: "configs", - CSRFField: s.csrfField(r), - PBSDR: s.pbsDRViewFor(customerID), - } - s.templates.ExecuteTemplate(w, "config_form.html", data) + s.renderConfigForm(w, r, false, cfg, nil, "") } // handleConfigUpdate processes the edit form submission. @@ -965,29 +964,11 @@ func (s *Server) handleCreateConfigFromReport(w http.ResponseWriter, r *http.Req http.Redirect(w, r, "/configs/"+customerID+"/edit", http.StatusSeeOther) } -// renderConfigForm is a helper to re-render the form with an error. +// renderConfigForm renders the STANDALONE config form page (chrome + config_form_body) — the +// create flow and the validation-error re-render. The customer page's Edit tab embeds the same +// body via configFormData directly. func (s *Server) renderConfigForm(w http.ResponseWriter, r *http.Request, isNew bool, cfg *store.CustomerConfig, overrides map[string]interface{}, errMsg string) { - if overrides == nil { - overrides = make(map[string]interface{}) - } - data := struct { - IsNew bool - Config *store.CustomerConfig - Overrides map[string]interface{} - ActiveNav string - Error string - CSRFField template.HTML - PBSDR pbsDRView - }{ - IsNew: isNew, - Config: cfg, - Overrides: overrides, - ActiveNav: "configs", - Error: errMsg, - CSRFField: s.csrfField(r), - PBSDR: s.pbsDRViewFor(cfg.CustomerID), - } - s.templates.ExecuteTemplate(w, "config_form.html", data) + s.templates.ExecuteTemplate(w, "config_form.html", s.configFormData(r, isNew, cfg, overrides, errMsg)) } // buildConfigJSON builds the config_json from optional form fields. diff --git a/hub/internal/web/templates/config_form.html b/hub/internal/web/templates/config_form.html index cd2a994..5afb244 100644 --- a/hub/internal/web/templates/config_form.html +++ b/hub/internal/web/templates/config_form.html @@ -4,7 +4,7 @@ Felhom Hub — {{if .IsNew}}Add Customer{{else}}Edit {{.Config.CustomerID}}{{end}} - + {{template "icon_sprite"}} @@ -28,200 +28,9 @@
{{.Error}}
{{end}} -
- {{.CSRFField}} -
-

Customer Identity

-
-
- - - {{if .IsNew}}Letters, numbers, dots, hyphens only{{end}} -
-
- - -
-
- - -
-
- - -
-
-
- -
-

Infrastructure

-
-
- - -
-
- - - Szükséges jogosultságok: Zone DNS:Edit (ACME), Zone WAF:Edit (geo-korlátozás) -
-
-
- -
-

Git Sync

-

Opcionális — csak privát alkalmazás-katalógushoz. A verziófrissítés enélkül is működik.

-
-
- - -
-
- - -
-
-
- -
-

Hibakeresési mód (fejlesztői)

-
-
- - Bekapcsolva a vezérlő újraindul a következő ciklusban; a menü: https://felhom.<domain>/debug. Tesztelés után kapcsold ki. -
-
-
- -
-

Offsite backup

-
-
- -
-
- - -
-
- - -
-
- - -
-
- {{with .Overrides}}{{with index . "offsite"}}{{if index . "host"}} -

Provisioned: {{index . "user"}}@{{index . "host"}}:{{index . "repo_path"}} — the transient password is delivered to the controller once (never shown here).

- - - {{if eq (index . "type") "shared"}} - - - - {{end}} - {{end}}{{end}}{{end}} -
- -
-

PBS DR tier (ep0)

-
-
- - {{if not .PBSDR.Supported}} - Not configured on this hub (no tenantsync key) — enabling will fail until it is. - {{else if .PBSDR.NoHost}} - No host enrolled for this customer yet — enabling fails until the agent enrolls and reports its WG key. - {{end}} -
-
- - - The storage-entry id the agent creates on the box. Default felhom-pbs; the demo host's adopted manual entry is felhom-offsite. -
-
- {{if .PBSDR.Provisioned}} -

Provisioned: namespace {{.PBSDR.Namespace}}, token {{.PBSDR.TokenID}} (host {{.PBSDR.HostID}}) — the token secret is delivered to the host agent once (never shown here).

- - - {{end}} -
- -
- - Cancel - -
-
- + {{/* v0.48.0 edit-a: the form body is shared with the customer page's Edit tab — + one sub-template, two render surfaces (the host_detail_body pattern). */}} + {{template "config_form_body" .}}