{{/* Tell Intellij/GoLand to enable the autocompletion based on the *gen.Graph type. */}} {{/* gotype: entgo.io/ent/entc/gen.Graph */}} {{ define "admin/handler" }} // Code generated by ent, DO NOT EDIT. {{- $pkg := base $.Config.Package }} package admin import ( "fmt" "net/url" "strconv" "entgo.io/ent/dialect/sql" "github.com/labstack/echo/v4" "{{ $.Config.Package }}" {{- range $n := $.Nodes }} "{{ $.Config.Package }}/{{ $n.Package }}" {{- end }} ) const dateTimeFormat = "2006-01-02T15:04:05" const dateTimeFormatNoSeconds = "2006-01-02T15:04" type Handler struct { client *{{ $pkg }}.Client Config HandlerConfig } func NewHandler(client *{{ $pkg }}.Client, cfg HandlerConfig) *Handler { return &Handler{ client: client, Config: cfg, } } func (h *Handler) Create(ctx echo.Context, entityType EntityType) error { switch entityType.(type) { {{- range $n := $.Nodes }} case *{{ $n.Name }}: return h.{{ $n.Name }}Create(ctx) {{- end }} default: return fmt.Errorf("unsupported entity type: %s", entityType) } } func (h *Handler) Get(ctx echo.Context, entityType EntityType, id int) (url.Values, error) { switch entityType.(type) { {{- range $n := $.Nodes }} case *{{ $n.Name }}: return h.{{ $n.Name }}Get(ctx, id) {{- end }} default: return nil, fmt.Errorf("unsupported entity type: %s", entityType) } } func (h *Handler) Delete(ctx echo.Context, entityType EntityType, id int) error { switch entityType.(type) { {{- range $n := $.Nodes }} case *{{ $n.Name }}: return h.{{ $n.Name }}Delete(ctx, id) {{- end }} default: return fmt.Errorf("unsupported entity type: %s", entityType) } } func (h *Handler) Update(ctx echo.Context, entityType EntityType, id int) error { switch entityType.(type) { {{- range $n := $.Nodes }} case *{{ $n.Name }}: return h.{{ $n.Name }}Update(ctx, id) {{- end }} default: return fmt.Errorf("unsupported entity type: %s", entityType) } } func (h *Handler) List(ctx echo.Context, entityType EntityType) (*EntityList, error) { switch entityType.(type) { {{- range $n := $.Nodes }} case *{{ $n.Name }}: return h.{{ $n.Name }}List(ctx) {{- end }} default: return nil, fmt.Errorf("unsupported entity type: %s", entityType) } } {{ range $n := $.Nodes }} func (h *Handler) {{ $n.Name }}Create(ctx echo.Context) error { var payload {{ $n.Name }} if err := h.bind(ctx, &payload); err != nil { return err } op := h.client.{{ $n.Name }}.Create() {{- range $f := $n.Fields }} {{- if (fieldIsPointer $f) }} if payload.{{ fieldName $f.Name }} != nil { op.Set{{ fieldName $f.Name }}(*payload.{{ fieldName $f.Name }}) } {{- else }} op.Set{{ fieldName $f.Name }}(payload.{{ fieldName $f.Name }}) {{- end }} {{- end }} _, err := op.Save(ctx.Request().Context()) return err } func (h *Handler) {{ $n.Name }}Update(ctx echo.Context, id int) error { entity, err := h.client.{{ $n.Name }}.Get(ctx.Request().Context(), id) if err != nil { return err } var payload {{ $n.Name }} if err = h.bind(ctx, &payload); err != nil { return err } op := entity.Update() {{- range $f := $n.Fields }} {{- if not $f.Immutable }} {{- if $f.Sensitive }} if payload.{{ fieldName $f.Name }} != nil { op.Set{{ fieldName $f.Name }}(*payload.{{ fieldName $f.Name }}) } {{- else if $f.Nillable }} op.SetNillable{{ fieldName $f.Name }}(payload.{{ fieldName $f.Name }}) {{- else if $f.Optional }} if payload.{{ fieldName $f.Name }} == nil { op.Clear{{ fieldName $f.Name }}() } else { op.Set{{ fieldName $f.Name }}(*payload.{{ fieldName $f.Name }}) } {{- else if (fieldIsPointer $f) }} if payload.{{ fieldName $f.Name }} == nil { var empty {{ $f.Type }} op.Set{{ fieldName $f.Name }}(empty) } else { op.Set{{ fieldName $f.Name }}(*payload.{{ fieldName $f.Name }}) } {{- else }} op.Set{{ fieldName $f.Name }}(payload.{{ fieldName $f.Name }}) {{- end }} {{- end }} {{- end }} _, err = op.Save(ctx.Request().Context()) return err } func (h *Handler) {{ $n.Name }}Delete(ctx echo.Context, id int) error { return h.client.{{ $n.Name }}.DeleteOneID(id). Exec(ctx.Request().Context()) } func (h *Handler) {{ $n.Name }}List(ctx echo.Context) (*EntityList, error) { page, offset := h.getPageAndOffset(ctx) res, err := h.client.{{ $n.Name }}. Query(). Limit(h.Config.ItemsPerPage+1). Offset(offset). Order({{ $n.Package }}.ByID(sql.OrderDesc())). All(ctx.Request().Context()) if err != nil { return nil, err } list := &EntityList{ Columns: []string{ {{- range $f := $n.Fields }} {{- if not $f.Sensitive }} "{{ fieldLabel $f.Name }}", {{- end }} {{- end }} }, Entities: make([]EntityValues, 0, len(res)), Page: page, HasNextPage: len(res) > h.Config.ItemsPerPage, } for i := 0; i <= len(res)-1; i++ { list.Entities = append(list.Entities, EntityValues{ ID: res[i].ID, Values: []string{ {{- range $f := $n.Fields }} {{- if not $f.Sensitive }} {{- if eq $f.Type.String "string" }} res[i].{{ fieldName $f.Name }}, {{- else if eq $f.Type.String "time.Time" }} res[i].{{ fieldName $f.Name }}.Format(h.Config.TimeFormat), {{- else }} fmt.Sprint(res[i].{{ fieldName $f.Name }}), {{- end }} {{- end }} {{- end }} }, }) } return list, err } func (h *Handler) {{ $n.Name }}Get(ctx echo.Context, id int) (url.Values, error) { entity, err := h.client.{{ $n.Name }}.Get(ctx.Request().Context(), id) if err != nil { return nil, err } v := url.Values{} {{- range $f := $n.Fields }} {{- if and (not $f.Sensitive) (not $f.Immutable) }} {{- if eq $f.Type.String "string" }} v.Set("{{ $f.Name }}", entity.{{ fieldName $f.Name }}) {{- else if eq $f.Type.String "time.Time" }} v.Set("{{ $f.Name }}", entity.{{ fieldName $f.Name }}.Format(dateTimeFormat)) {{- else }} v.Set("{{ $f.Name }}", fmt.Sprint(entity.{{ fieldName $f.Name }})) {{- end }} {{- end }} {{- end }} return v, err } {{ end }} func (h *Handler) getPageAndOffset(ctx echo.Context) (int, int) { if page, err := strconv.Atoi(ctx.QueryParam(h.Config.PageQueryKey)); err == nil { if page > 1 { return page, (page-1) * h.Config.ItemsPerPage } } return 1, 0 } func (h *Handler) bind(ctx echo.Context, entity any) error { // Echo requires some pre-processing of form values to avoid problems. for k, v := range ctx.Request().Form { // Remove empty field values so Echo's bind does not fail when trying to parse things like // times, etc. if len(v) == 1 && len(v[0]) == 0 { delete(ctx.Request().Form, k) continue } // Echo expects datetime values to be in a certain format but that does not align with the datetime-local // HTML form element format, so we will attempt to convert it here. for _, format := range []string{dateTimeFormatNoSeconds, dateTimeFormat} { if t, err := time.Parse(format, v[0]); err == nil { ctx.Request().Form[k][0] = t.Format(time.RFC3339) break } } } return ctx.Bind(entity) } {{ end }}