Introduce web.FieldErrors for server-side per-field messages. Update templates to render is-invalid/invalid-feedback and add a fieldErr template helper that scopes errors to a specific form instance. Update operator handlers to validate inputs, populate FieldErrors, and render form-specific error state; add a no-op fieldErr stub to fedwiki partials so parsing succeeds.
47 lines
1.7 KiB
Go
47 lines
1.7 KiB
Go
// Package web holds small, framework-agnostic helpers shared across HTTP
|
|
// handlers — things that don't fit cleanly in `server` (because they have
|
|
// no handler-specific state) and shouldn't pull in domain dependencies.
|
|
package web
|
|
|
|
// FieldErrors maps form-field names to human-readable error messages.
|
|
//
|
|
// Convention per docs/operator-ux-conventions.md §6: every form that mutates
|
|
// revalidates server-side and renders field-level errors. Handler builds a
|
|
// FieldErrors map during validation; on failure returns 422 with the form
|
|
// partial + populated map. Templates render `is-invalid` + `<div class=
|
|
// "invalid-feedback">` per field by looking the field name up in the map.
|
|
//
|
|
// Templates read it with `{{ index .FieldErrors "field_name" }}`, which
|
|
// returns the empty string if the field has no error (`with` and `if`
|
|
// branch on that cleanly).
|
|
type FieldErrors map[string]string
|
|
|
|
// New returns an empty FieldErrors map ready to populate.
|
|
func New() FieldErrors {
|
|
return make(FieldErrors)
|
|
}
|
|
|
|
// Set records an error for one field. Multiple calls with the same field
|
|
// keep only the last message — the convention is one concise, actionable
|
|
// message per field, not a list.
|
|
func (e FieldErrors) Set(field, msg string) {
|
|
e[field] = msg
|
|
}
|
|
|
|
// Get returns the error for one field, or empty string if there is none.
|
|
func (e FieldErrors) Get(field string) string {
|
|
return e[field]
|
|
}
|
|
|
|
// Has reports whether a specific field has an error.
|
|
func (e FieldErrors) Has(field string) bool {
|
|
_, ok := e[field]
|
|
return ok
|
|
}
|
|
|
|
// Any reports whether any field has an error. Use this as the handler's
|
|
// branch point: `if errs.Any() { ...return 422... }`.
|
|
func (e FieldErrors) Any() bool {
|
|
return len(e) > 0
|
|
}
|