personal-site/pkg/ui/forms/admin_entity.go
2025-04-20 13:32:23 -04:00

125 lines
2.9 KiB
Go

package forms
import (
"net/http"
"net/url"
"entgo.io/ent/entc/load"
"entgo.io/ent/schema/field"
"github.com/mikestefanello/pagoda/ent/admin"
"github.com/mikestefanello/pagoda/pkg/routenames"
"github.com/mikestefanello/pagoda/pkg/ui"
. "github.com/mikestefanello/pagoda/pkg/ui/components"
. "maragu.dev/gomponents"
. "maragu.dev/gomponents/html"
)
func AdminEntity(r *ui.Request, schema *load.Schema, values url.Values) Node {
// TODO inline validation?
isNew := values == nil
nodes := make(Group, 0)
getValue := func(name string) string {
// Values in the submitted form take precedence.
if value := r.Context.FormValue(name); value != "" {
return value
}
// Fallback to the entity's values, if being edited.
if values != nil && len(values[name]) > 0 {
return values[name][0]
}
return ""
}
// Attempt to add form elements for all editable entity fields.
for _, f := range schema.Fields {
// TODO cardinality?
if !isNew && f.Immutable {
continue
}
switch f.Info.Type {
case field.TypeString:
p := InputFieldParams{
Name: f.Name,
InputType: "text",
Label: admin.FieldLabel(f.Name),
Value: getValue(f.Name),
}
if f.Sensitive {
p.InputType = "password"
if !isNew {
p.Placeholder = "*****"
p.Help = "SENSITIVE: This field will only be updated if a value is provided."
}
}
nodes = append(nodes, InputField(p))
case field.TypeTime:
nodes = append(nodes, InputField(InputFieldParams{
Name: f.Name,
InputType: "datetime-local",
Label: admin.FieldLabel(f.Name),
Value: getValue(f.Name),
}))
case field.TypeInt, field.TypeInt8, field.TypeInt16, field.TypeInt32, field.TypeInt64,
field.TypeUint, field.TypeUint8, field.TypeUint16, field.TypeUint32, field.TypeUint64,
field.TypeFloat32, field.TypeFloat64:
nodes = append(nodes, InputField(InputFieldParams{
Name: f.Name,
InputType: "number",
Label: admin.FieldLabel(f.Name),
Value: getValue(f.Name),
}))
case field.TypeBool:
nodes = append(nodes, Checkbox(CheckboxParams{
Name: f.Name,
Label: admin.FieldLabel(f.Name),
Checked: getValue(f.Name) == "true",
}))
case field.TypeEnum:
options := make([]Choice, 0, len(f.Enums)+1)
if f.Optional {
options = append(options, Choice{
Label: "-",
Value: "",
})
}
for _, enum := range f.Enums {
options = append(options, Choice{
Label: enum.V,
Value: enum.V,
})
}
nodes = append(nodes, SelectList(OptionsParams{
Name: f.Name,
Label: admin.FieldLabel(f.Name),
Value: getValue(f.Name),
Options: options,
}))
default:
nodes = append(nodes, P(Textf("%s not supported", f.Name)))
}
}
return Form(
Method(http.MethodPost),
nodes,
ControlGroup(
FormButton("is-primary", "Submit"),
ButtonLink(
r.Path(routenames.AdminEntityList(schema.Name)),
"is-secondary",
"Cancel",
),
),
CSRF(r),
)
}