From 255ed2a4723fa31c216b4a5cfb758a71f8fbaac5 Mon Sep 17 00:00:00 2001 From: mpl Date: Sat, 21 Apr 2012 22:41:40 +0200 Subject: [PATCH] support arrays as comma separated values in wizard Change-Id: I44de427c91859ee23c230f4649d5f27a1502370b --- pkg/server/wizard.go | 60 ++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/pkg/server/wizard.go b/pkg/server/wizard.go index 6120618c1..e8e602c62 100644 --- a/pkg/server/wizard.go +++ b/pkg/server/wizard.go @@ -24,6 +24,7 @@ import ( "os" "reflect" "strconv" + "strings" "camlistore.org/pkg/auth" "camlistore.org/pkg/blobserver" @@ -46,6 +47,19 @@ func newSetupFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handl return wizard, nil } +func jsonPrint(i interface{}) (s string) { + switch ei := i.(type) { + case []interface{}: + for _, v := range ei { + s += jsonPrint(v) + "," + } + s = strings.TrimRight(s, ",") + default: + return fmt.Sprintf("%v", i) + } + return s +} + func sendWizard(req *http.Request, rw http.ResponseWriter, hasChanged bool) { config, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { @@ -53,15 +67,19 @@ func sendWizard(req *http.Request, rw http.ResponseWriter, hasChanged bool) { return } + funcMap := template.FuncMap{ + "jsonPrint": jsonPrint, + } + body := `
` - body += `{{range $k,$v := .}}{{printf "%v" $k}}
{{end}}` + body += `{{range $k,$v := .}}{{printf "%v" $k}}
{{end}}` body += `
` if hasChanged { body += `

Configuration succesfully rewritten

` } - tmpl, err := template.New("wizard").Parse(topWizard + body + bottomWizard) + tmpl, err := template.New("wizard").Funcs(funcMap).Parse(topWizard + body + bottomWizard) if err != nil { httputil.ServerError(rw, err) return @@ -101,34 +119,28 @@ func handleSetupChange(req *http.Request, rw http.ResponseWriter) { } hasChanged := false + var el interface{} for k, v := range req.Form { if _, ok := hilevelConf[k]; !ok { continue } - // TODO(mpl): this only works for single elements (so it actually fails for - // replicateTo already because it's supposed to be an array). - // so the question is: - // Do we allow the high level conf file to get more complicated than that? - // i.e, do we allow some fields to be arrays, maps, etc? it looks like we need - // that at least for replicateTo, which is an empty array for now. So, we could - // 1) only allow fields to be simple elements (bools, ints, or strings), but that - // limits the user's possibilities with that wizard - // 2) or allow input fields to be valid json syntax so the user can input arrays - // and such. But then it's not such a userfriendly wizard anymore. - // 3) lose the genericity and expect the type depending on the key. i.e, I know - // I'm supposed to get an array for replicateTo, so I know I'm supposed to get a - // comma, or space, or whatever separated list of elements in that field. - // 3) something else altogether? - var el interface{} - if b, err := strconv.ParseBool(v[0]); err == nil { - el = b - } else { - if i, err := strconv.ParseInt(v[0], 0, 32); err == nil { - el = i - } else { - el = v[0] + switch k { + case "TLS": + b, err := strconv.ParseBool(v[0]) + if err != nil { + httputil.ServerError(rw, fmt.Errorf("TLS field expects a boolean value")) } + el = b + case "replicateTo": + els := []string{} + if len(v[0]) > 0 { + vals := strings.Split(v[0], ",") + els = append(els, vals...) + } + el = els + default: + el = v[0] } if reflect.DeepEqual(hilevelConf[k], el) { continue